ํ•œ ๊ฐ€์ง€ ์ทจ์•ฝ์ ์— ๋Œ€ํ•ด...

ํ•œ ๊ฐ€์ง€ ์ทจ์•ฝ์ ์— ๋Œ€ํ•ด...

21๋…„ ์ „์ธ 2019๋…„ XNUMX์›” XNUMX์ผ, ๋ฒ„๊ทธ ํ˜„์ƒ๊ธˆ ํ”„๋กœ๊ทธ๋žจ Mail.Ru HackerOne์— ์•„์ฃผ ์ข‹์€ ์‚ฌ๋žŒ์ด ์™”์Šต๋‹ˆ๋‹ค ๋ฒ„๊ทธ ๋ณด๊ณ ์„œ ๋ถ€ํ„ฐ ๋งฅ์‚ฌ๋ฅด. HTTP ๋ฆฌ๋””๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•œ ์›น ๋ฉ”์ผ API ์š”์ฒญ ์ค‘ ํ•˜๋‚˜์˜ POST ๋งค๊ฐœ ๋ณ€์ˆ˜์— 0๋ฐ”์ดํŠธ(ASCII XNUMX)๋ฅผ ๋„์ž…ํ•˜๋ฉด ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๋ฉ”๋ชจ๋ฆฌ ์กฐ๊ฐ์ด ๋ฆฌ๋””๋ ‰์…˜ ๋ฐ์ดํ„ฐ์— ํ‘œ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ์„œ๋ฒ„.

์ด๋Š” ์‹ฌ๊ฐํ•œ ์ทจ์•ฝ์ ์ด๊ธฐ ๋•Œ๋ฌธ์—... ์š”์ฒญ์—๋Š” ์„ธ์…˜ ์ฟ ํ‚ค๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช‡ ์‹œ๊ฐ„ ํ›„, 13๋ฐ”์ดํŠธ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๋Š” ์ž„์‹œ ์ˆ˜์ •์ด ์ด๋ฃจ์–ด์กŒ์Šต๋‹ˆ๋‹ค(๋‚˜์ค‘์— ๋ฐํ˜€์กŒ์ง€๋งŒ ํ—ค๋”๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” CRLF/ASCII 10, XNUMX์„ ์ฃผ์ž…ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์—ฌ์ „ํžˆ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. HTTP ์‘๋‹ต ๋ฐ์ดํ„ฐ์˜ ๊ฒฝ์šฐ ๋œ ์ค‘์š”ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ถˆ์พŒํ•ฉ๋‹ˆ๋‹ค). ๋™์‹œ์— ๋ฒ„๊ทธ์˜ ์›์ธ์„ ์ฐพ์•„ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด ๋ฌธ์ œ๋ฅผ ๋ณด์•ˆ ๋ถ„์„๊ฐ€์™€ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ „๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค.

Mail.ru ๋ฉ”์ผ์€ ๋งค์šฐ ๋ณต์žกํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ, ์˜คํ”ˆ ์†Œ์Šค(๋ชจ๋“  ๋ฌด๋ฃŒ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค)์™€ ์ž์ฒด ๊ฐœ๋ฐœ๋œ ๋‹ค์–‘ํ•œ ํ”„๋ŸฐํŠธ์—”๋“œ/๋ฐฑ์—”๋“œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์‘๋‹ต ์ƒ์„ฑ์— ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” nginx์™€ openresty๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ œ์™ธํ•˜๊ณ  ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— ๋ฌธ์ œ๋ฅผ ํ˜„์ง€ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. ngx.req.set_uri() ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” OpenResty ์Šคํฌ๋ฆฝํŠธ์—์„œ(๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด ์‚ฌ์šฉ๋˜๋ฉฐ ์ •ํ™•ํžˆ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ด์•ผ ํ•˜๋Š” ngx_http_rewrite_module์—์„œ ๋‹ค์‹œ ์ž‘์„ฑํ•˜์—ฌ GET ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ๋„ ๋ฐ”์ดํŠธ ๋˜๋Š” ๋ผ์ธ ํ”ผ๋“œ ์‚ฝ์ž…) ์ž‘๋™ํ•˜์ง€). ๊ฐ€๋Šฅํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ํ•„ํ„ฐ๋ง์„ ์ตœ๋Œ€ํ•œ ์—„๊ฒฉํ•˜๊ฒŒ ์ถ”๊ฐ€ํ–ˆ์œผ๋ฉฐ ํ•„ํ„ฐ๋ง์„ ๊ฒ€์ฆํ•˜์—ฌ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๋ฒกํ„ฐ๋ฅผ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด์šฉ ์œ ์ถœ์„ ์ดˆ๋ž˜ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ๋ฏธ์Šคํ„ฐ๋ฆฌ๋กœ ๋‚จ์•„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๋‹ฌ ํ›„, ๋ฒ„๊ทธ ๋ฆฌํฌํŠธ๋Š” ํ•ด๊ฒฐ๋œ ๋Œ€๋กœ ์ข…๋ฃŒ๋˜์—ˆ๊ณ , ๋ฒ„๊ทธ ์›์ธ ๋ถ„์„์€ ๋” ๋‚˜์€ ๋•Œ๊นŒ์ง€ ์—ฐ๊ธฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

OpenResty๋Š” nginx ๋‚ด๋ถ€์—์„œ Lua ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋งค์šฐ ์ธ๊ธฐ ์žˆ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ด๋ฉฐ ์—ฌ๋Ÿฌ Mail.ru ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์–ผ๋งˆ ํ›„ ๊ทธ๋“ค์€ ์ง„์ •ํ•œ ์ด์œ ์™€ ๊ฐ€๋Šฅํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ดํ•ดํ•˜๊ณ  ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๊ถŒ์žฅ ์‚ฌํ•ญ์„ ์ œ์‹œํ•˜๊ธฐ ์œ„ํ•ด ๋งˆ์นจ๋‚ด ๋‹ค์‹œ ๋Œ์•„์™”์Šต๋‹ˆ๋‹ค. ์†Œ์Šค์ฝ”๋“œ ๋ฐœ๊ตด์— ์ฐธ์—ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ๋‹ˆ์Šค ๋ฐ๋‹ˆ ์†Œํ”„ ะธ ๋‹ˆ์ฝœ๋ผ์ด ์—๋ฅด๋ฏธ์‰ฌํ‚จ. ๊ทธ๊ฒƒ์€ ๋ฐํ˜€์กŒ๋‹ค:

  • nginx์—์„œ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋กœ ๋‹ค์‹œ ์“ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ผ๋ถ€ ๊ตฌ์„ฑ์—์„œ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ ํƒ์ƒ‰(์•„๋งˆ๋„ SSRF)์ด ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์ง€๋งŒ ์ด๋Š” ์•Œ๋ ค์ง„ ์‚ฌ์‹ค์ด๋ฉฐ ๋‹ค์Œ์˜ ์ •์  ๊ตฌ์„ฑ ๋ถ„์„๊ธฐ์— ์˜ํ•ด ๊ฐ์ง€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Nginx ์ฆํญ ะธ ๊ธฐ์‹œ Yandex์—์„œ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค(์˜ˆ, ์ €ํฌ๋„ ๊ทธ๊ฑธ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค). OpenResty๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ด ๊ธฐ๋Šฅ์„ ๋†“์น˜๊ธฐ ์‰ฝ์ง€๋งŒ ์ด๋Š” ๊ตฌ์„ฑ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    ๊ตฌ์„ฑ ์˜ˆ:

    location ~ /rewrite {
        rewrite ^.*$ $arg_x;
    }
    
    location / {
        root html;
        index index.html index.htm;
    }

    ๊ฒฐ๊ณผ

    curl localhost:8337/rewrite?x=/../../../../../../../etc/passwd
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    ...

  • Nginx์—๋Š” ๋‹ค์‹œ ์“ฐ๊ธฐ ๋ผ์ธ์— ๋„ ๋ฐ”์ดํŠธ๊ฐ€ ํฌํ•จ๋œ ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์ผ์œผํ‚ค๋Š” ๋ฒ„๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด nginx๋Š” ๋ผ์ธ์˜ ์ „์ฒด ๊ธธ์ด์— ํ•ด๋‹นํ•˜๋Š” ์ƒˆ๋กœ์šด ๋ฉ”๋ชจ๋ฆฌ ๋ฒ„ํผ๋ฅผ ํ• ๋‹นํ•˜์ง€๋งŒ XNUMX๋ฐ”์ดํŠธ๊ฐ€ ๋ผ์ธ ์ข…๊ฒฐ์ž์ธ line ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ฑฐ๊ธฐ์— ๋ผ์ธ์„ ๋ณต์‚ฌํ•˜๋ฏ€๋กœ ๋ผ์ธ์€ XNUMX๊นŒ์ง€๋งŒ ๋ณต์‚ฌ๋ฉ๋‹ˆ๋‹ค. ๋ฐ”์ดํŠธ; ๋ฒ„ํผ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์—๋Š” ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ƒ์„ธํ•œ ๋ถ„์„์„ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ์—ฌ๊ธฐ์—.

    ๊ตฌ์„ฑ ์˜ˆ(^@ XNUMX๋ฐ”์ดํŠธ)

    
    location ~ /memleak {
        rewrite ^.*$ "^@asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdasdf";
    }
    
    location / {
        root html;
        index index.html index.htm;
    }

    ๊ฒฐ๊ณผ
    curl localhost:8337/secret -vv
    ...
    curl localhost:8337/memleak -vv
    ...
    Location: http://localhost:8337/secret
    ...

  • Nginx๋Š” ์„œ๋น„์Šค ๋ฌธ์ž ์ฃผ์ž…์œผ๋กœ๋ถ€ํ„ฐ GET ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ณดํ˜ธํ•˜๊ณ  ์žฌ์ž‘์„ฑ ์‹œ GET ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ nginx์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•œ ์ฃผ์ž…์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. POST ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋ณดํ˜ธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. OpenResty๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด GET ๋ฐ POST ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชจ๋‘๋กœ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ OpenResty๋ฅผ ํ†ตํ•ด POST ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํŠน์ˆ˜ ๋ฌธ์ž๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

    ๊ตฌ์„ฑ ์˜ˆ:

    location ~ /memleak {
        rewrite_by_lua_block {
            ngx.req.read_body();
            local args, err = ngx.req.get_post_args();
            ngx.req.set_uri( args["url"], true );
        }
    }
    
    location / {
        root html;
        index index.html index.htm;
    }
    

    ๊ฒฐ๊ณผ :

    curl localhost:8337 -d "url=secret" -vv
    ...
    curl localhost:8337 -d "url=%00asdfasdfasdfasdfasdfasdfasdfasdf" -vv
    ...
    Location: http://localhost:8337/{...ะผะพะถะตั‚ ัะพะดะตั€ะถะฐั‚ัŒ secret...}
    ...

์ถ”๊ฐ€ ๋ฐ˜์‘

์ด ๋ฌธ์ œ๋Š” nginx ๋ฐ OpenResty ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋ณด๊ณ ๋˜์—ˆ์œผ๋ฉฐ ๊ฐœ๋ฐœ์ž๋Š” ์ด ๋ฌธ์ œ๋ฅผ nginx์˜ ๋ณด์•ˆ ๋ฒ„๊ทธ๋กœ ๊ฐ„์ฃผํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. nginx ์ž์ฒด์—๋Š” ํŠน์ˆ˜ ๋ฌธ์ž๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ ์˜ค๋ฅ˜๋ฅผ ์•…์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐœ 16์›” 4์ผ์— ์ถœํŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ณด๊ณ ์„œ ์ดํ›„ 18๊ฐœ์›” ๋™์•ˆ OpenResty์—๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์—†์—ˆ์ง€๋งŒ ngx.req.set_uri() ํ•จ์ˆ˜์˜ ์•ˆ์ „ํ•œ ๋ฒ„์ „์ด ํ•„์š”ํ•˜๋‹ค๋Š” ์ดํ•ด๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. 2020๋…„ 21์›” XNUMX์ผ์— ์ •๋ณด๋ฅผ ๊ฒŒ์‹œํ–ˆ์œผ๋ฉฐ, XNUMX์›” XNUMX์ผ์— OpenResty๊ฐ€ ์ถœ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฒ„์ „ 1.15.8.3, URI ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

ํฌํŠธ์œ„๊ฑฐ ะฝะฐะฟะธัะฐะป ์ข‹์€ ๊ธฐ์‚ฌ์ด๋ฉฐ OpenResty ๋ฐ Nginx์—์„œ ์˜๊ฒฌ์„ ๊ฐ€์ ธ์™”์Šต๋‹ˆ๋‹ค(๋น„๋ก ์ž‘์€ ๋ฉ”๋ชจ๋ฆฌ ์กฐ๊ฐ๋งŒ ๋…ธ์ถœ๋œ๋‹ค๋Š” ์˜๊ฒฌ์€ ๋ถ€์ •ํ™•ํ•˜๊ณ  ์˜คํ•ด์˜ ์†Œ์ง€๊ฐ€ ์žˆ์ง€๋งŒ ์ด๋Š” null ๋ฐ”์ดํŠธ ๋‹ค์Œ ์ค„์˜ ๊ธธ์ด์— ์˜ํ•ด ๊ฒฐ์ •๋˜๋ฉฐ, ๊ธธ์ด๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).

๊ทธ๋ ‡๋‹ค๋ฉด ์‹ค์ˆ˜๋Š” ๋ฌด์—‡์ด๋ฉฐ ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

nginx์— ๋ฒ„๊ทธ๊ฐ€ ์žˆ์—ˆ๋‚˜์š”? ๋„ค, ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋‚ด์šฉ ์œ ์ถœ์€ ์–ด๋–ค ๊ฒฝ์šฐ์—๋„ ์˜ค๋ฅ˜์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

OpenResty์— ๋ฒ„๊ทธ๊ฐ€ ์žˆ์—ˆ๋‚˜์š”? ์˜ˆ, ์ตœ์†Œํ•œ OpenResty๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์˜ ๋ณด์•ˆ ๋ฌธ์ œ๋Š” ์กฐ์‚ฌ ๋ฐ ๋ฌธ์„œํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

OpenResty์— ๊ตฌ์„ฑ/์‚ฌ์šฉ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์—ˆ๋‚˜์š”? ์˜ˆ, ๋ช…์‹œ์ ์ธ ์„ค๋ช…์ด ์—†์œผ๋ฉด ์‚ฌ์šฉ ์ค‘์ธ ๊ธฐ๋Šฅ์˜ ๋ณด์•ˆ์— ๋Œ€ํ•ด ํ™•์ธ๋˜์ง€ ์•Š์€ ๊ฐ€์ •์ด ์ด๋ฃจ์–ด์กŒ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ ์ค‘ ํ˜„์ƒ๊ธˆ์ด 10000๋‹ฌ๋Ÿฌ์ธ ๋ณด์•ˆ ์ทจ์•ฝ์ ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์šฐ๋ฆฌ์—๊ฒŒ ์ด๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์†Œํ”„ํŠธ์›จ์–ด, ํŠนํžˆ ์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ต์ฐจ์ , ํŠนํžˆ ๋‹ค์–‘ํ•œ ํ”„๋กœ์ ํŠธ์™€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด์—์„œ๋Š” ๋ˆ„๊ตฌ๋„ ์ž‘์—…์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์ด ์•Œ๋ ค์ ธ ์žˆ๊ณ  ๋ฌธ์„œํ™”๋˜์–ด ์žˆ์œผ๋ฉฐ ์˜ค๋ฅ˜๊ฐ€ ์—†๋‹ค๊ณ  ๋ณด์žฅํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ชจ๋“  ๋ณด์•ˆ ์ทจ์•ฝ์ ์€ ๋ณด์•ˆ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ณณ์—์„œ ์ •ํ™•ํ•˜๊ฒŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ๊ฒฝ์šฐ๋“  ๋ช…์‹œ์ ์ธ ์ง€์นจ์ด ์—†๊ณ  ์ด๊ฒƒ์ด ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋Š” ๋ช…ํ™•ํ•œ ์ดํ•ด๊ฐ€ ์—†๋Š” ํ•œ ์™ธ๋ถ€ ๋ชจ๋“ˆ/API์— ๋“ค์–ด๊ฐ€๋Š” ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์ด ์ •๊ทœํ™”ํ•˜๊ฑฐ๋‚˜ ์ œํ•œ/ํ•„ํ„ฐ๋งํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์—๋ผํƒ€

๊ฒฝํ—˜์—์„œ ์ด์ „ ๊ธฐ์‚ฌ, ์–ธ์–ด์˜ ์ˆœ์ˆ˜์„ฑ์„ ๋ณด์กดํ•˜๊ธฐ ์œ„ํ•ด:

๋ฒ„๊ทธ ํ˜„์ƒ๊ธˆ - ๋ฒ„๊ทธ ์‚ฌ๋ƒฅ ๋Œ€ํšŒ
๋ฒ„๊ทธ ๋ณด๊ณ ์„œ - ์˜ค๋ฅ˜ ์•Œ๋ฆผ
๋ฆฌ๋””๋ ‰์…˜ - ๋ฆฌ๋””๋ ‰์…˜
์˜คํ”ˆ ์†Œ์Šค - ์˜คํ”ˆ ์†Œ์Šค
์ •์˜คํ‘œ - ์‹ค์ˆ˜์— ๋Œ€ํ•ด ๋…ธ๋ ฅํ•˜๋ผ

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€