Skip to main content

์ถ”์ถœ๊ธฐ ์˜ต์…˜

CodeQL CLI๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†Œํ”„ํŠธ์›จ์–ด ํ”„๋กœ์ ํŠธ์—์„œ CodeQL ํ”„๋กœ์„ธ์Šค๋ฅผ ๋กœ์ปฌ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ฐ€ ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‚˜์š”?

CodeQL์€(๋Š”) ๋‹ค์Œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์œ ํ˜•์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • GitHub.com์˜ ํผ๋ธ”๋ฆญ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ, GitHub CodeQL ์‚ฌ์šฉ ์•ฝ๊ด€ ์ฐธ์กฐ
  • GitHub Code Security๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •๋œ GitHub Team์˜ ์กฐ์ง ์†Œ์œ  ๋ฆฌํฌ์ง€ํ† ๋ฆฌ

์ถ”์ถœ๊ธฐ ์ •๋ณด

CodeQL CLI์€(๋Š”) ์ถ”์ถœ๊ธฐ๋ผ๋Š” ํŠน์ˆ˜ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜์—ฌ ์†Œํ”„ํŠธ์›จ์–ด ์‹œ์Šคํ…œ์˜ ์†Œ์Šค ์ฝ”๋“œ์—์„œ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. CodeQL CLI๋ฅผ ํ†ตํ•ด ์ถ”์ถœ๊ธฐ ๊ตฌ์„ฑ ์˜ต์…˜์„ ์„ค์ •ํ•˜์—ฌ ์ถ”์ถœ๊ธฐ์˜ ๋™์ž‘์„ ์‚ฌ์šฉ์ž ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์ •๋ณด

๊ฐ ์ถ”์ถœ๊ธฐ๋Š” ๊ณ ์œ ํ•œ ๊ตฌ์„ฑ ์˜ต์…˜ ์ง‘ํ•ฉ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ํŠน์ • ์ถ”์ถœ๊ธฐ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ํ™•์ธํ•˜๋ ค๋ฉด --format=betterjson ์˜ต์…˜๊ณผ ํ•จ๊ป˜ codeql resolve languages ๋˜๋Š” codeql resolve extractor๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. betterjson ์ถœ๋ ฅ ํ˜•์‹์€ ์ถ”์ถœ๊ธฐ์˜ ๋ฃจํŠธ ๊ฒฝ๋กœ์™€ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. codeql resolve extractor --format=betterjson ์ถœ๋ ฅ์€ ํ”ํžˆ ๋‹ค์Œ ์˜ˆ์™€ ๊ฐ™์ด ํ˜•์‹์ด ์ง€์ •๋ฉ๋‹ˆ๋‹ค.

{
    "extractor_root" : "/home/user/codeql/java",
    "extractor_options" : {
        "option1" : {
            "title" : "Java extractor option 1",
            "description" : "An example string option for the Java extractor.",
            "type" : "string",
            "pattern" : "[a-z]+"
        },
        "group1" : {
            "title" : "Java extractor group 1",
            "description" : "An example option group for the Java extractor.",
            "type" : "object",
            "properties" : {
                "option2" : {
                    "title" : "Java extractor option 2",
                    "description" : "An example array option for the Java extractor",
                    "type" : "array",
                    "pattern" : "[1-9][0-9]*"
                }
            }
        }
    }
}

์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์ด๋ฆ„ ๋ฐ ์„ค๋ช…์€ extractor_options ์•„๋ž˜์— ๋‚˜์—ด๋ฉ๋‹ˆ๋‹ค. ๊ฐ ์˜ต์…˜์— ๋Œ€ํ•ด ๋‹ค์Œ ํ•„๋“œ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  • title(ํ•„์ˆ˜): ์˜ต์…˜์˜ ์ œ๋ชฉ
  • description(ํ•„์ˆ˜): ์˜ต์…˜์— ๋Œ€ํ•œ ์„ค๋ช…
  • type(ํ•„์ˆ˜): ์˜ต์…˜์˜ ํ˜•์‹์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • string: ์˜ต์…˜์— ๋‹จ์ผ ๋ฌธ์ž์—ด ๊ฐ’์ด ์žˆ์„ ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • array: ์˜ต์…˜์— ๋ฌธ์ž์—ด ๊ฐ’ ์‹œํ€€์Šค๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • object: ์˜ต์…˜ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์˜ต์…˜ ๋ฐ ์˜ต์…˜ ๊ทธ๋ฃน์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ๊ทธ๋ฃนํ™”์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • pattern(์„ ํƒ ์‚ฌํ•ญ): ์˜ต์…˜์˜ ๋ชจ๋“  ๊ฐ’์ด ์ผ์น˜ํ•ด์•ผ ํ•˜๋Š” ์ •๊ทœ์‹ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์ถ”์ถœ๊ธฐ๋Š” ์ด ์ •๊ทœ์‹ ํŒจํ„ด์—์„œ ํ‘œํ˜„ํ•  ์ˆ˜ ์—†๊ฑฐ๋‚˜ ํ‘œํ˜„ํ•  ์ˆ˜ ์—†๋Š” ์˜ต์…˜ ๊ฐ’์— ์ถ”๊ฐ€ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์„ค๋ช… ํ•„๋“œ ์•„๋ž˜์— ์„ค๋ช…๋ฉ๋‹ˆ๋‹ค.
  • properties(์„ ํƒ ์‚ฌํ•ญ): ์˜ต์…˜ ๊ทธ๋ฃน์˜ ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์ด๋ฆ„์—์„œ ํ•ด๋‹น ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์„ค๋ช…์œผ๋กœ์˜ ๋งต์ž…๋‹ˆ๋‹ค. ์ด ํ•„๋“œ๋Š” ์˜ต์…˜ ๊ทธ๋ฃน์— ๋Œ€ํ•ด์„œ๋งŒ ์กด์žฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด object ์œ ํ˜•์˜ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

์œ„์˜ ์˜ˆ์—์„œ ์ถ”์ถœ๊ธฐ๋Š” ๋‘ ๊ฐ€์ง€ ์˜ต์…˜์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

  • option1์€ [a-z]+์™€ ์ผ์น˜ํ•˜๋Š” ๊ฐ’์„ ๊ฐ–๋Š” string ์˜ต์…˜์ž…๋‹ˆ๋‹ค.
  • group1.option2๋Š” [1-9][0-9]\*์™€ ์ผ์น˜ํ•˜๋Š” ๊ฐ’์„ ๊ฐ–๋Š” array ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

CodeQL CLI๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์„ค์ •

CodeQL CLI๋Š” ์ถ”์ถœ๊ธฐ๋ฅผ ์ง์ ‘ ๋˜๋Š” ๊ฐ„์ ‘์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ํ•˜์œ„ ๋ช…๋ น์˜ ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์„ค์ •์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ช…๋ น์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • codeql database create
  • codeql database start-tracing
  • codeql database trace-command
  • codeql database index-files

์ด๋Ÿฌํ•œ ํ•˜์œ„ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ๋•Œ --extractor-option CLI ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ:

  • codeql database create --extractor-option java.option1=abc ...
  • codeql database start-tracing --extractor-option java.group1.option2=102 ...

--extractor-option์—๋Š” extractor_option_name=extractor_option_value ํ˜•์‹์˜ ์ธ์ˆ˜๊ฐ€ ์ •ํ™•ํžˆ ํ•˜๋‚˜ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. extractor_option_name์€ ์ถ”์ถœ๊ธฐ ์ด๋ฆ„(์ด ์˜ˆ์—์„œ๋Š” java)๊ณผ ๋งˆ์นจํ‘œ, ์ถ”์ถœ๊ธฐ ์˜ต์…˜์˜ ์ด๋ฆ„(์ด ์˜ˆ์—์„œ๋Š” option1 ๋˜๋Š” group1.option2)์ž…๋‹ˆ๋‹ค. extractor_option_value \๋Š” ์ถ”์ถœ๊ธฐ ์˜ต์…˜์— ํ• ๋‹น๋˜๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค. ๊ฐ’์€ ์ถ”์ถœ๊ธฐ ์˜ต์…˜์˜ ์ •๊ทœ์‹ ํŒจํ„ด(์žˆ๋Š” ๊ฒฝ์šฐ)๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•˜๋ฉฐ ์ค„ ๋ฐ”๊ฟˆ ๋ฌธ์ž๋ฅผ ํฌํ•จํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

--extractor-option์„ ์‚ฌ์šฉํ•˜์—ฌ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์€ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.

CodeQL CLI๋Š” ๋™์ผํ•œ ํ˜ธ์ถœ์—์„œ ์—ฌ๋Ÿฌ --extractor-option ์˜ต์…˜์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. string ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์„ค์ •ํ•˜๋ฉด ๋งˆ์ง€๋ง‰ ์˜ต์…˜ ๊ฐ’์ด ์ด์ „์˜ ๋ชจ๋“  ์˜ต์…˜์„ ๋ฎ์–ด์”๋‹ˆ๋‹ค. ๋ฐฐ์—ด ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์„ค์ •ํ•˜๋ฉด ๋ชจ๋“  ์˜ต์…˜ ๊ฐ’์ด ์ˆœ์„œ๋Œ€๋กœ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

์ถ”์ถœ๊ธฐ ์ด๋ฆ„ ์—†์ด ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ:

  • codeql database create --extractor-option option1=abc ...
  • codeql database start-tracing --extractor-option group1.option2=102 ...

์ถ”์ถœ๊ธฐ ์ด๋ฆ„์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ์ง€์ •๋œ ์ด๋ฆ„์œผ๋กœ ์˜ต์…˜์„ ์„ ์–ธํ•˜๋Š” ๋ชจ๋“  ์ถ”์ถœ๊ธฐ์— ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์„ค์ •์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ ์ฒซ ๋ฒˆ์งธ ๋ช…๋ น์€ java ์ถ”์ถœ๊ธฐ ๋ฐ ์˜ต์…˜ option1๊ฐ€ ์žˆ๋Š” ๋ชจ๋“  ์ถ”์ถœ๊ธฐ(์˜ˆ: ํ•ด๋‹น ์ถ”์ถœ๊ธฐ์— option1 ์ถ”์ถœ๊ธฐ ์˜ต์…˜์ด ์žˆ๋Š” ๊ฒฝ์šฐ cpp ์ถ”์ถœ๊ธฐ)์— ๋Œ€ํ•ด ์ถ”์ถœ๊ธฐ ์˜ต์…˜ option1์„(๋ฅผ) abc(์œผ)๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

ํŒŒ์ผ์—์„œ ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ์„ค์ •

ํŒŒ์ผ์„ ํ†ตํ•ด ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. --extractor-option์„ ์ˆ˜๋ฝํ•˜๋Š” CodeQL CLI ํ•˜์œ„ ๋ช…๋ น์€ --extractor-options-file๋„ ์ˆ˜๋ฝํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” YAML ํŒŒ์ผ(ํ™•์žฅ์ž .yaml ๋˜๋Š” .yml) ๋˜๋Š” JSON ํŒŒ์ผ(ํ™•์žฅ์ž .json) ๊ฒฝ๋กœ์— ๋Œ€ํ•œ ํ•„์ˆ˜ ์ธ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ:

  • codeql database create --extractor-options-file options.yml ...
  • codeql database start-tracing --extractor-options-file options.json ...

๊ฐ ์˜ต์…˜ ํŒŒ์ผ์—๋Š” ์ค‘์ฒฉ๋œ ๋งต์˜ ํŠธ๋ฆฌ ๊ตฌ์กฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฃจํŠธ์—๋Š” ์ถ”์ถœ๊ธฐ ๋งต ํ‚ค๊ฐ€ ์žˆ์œผ๋ฉฐ ๊ทธ ์•„๋ž˜์—๋Š” ์ถ”์ถœ๊ธฐ ์ด๋ฆ„์— ํ•ด๋‹นํ•˜๋Š” ์ง€๋„ ํ‚ค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ธ ๋ฒˆ์งธ ์ˆ˜์ค€๋ถ€ํ„ฐ ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ๋ฐ ์˜ต์…˜ ๊ทธ๋ฃน์ด ์žˆ์Šต๋‹ˆ๋‹ค.

JSON:

{
     "extractor" : {
        "java": {
            "option1" : "abc",
            "group1" : {
                "option2" : [ 102 ]
            }
        }
    }
}

YAML:

extractor:
    java:
        option1: "abc"
        group1:
            option2: [ 102 ]

์ถ”์ถœ๊ธฐ ์˜ต์…˜์˜ string ๊ฐ’์€ ๋ฌธ์ž์—ด ๋˜๋Š” ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค(์ถ”๊ฐ€ ์ฒ˜๋ฆฌ ์ „์— ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜๋จ).

์ถ”์ถœ๊ธฐ ์˜ต์…˜์˜ array ๊ฐ’์€ ๋ฌธ์ž์—ด ๋˜๋Š” ์ˆซ์ž์˜ ๋ฐฐ์—ด์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ ๊ทธ๋ฃน(ํ˜•์‹ object)์˜ ๊ฐ’์€ ์ค‘์ฒฉ๋œ ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ๋ฐ ์˜ต์…˜ ๊ทธ๋ฃน์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ๋งต์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ๊ฐ’์€ ์ถ”์ถœ๊ธฐ ์˜ต์…˜์˜ ์ •๊ทœ์‹ ํŒจํ„ด(์žˆ๋Š” ๊ฒฝ์šฐ)๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•˜๋ฉฐ ์ค„ ๋ฐ”๊ฟˆ ๋ฌธ์ž๋ฅผ ํฌํ•จํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์€ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค. ํŠน์ˆ˜ํ•œ __allow_unknown_properties ๋ถ€์šธ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ CodeQL CLI๊ฐ€ ์•Œ ์ˆ˜ ์—†๋Š” ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ๋ฌด์‹œํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ์˜ต์…˜ ํŒŒ์ผ์€ CodeQL CLI๊ฐ€ ๋ชจ๋“  ์•Œ ์ˆ˜ ์—†๋Š” ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ๋ฐ group1 ์•„๋ž˜์˜ ์˜ต์…˜ ๊ทธ๋ฃน์„ ๋ฌด์‹œํ•˜๋„๋ก ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

extractor:
    java:
        option1: "abc"
        group1:
            __allow_unknown_properties: true
            option2: [ 102 ]

--extractor-options-file์€ ์—ฌ๋Ÿฌ ๋ฒˆ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ํ• ๋‹น์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

  1. --extractor-options-file์œผ๋กœ ์ง€์ •ํ•œ ๋ชจ๋“  ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ํŒŒ์ผ์€ ๋ช…๋ น์ค„์— ํ‘œ์‹œ๋˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  2. --extractor-option์œผ๋กœ ์ง€์ •ํ•œ ๋ชจ๋“  ์ถ”์ถœ๊ธฐ ์˜ต์…˜ ํ• ๋‹น์€ ๋ช…๋ น์ค„์— ํ‘œ์‹œ๋˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

--extractor-option์„ ์‚ฌ์šฉํ•˜์—ฌ, --extractor-options-file์„ ์‚ฌ์šฉํ•˜์—ฌ ๋˜๋Š” ์ด ๋‘˜์˜ ๋ช‡ ๊ฐ€์ง€ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ• ๋‹นํ•˜๋Š”์ง€์— ๊ด€๊ณ„์—†์ด ๋™์ผํ•œ ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์„ค์ •ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ž‘์—…์€ ๋™์ผํ•œ ๊ทœ์น™์ด ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. string ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์„ค์ • ํ•˜๋ฉด ๋งˆ์ง€๋ง‰ ์˜ต์…˜ ๊ฐ’์ด ๋ชจ๋“  ์ด์ „ ๊ฐ’์„ ๋ฎ์–ด์”๋‹ˆ๋‹ค. array ์ถ”์ถœ๊ธฐ ์˜ต์…˜์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์„ค์ •ํ•˜๋ฉด ๋ชจ๋“  ์˜ต์…˜ ๊ฐ’์ด ์ˆœ์„œ๋Œ€๋กœ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.