Unit7 - [Deploy] CI/CD

๊ฐ•์„ฑ์ผยท2023๋…„ 8์›” 2์ผ
0
post-thumbnail

โœ… TIL


์„œ๋น„์Šค์˜ ๊ทœ๋ชจ๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ  ์ปค์งˆ์ˆ˜๋ก, ์„œ๋น„์Šค๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๊ณผ์ •์ด ๋ณต์žกํ•ด์ง€๊ณ  ์†Œ์š”๋˜๋Š” ์‹œ๊ฐ„์ด ๋Š˜์–ด๋‚˜๊ฒŒ ๋œ๋‹ค.
๋˜ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ƒ๊ธธ ๋•Œ๋งˆ๋‹ค ๋ฐฐํฌ ๊ณผ์ •์„ ๋งค๋ฒˆ ์ˆ˜๋™์œผ๋กœ ์ง„ํ–‰ํ•œ๋‹ค๋ฉด, ๋ฐฐํฌ ๊ณผ์ •์— ๋งŽ์€ ์‹œ๊ฐ„์„ ํ—ˆ๋น„ํ•ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค.

๋ฒ„ํŠผ ํ•˜๋‚˜๋งŒ ํด๋ฆญํ•˜๋ฉด ์ „์ฒด ๋ฐฐํฌ ๊ณผ์ •์ด '์ž๋™'์œผ๋กœ ์ง„ํ–‰๋˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜๋Š” ์—†์„๊นŒ?

์ด๋ฒˆ ์œ ๋‹›์—์„œ๋Š” ๋ฐฐํฌ ์ž๋™ํ™” ๊ฐœ๋…์— ๋Œ€ํ•ด ํ•™์Šตํ•˜๊ณ , ์‹ค์Šต์„ ํ†ตํ•ด ๋ฐฐํฌ ์ž๋™ํ™”์˜ ์žฅ์ ์„ ์ฒดํ—˜ํ•ด๋ณด๊ฒ ๋‹ค.



CI/CD


CI/CD๋Š” ์•ฝ์–ด๋กœ, ๋ช‡ ๊ฐ€์ง€์˜ ๋‹ค๋ฅธ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

CI/CD์˜ "CI"๋Š” ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์ž๋™ํ™” ํ”„๋กœ์„ธ์Šค์ธ ์ง€์†์ ์ธ ํ†ตํ•ฉ(Continuous Integration)์„ ์˜๋ฏธํ•œ๋‹ค.
CI๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ •๊ธฐ์ ์œผ๋กœ ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ๋˜์–ด ๊ณต์œ  ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํ†ตํ•ฉ๋˜๋ฏ€๋กœ ์—ฌ๋Ÿฌ ๋ช…์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋™์‹œ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ๊ณผ ๊ด€๋ จ๋œ ์ฝ”๋“œ ์ž‘์—…์„ ํ•  ๊ฒฝ์šฐ ์„œ๋กœ ์ถฉ๋Œํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

CI/CD์˜ "CD"๋Š” ์ง€์†์ ์ธ ์„œ๋น„์Šค ์ œ๊ณต(Continuous Delivery) ๋ฐ/๋˜๋Š” ์ง€์†์ ์ธ ๋ฐฐํฌ(Continuous Deployment)๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ ์ด ๋‘ ์šฉ์–ด๋Š” ์ƒํ˜ธ ๊ตํ™˜์ ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ๋‘ ๊ฐ€์ง€ ์˜๋ฏธ ๋ชจ๋‘ ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ถ”๊ฐ€ ๋‹จ๊ณ„์— ๋Œ€ํ•œ ์ž๋™ํ™”๋ฅผ ๋œปํ•˜์ง€๋งŒ ๋•Œ๋กœ๋Š” ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ž๋™ํ™”๊ฐ€ ์ด๋ฃจ์–ด์ง€๊ณ  ์žˆ๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„๋กœ ์‚ฌ์šฉ๋˜๊ธฐ๋„ ํ•œ๋‹ค.


CI/CD์˜ ๋‹จ๊ณ„



์ง€์†์  ํ†ตํ•ฉ(Continuous Integration, CI)


๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์ž๋™ํ™” ํ”„๋กœ์„ธ์Šค๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, Code - Build - Test ๋‹จ๊ณ„์—์„œ ๊พ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Code : ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ์›๊ฒฉ ์ฝ”๋“œ ์ €์žฅ์†Œ (Ex. github repository)์— pushํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค.
  • Build : ์›๊ฒฉ ์ฝ”๋“œ ์ €์žฅ์†Œ๋กœ๋ถ€ํ„ฐ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์™€ ์œ ๋‹› ํ…Œ์ŠคํŠธ ํ›„ ๋นŒ๋“œํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค.
  • Test : ์ฝ”๋“œ ๋นŒ๋“œ์˜ ๊ฒฐ๊ณผ๋ฌผ์ด ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ์ž˜ ํ†ตํ•ฉ๋˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์ด๋‹ค.

์ด ๊ณผ์ •์—์„œ ๊ฐœ๋ฐœ์ž๋Š” ์ฝ”๋“œ๋ฅผ ์žฆ๊ฒŒ ์›๊ฒฉ ์ฝ”๋“œ ์ €์žฅ์†Œ์— pushํ•˜๊ณ , ํ…Œ์ŠคํŠธ ๋ฐ ๋นŒ๋“œ๋ฅผ ํ•˜๋ฉฐ ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฅผ ํ†ตํ•ด ๋นŒ๋“œ๊ฐ€ ์„ฑ๊ณตํ–ˆ๋Š”์ง€ ์‹คํŒจํ–ˆ๋Š”์ง€ ํ™•์ธ์„ ํ•˜๊ณ , ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ํ†ตํ•ด ๊ฐœ์„  ๋ฐฉ์•ˆ์„ ์ฐพ๋Š”๋‹ค. ์ด ์ง€์†์ ์ธ ํ†ตํ•ฉ ๊ณผ์ •์„ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ๋ฒ„๊ทธ๋ฅผ ์ผ์ฐ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ๊ณ , ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋œ ์ฝ”๋“œ์— ๋Œ€ํ•ด ๋น ๋ฅธ ์ „๋‹ฌ์ด ๊ฐ€๋Šฅํ•ด์ง€๋ฉฐ ์ง€์†์ ์ธ ๋ฐฐํฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

์ง€์†์  ํ†ตํ•ฉ์€ ๋ชจ๋“  ์ฝ”๋“œ ๋ณ€ํ™”๋ฅผ ํ•˜๋‚˜์˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค. ๋ชจ๋“  ๊ฐœ๋ฐœํŒ€์ด ์ฝ”๋“œ์˜ ๋ณ€ํ™”๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํˆฌ๋ช…ํ•˜๊ฒŒ ๋ฌธ์ œ์ ์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์žฆ์€ ํ’€ ๋ฆฌํ€˜์ŠคํŠธ(pull request)์™€ ๋จธ์ง€(merge)๋กœ ์ฝ”๋“œ๋ฅผ ์ž์ฃผ ํ†ตํ•ฉํ•œ๋‹ค. ์ด๋•Œ, ๊ธฐ๋ณธ์ ์ธ ํ…Œ์ŠคํŠธ๋„ ์ž‘๋™์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ง€์†์  ํ†ตํ•ฉ์„ ํ†ตํ•ด ๊ฐœ๋ฐœํŒ€์€ ๊ฐ์ž ๊ฐœ๋ฐœํ•œ ์ฝ”๋“œ๋ฅผ ์ด๋ฅธ ์‹œ์ ์— ์ž์ฃผ ํ•ฉ์น˜๊ณ  ์ž์ฃผ ํ…Œ์ŠคํŠธ ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

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


์ง€์†์  ๋ฐฐํฌ(Continuous Delivery/Deployment, CD)


์ง€์†์ ์ธ ์„œ๋น„์Šค ์ œ๊ณต(Continuous Delivery) ๋ฐ ์ง€์†์ ์ธ ๋ฐฐํฌ(Continuous Deployment)๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ
์ด ๋‘ ์šฉ์–ด๋Š” ์ƒํ˜ธ ๊ตํ™˜์ ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ์ด ๋ถ€๋ถ„์€ Release - Deploy - Operate ๋‹จ๊ณ„์—์„œ ๊พ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Release : ๋ฐฐํฌ ๊ฐ€๋Šฅํ•œ ์†Œํ”„ํŠธ์›จ์–ด ํŒจํ‚ค์ง€๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
  • Deploy : ํ”„๋กœ๋น„์ €๋‹์„ ์‹คํ–‰ํ•˜๊ณ  ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœํ•œ๋‹ค. ์‹ค์งˆ์ ์ธ ๋ฐฐํฌ ๋ถ€๋ถ„์ด๋‹ค.
  • Operate : ์„œ๋น„์Šค ํ˜„ํ™ฉ์„ ํŒŒ์•…ํ•˜๊ณ  ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ๊ฐ์ง€ํ•œ๋‹ค.

์ง€์†์  ๋ฐฐํฌ์˜ ๊ฒฝ์šฐ, ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์˜ ๋ณ‘ํ•ฉ๋ถ€ํ„ฐ ํ”„๋กœ๋•์…˜์— ์ ํ•ฉํ•œ ๋นŒ๋“œ ์ œ๊ณต์—
์ด๋ฅด๋Š” ๋ชจ๋“  ๋‹จ๊ณ„๋กœ, ํ…Œ์ŠคํŠธ ์ž๋™ํ™”์™€ ์ฝ”๋“œ ๋ฐฐํฌ ์ž๋™ํ™”๊ฐ€ ํฌํ•จ๋œ๋‹ค.

์ด ํ”„๋กœ์„ธ์Šค๋ฅผ ์™„๋ฃŒํ•˜๋ฉด ํ”„๋กœ๋•์…˜ ์ค€๋น„๊ฐ€ ์™„๋ฃŒ๋œ ๋นŒ๋“œ๋ฅผ ์ฝ”๋“œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ์ž๋™์œผ๋กœ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๊ธฐ
๋•Œ๋ฌธ์— ์šด์˜ํŒ€์ด ๋ณด๋‹ค ๋น ๋ฅด๊ณ  ์†์‰ฝ๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ”„๋กœ๋•์…˜์œผ๋กœ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

์ตœ๊ทผ์—๋Š” ํด๋ผ์šฐ๋“œ ๊ธฐ์ˆ  ๋ฐœ์ „๊ณผ ๋งž๋ฌผ๋ ค ์ง€์†์  ํ†ตํ•ฉ๊ณผ ์ง€์†์  ๋ฐฐํฌ๊ฐ€ ๋น ๋ฅธ ์†๋„๋กœ ์ง„ํ–‰๋˜๋ฉด์„œ CI/CD๋ฅผ ํ•˜๋‚˜๋กœ ๋ฌถ์–ด์„œ ๋‹ค๋ฃจ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ ์ฐจ ์ฆ๊ฐ€ํ•˜๊ณ  ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด์ „์—๋Š” ๋ฐฐํฌ ์ž์ฒด๊ฐ€ ์ƒ๋‹นํžˆ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๊ณ  ํž˜๋“  ์ผ์ด์–ด์„œ ๋ฐฐํฌ ์ด์ „ ๋‹จ๊ณ„์—์„œ ๋งŽ์€ ๊ณ ๋ฏผ์„ ํ•˜๊ณค ํ–ˆ๋‹ค. ์„œ๋ฒ„๋ฅผ ์ „๋ถ€ ์žฌ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค๊ฑฐ๋‚˜, ์ผ๋ถ€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๋„ ๋งŽ์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์š”์ฆ˜์€ ๊ณ ๊ฐ์˜ ํ”ผ๋“œ๋ฐฑ์„ ๋นจ๋ฆฌ ๋ฐ›๊ธฐ ์œ„ํ•ด์„œ๋ผ๋„, ์„œ๋น„์Šค๋ฅผ ์ค‘๋‹จํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ๋ผ๋„ ๋ฆด๋ฆฌ์Šค๋งŒ ์ž˜ ๊ธฐ๋กํ•ด ๋‘๊ณ  ๋ฐ”๋กœ๋ฐ”๋กœ ๋ฐฐํฌํ•˜๋Š” ์‚ฌ๋ก€๊ฐ€ ์ฆ๊ฐ€ํ•˜๊ณ  ์žˆ๋‹ค.



CI/CD ํŒŒ์ดํ”„๋ผ์ธ


๋ฐฐํฌ ์ž๋™ํ™”

๋ฐฐํฌ ์ž๋™ํ™”๋ž€ ํ•œ ๋ฒˆ์˜ ํด๋ฆญ ํ˜น์€ ๋ช…๋ น์–ด ์ž…๋ ฅ์„ ํ†ตํ•ด ์ „์ฒด ๋ฐฐํฌ ๊ณผ์ •์„ ์ž๋™์œผ๋กœ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋œปํ•œ๋‹ค.
๋ฐฐํฌ ์ž๋™ํ™”๊ฐ€ ์™œ ํ•„์š”ํ• ๊นŒ?

  • ๋จผ์ € ์ˆ˜๋™์ ์ด๊ณ  ๋ฐ˜๋ณต์ ์ธ ๋ฐฐํฌ ๊ณผ์ •์„ ์ž๋™ํ™”ํ•จ์œผ๋กœ์จ ์‹œ๊ฐ„์ด ์ ˆ์•ฝ๋œ๋‹ค.
  • ํœด๋จผ ์—๋Ÿฌ(Human Error)๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
    ์—ฌ๊ธฐ์„œ ํœด๋จผ ์—๋Ÿฌ๋ž€ ์‚ฌ๋žŒ์ด ์ˆ˜๋™์ ์œผ๋กœ ๋ฐฐํฌ ๊ณผ์ •์„ ์ง„ํ–‰ํ•˜๋Š” ์ค‘์— ์ƒ๊ธฐ๋Š” ์‹ค์ˆ˜๋“ค์„ ๋œปํ•œ๋‹ค. ๊ทธ์ „์— ํ–ˆ๋˜ ๋ฐฐํฌ ๊ณผ์ •๊ณผ ๋น„๊ตํ•˜์—ฌ ํŠน์ • ๊ณผ์ •์„ ์ƒ๋žตํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅด๊ฒŒ ์ง„ํ–‰ํ•˜์—ฌ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด ํœด๋จผ ์—๋Ÿฌ์˜ ์˜ˆ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋ฐฐํฌ ์ž๋™ํ™”๋ฅผ ํ†ตํ•ด ์ „์ฒด ๋ฐฐํฌ ๊ณผ์ •์„ ๋งค๋ฒˆ ์ผ๊ด€๋˜๊ฒŒ ์ง„ํ–‰ํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•˜์—ฌ ํœด๋จผ ์—๋Ÿฌ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์„ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ๋‹ค.


CI/CD ํŒŒ์ดํ”„๋ผ์ธ

์•ž์„œ ์šฐ๋ฆฌ๋Š” ์ „ํ†ต์ ์ธ ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค์™€ ๋ชจ๋˜ ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•ด ๋ฐฐ์› ๋‹ค.
๊ทธ๋ฆฌ๊ณ  SaaS๊ฐ€ ๋ชจ๋˜ ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค๋กœ ๊ฐœ๋ฐœํ•˜๊ธฐ ์ ํ•ฉํ•œ ์†Œํ”„ํŠธ์›จ์–ด์ž„๋„ ํ™•์ธํ–ˆ๋‹ค.

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

๊ทธ๋ž˜์„œ ์ด ์ˆ˜์—†์ด ์ง„ํ–‰๋˜๋Š” ๋ฐฐํฌ ๊ณผ์ •์„ ์ž๋™ํ™”์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์„ ๊ตฌ์ถ•ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ๊ทธ๊ฒƒ์„ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์ด๋ผ๊ณ  ํ•œ๋‹ค.

ํ•ด๋‹น ๊ทธ๋ฆผ์€ ๋ฐฐํฌ ๊ณผ์ •์„ ๋„์‹ํ™”ํ•œ ๊ฒƒ์ด๋‹ค.

๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ์›๊ฒฉ ์ €์žฅ์†Œ์— ์˜ฌ๋ฆฌ๋ฉด, ๊ทธ ์ฝ”๋“œ๊ฐ€ ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ์™€ ๋ฆด๋ฆฌ์Šค๋ฅผ ๊ฑฐ์ณ ๋ฐฐํฌ ์„œ๋ฒ„๋กœ ์ „๋‹ฌ๋œ๋‹ค.

๋ฐฐํฌ ์„œ๋ฒ„์— ๋„๋‹ฌํ•œ ๋นŒ๋“œ๋œ ์ฝ”๋“œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„๋กœ ์ตœ์ข… ๋ฐฐํฌ๊ฐ€ ์™„๋ฃŒ๋˜๊ณ ,
๊ทธ ๊ฒฐ๊ณผ๋ฌผ์„ ์œ ์ €๊ฐ€ ์ง์ ‘ ํ™•์ธํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์—ฌ๊ธฐ์„œ ์ž๋™ํ™”๋ฅผ ๊พ€ํ•˜๋Š” ๋ถ€๋ถ„์€ ๋ณดํ†ต ์ฝ”๋“œ๊ฐ€ ๋นŒ๋“œ๋˜๋ฉด์„œ ์ตœ์ข…์ ์œผ๋กœ ๋ฐฐํฌ๊ฐ€ ๋˜๋Š” ๋‹จ๊ณ„๊นŒ์ง€์ด๋‹ค.
์ด ๋ถ€๋ถ„์„ ์ง€์†์ ์ธ ํ†ตํ•ฉ ๋ฐ ๋ฐฐํฌ๋ฅผ ์œ„ํ•˜์—ฌ ์ผ๋ จ์˜ ์ž๋™ํ™” ๋‹จ๊ณ„๋กœ ๋งŒ๋“œ๋Š”๋ฐ, ์ด๊ฒƒ์„ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•œ๋‹ค๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.


CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ๋‹จ๊ณ„์™€ ์ˆ˜ํ–‰ ์ž‘์—…

๋ฐฐํฌ์—์„œ ํŒŒ์ดํ”„๋ผ์ธ(Pipeline)์ด๋ž€ ์šฉ์–ด๋Š” ์†Œ์Šค ์ฝ”๋“œ์˜ ๊ด€๋ฆฌ๋ถ€ํ„ฐ ์‹ค์ œ ์„œ๋น„์Šค๋กœ์˜ ๋ฐฐํฌ ๊ณผ์ •์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ๋œปํ•œ๋‹ค.

ํŒŒ์ดํ”„๋ผ์ธ์€ ์ „์ฒด ๋ฐฐํฌ ๊ณผ์ •์„ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„(Stages)๋กœ ์„ธ ๊ฐ€์ง€ ๋‹จ๊ณ„๋กœ ๋ถ„๋ฆฌํ•œ๋‹ค.
๊ฐ ๋‹จ๊ณ„๋Š” ํŒŒ์ดํ”„๋ผ์ธ ์•ˆ์—์„œ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉฐ, ๊ฐ ๋‹จ๊ณ„๋งˆ๋‹ค ์ฃผ์–ด์ง„ ์ž‘์—…(Actions)๋“ค์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

  1. Source ๋‹จ๊ณ„: Source ๋‹จ๊ณ„์—์„œ๋Š” ์›๊ฒฉ ์ €์žฅ์†Œ์— ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ๋Š” ์†Œ์Šค ์ฝ”๋“œ์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ผ์–ด๋‚  ๊ฒฝ์šฐ,
    ์ด๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ „๋‹ฌํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  2. Build ๋‹จ๊ณ„: Build ๋‹จ๊ณ„์—์„œ๋Š” Source ๋‹จ๊ณ„์—์„œ ์ „๋‹ฌ๋ฐ›์€ ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผ, ๋นŒ๋“œ, ํ…Œ์ŠคํŠธํ•˜์—ฌ ๊ฐ€๊ณตํ•œ๋‹ค.
    ๋˜ํ•œ Build ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ ์ƒ์„ฑ๋œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ „๋‹ฌํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  3. Deploy ๋‹จ๊ณ„: Deploy ๋‹จ๊ณ„์—์„œ๋Š” Build ๋‹จ๊ณ„๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๊ฒฐ๊ณผ๋ฌผ์„ ์‹ค์ œ ์„œ๋น„์Šค์— ๋ฐ˜์˜ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋‹จ๊ณ„๋Š” ํ•„์š”์— ๋”ฐ๋ผ ๋” ์„ธ๋ถ„ํ™”๋˜๊ฑฐ๋‚˜ ๊ฐ„์†Œํ™”๋  ์ˆ˜ ์žˆ๋‹ค
DevOps๋ฅผ ์ „๋ฌธ์œผ๋กœ ํ•™์Šตํ•˜๋Š” ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์ด ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋‹จ๊ณ„๋ฅผ ์„ธ๋ถ„ํ™”ํ•ด์„œ ๋‚˜๋ˆ„๊ธฐ๋„ ํ•œ๋‹ค.
๋˜ํ•œ, ํ•ด๋‹น ํˆด์„ ์†Œ๊ฐœํ•˜๋Š” ์—…์ฒด์— ๋”ฐ๋ผ ์šฉ์–ด๋ฅผ ๋ฏธ๋ฌ˜ํ•˜๊ฒŒ ๋‹ค๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•œ๋‹ค.


CI/CD ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์„ฑ ์š”์†Œ ๋ฐ ์žฅ์ 

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

๋กœ์ด๋ฃจ์–ด์ ธ ์žˆ์œผ๋ฉฐ, ์ด ๊ณผ์ •์ด ์‹ค๋ฌด์—์„œ๋Š” ๋ฐ˜๋ณต์ ์ธ ํ”„๋กœ์„ธ์Šค์ด๊ธฐ ๋•Œ๋ฌธ์—
์ด ๋ถ€๋ถ„์„ ์ผ๋ จ์˜ ์ž๋™ํ™” ๋‹จ๊ณ„๋กœ ๋งŒ๋“ ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๊ตฌ์ถ•๋œ ํŒŒ์ดํ”„๋ผ์ธ์€ ์ตœ์‹  ๋ฒ„์ „์˜ ์†Œํ”„ํŠธ์›จ์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์ œ๊ณตํ•˜๋ ค๋Š” ์ผ๋ จ์˜ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„์— ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ์ˆ˜๋™์œผ๋กœ ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋น ๋ฅด๊ณ  ์•ˆ์ •์ ์ด๋ฉฐ ํšจ๊ณผ์ ์œผ๋กœ ์ค„์—ฌ์ฃผ๊ณ  CI/CD ์ธํ”„๋ผ์™€์˜ ํ˜ธํ™˜์„ฑ๊ณผ ํšจ์œจ์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.



Github Action


GitHub Actions๋Š” Github๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋นŒ๋“œ, ํ…Œ์ŠคํŠธ ๋ฐ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” CI/CD ํ”Œ๋žซํผ์ด๋‹ค.

๋ ˆํฌ์ง€ํ† ๋ฆฌ์—์„œ Pull Request๋‚˜ push๊ฐ™์€ ์ด๋ฒคํŠธ๋ฅผ
ํŠธ๋ฆฌ๊ฑฐ๋กœ GitHub ์ž‘์—… ์›Œํฌํ”Œ๋กœ์šฐ(Workflow)๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์›Œํฌํ”Œ๋กœ์šฐ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์ž‘์—…์ด ์‹คํ–‰๋˜๋Š” ์ž๋™ํ™” ํ”„๋กœ์„ธ์Šค๋กœ,
๊ฐ ์ž‘์—…์€ ์ž์ฒด ๊ฐ€์ƒ ๋จธ์‹  ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—์„œ ์‹คํ–‰๋œ๋‹ค.

์›Œํฌํ”Œ๋กœ์šฐ๋Š” .yml (ํ˜น์€ .yaml ) ํŒŒ์ผ์— ์˜ํ•ด ๊ตฌ์„ฑ๋˜๋ฉฐ, ํ…Œ์ŠคํŠธ, ๋ฐฐํฌ ๋“ฑ ๊ธฐ๋Šฅ์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ๊ฐœ์˜
์›Œํฌํ”Œ๋กœ์šฐ๋กœ๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์ƒ์„ฑ๋œ ์›Œํฌํ”Œ๋กœ์šฐ๋Š” .github/workflows ๋””๋ ‰ํ† ๋ฆฌ ์ดํ•˜์— ์œ„์น˜ํ•œ๋‹ค.

๋น„๊ณต๊ฐœ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์˜ ๊ฒฝ์šฐ Github Actions๊ฐ€ ์ž‘๋™ํ•  ๋•Œ์˜ ์šฉ๋Ÿ‰๊ณผ ์‹œ๊ฐ„์ด
์ œํ•œ๋˜์–ด ์žˆ์œผ๋ฉฐ ๊ณต๊ฐœ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋Š” ๋ฌด๋ฃŒ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.



ํŠœํ† ๋ฆฌ์–ผ


์ด๋ฒˆ ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋‚˜๋งŒ์˜ ์•„๊ณ ๋ผ ์Šคํ…Œ์ด์ธ  ์„œ๋ฒ„ ๋ ˆํผ๋Ÿฐ์Šค์™€ Github Action์„ ์ด์šฉํ•˜์—ฌ ์ง„ํ–‰ํ•œ๋‹ค.

๋จผ์ €, ์ž์‹ ์˜ ๊นƒํ—ˆ๋ธŒ ๊ณ„์ •์— ์ƒˆ๋กœ์šด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ ๋‹ค.
๐Ÿ’ก public์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ Github Action์„ ๋ฌด๋ฃŒ๋กœ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ƒˆ๋กœ์šด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋‚˜๋งŒ์˜ ์•„๊ณ ๋ผ ์Šคํ…Œ์ด์ธ  ์„œ๋ฒ„ ๋ ˆํผ๋Ÿฐ์Šค ์ฝ”๋“œ๋ฅผ pushํ•œ๋‹ค.

drag & drop์„ ํ•  ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ, ๊ฐ€๋Šฅํ•˜๋ฉด ๊ธฐ์กด ๋‚˜๋งŒ์˜ ์•„๊ณ ๋ผ ์Šคํ…Œ์ด์ธ  ์„œ๋ฒ„ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ
ํด๋ก ๋ฐ›์•„์„œ, ์ƒˆ๋กœ์šด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์›๊ฒฉ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋กœ ๋“ฑ๋กํ•˜๊ณ , ์ฝ”๋“œ๋ฅผ pushํ•œ๋‹ค.

# ๊ธฐ์กด ๋‚˜๋งŒ์˜ ์•„๊ณ ๋ผ ์Šคํ…Œ์ด์ธ  ์„œ๋ฒ„ ๋ ˆํผ๋Ÿฐ์Šค ํด๋ก 
git clone git@github.com:codestates-seb/fe-sprint-my-agora-states-server-reference.git
# ๋””๋ ‰ํ„ฐ๋ฆฌ ์ด๋™
cd fe-sprint-my-agora-states-server-reference
# ์ƒˆ๋กœ์šด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์›๊ฒฉ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋กœ ๋“ฑ๋ก
git remote add myRepo git@github.com:{์—ฌ๋Ÿฌ๋ถ„์˜ ์•„์ด๋””}/{์ƒˆ๋กœ์šด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ด๋ฆ„}.git
# ๊ธฐ์กด ๋ ˆํผ๋Ÿฐ์Šค ์ฝ”๋“œ๋ฅผ ์ƒˆ๋กœ์šด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋กœ push
git push myRepo reference


์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๊ฐ€ ๋ชจ๋‘ push๊ฐ€ ๋œ ๋ชจ์Šต์„ ํ™•์ธํ•œ๋‹ค. ์ปค๋ฐ‹ ๊ธฐ๋ก์„ ๋ณด์‹œ๋ฉด, ์ฃผํ™ฉ์ƒ‰ ์›์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฃผํ™ฉ์ƒ‰ ์›์ด ๋ฌด์—‡์ธ์ง€ ์ข€ ๋” ์ž์„ธํžˆ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด Actions ํƒญ์œผ๋กœ ์ด๋™ํ•œ๋‹ค.
Github Action์„ ์ฝ”๋“œ๋ฅผ ์„ค์ •ํ•ด ๋‘๋ฉด ์ด๋ ‡๊ฒŒ ์„œ๋ฒ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Github Action์€ Github์˜ ํŠน์ • ์ด๋ฒคํŠธ์— ๋งž๊ฒŒ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” CI/CD ํ”Œ๋žซํผ์ด๋‹ค. EC2์™€ ๊ฐ™์€ ํ•˜๋‚˜์˜ ๊ฐ€์ƒ ์ธ์Šคํ„ด์Šค๋ฅผ ์‹คํ–‰์‹œ์ผœ์„œ ์›ํ•˜๋Š” ์ž‘์—…์„ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ pushํ•˜๊ธฐ๋งŒ ํ–ˆ๋Š”๋ฐ, ์™œ ์ž‘๋™ํ–ˆ์„๊นŒ? ./.github/workflows/pullRequest.yml ํŒŒ์ผ์„ ์ฝ์–ด๋ณด๋ฉด, ์–ธ์ œ ์–ด๋–ค job์„ ํ• ์ง€ ๋ช…์‹œ๋˜์–ด ์žˆ๋‹ค.

  • npm install์€ ๋นŒ๋“œ๋ฅผ ์œ„ํ•œ ์ค€๋น„๊ณผ์ •์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. Node.js๋กœ ๋งŒ๋“  ์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€
    npm์œผ๋กœ ๊ด€๋ จ ์˜คํ”ˆ์†Œ์Šค๋ฅผ ๋ชจ๋‘ ๊น”๋”ํ•˜๊ฒŒ ์„ค์น˜ํ•ด์•ผ ์ž‘๋™ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • npm test๋Š” ์œ ๋‹› ํ…Œ์ŠคํŠธ ๊ณผ์ •์ด๋‹ค. ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ ์š”๊ตฌ์‚ฌํ•ญ
    ์ถฉ์กฑ์„ ์œ„ํ•œ ์ตœ์†Œํ•œ์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์žˆ๋‹ค.

name: Bare Minimum Requirements

# ์–ธ์ œ job์„ ์ž‘๋™์‹œํ‚ฌ์ง€
on: [push, pull_request]

# ์–ด๋–ค job์„ ํ• ์ง€
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Bare Minimum Requirements
        uses: actions/setup-node@v1
        with:
          node-version: '16'
      - run: npm install
      - run: npm test


YAML


Yet Another Markup Language์˜ ์•ฝ์ž๋กœ, ์‚ฌ๋žŒ์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์ง๋ ฌํ™” ์–ธ์–ด๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
ํŒŒ์ผ๋กœ ์ž‘์„ฑ ์‹œ ํ™•์žฅ์ž๋Š” .yaml ํ˜น์€ .yml ํ™•์žฅ์ž๋ฅผ ๊ฐ€์ง„๋‹ค.

YAML์€ ์‚ฌ๋žŒ์ด ์ฝ์„ ์ˆ˜ ์žˆ๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ์ค‘์—์„œ๋„ ์ธ๊ธฐ๊ฐ€ ๋†’๋‹ค. ๋˜ํ•œ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์™€
ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค. YAML์€ ๊ทธ ์œ ์—ฐ์„ฑ๊ณผ ์ ‘๊ทผ์„ฑ์œผ๋กœ ์ธํ•ด ์ž๋™ํ™” ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ์—๋„ ์‚ฌ์šฉ๋œ๋‹ค.


JSON vs YAML


// YAML ํŒŒ์ผ

name: Bare Minimum Requirements
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Bare Minimum Requirements
        uses: actions/setup-node@v1
        with:
          node-version: '16'
      - run: npm install
      - run: npm test
// JSON ํŒŒ์ผ

{
  "squadName": "Super hero squad",
  "homeTown": "Metro City",
  "formed": 2016,
  "secretBase": "Super tower",
  "active": true,
  "members": [
    {
      "name": "Molecule Man",
      "age": 29,
      "secretIdentity": "Dan Jukes",
      "powers": [
        "Radiation resistance",
        "Turning tiny",
        "Radiation blast"
      ]
    }
  ]
}


JSON ํŒŒ์ผ๊ณผ YAML ํŒŒ์ผ์€ key-value ํ˜•ํƒœ๋กœ ์ž‘์„ฑ๋œ ํŒŒ์ผ์ด๋ฉฐ, ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์—๋Š” ๋™์ผํ•˜๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ YAML ํŒŒ์ผ์€ "" (ํฐ๋”ฐ์˜ดํ‘œ, double quotation marks) ์—†์ด ๋ฌธ์ž์—ด ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•ด, ์„ค์ •์„ ์œ„ํ•œ ์ŠคํŽ™์ด๋‚˜ ํ”„๋กœํผํ‹ฐ ๊ฐ’ ๋“ฑ์ด JSON ํŒŒ์ผ์— ๋น„ํ•ด ํ•œ๋ˆˆ์— ๋“ค์–ด์˜จ๋‹ค๋Š” ์ ์ด๋‹ค. ๋˜ํ•œ JSON ํŒŒ์ผ์ฒ˜๋Ÿผ {} ํ˜•ํƒœ๋กœ ๊ฐ์‹ธ์ค„ ํ•„์š”๋„ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์Šค์ฝ”ํ”„์˜ ์••๋ฐ•(์ž˜๋ชป ์“ฐ๋ฉด ์ผ์ผ์ด ์–ด๋””๊ฐ€ ์ฒ˜์Œ์ด๊ณ  ๋์ธ์ง€ ์ฐพ์•„์•ผ ํ•˜๋Š” ๋“ฑ)์—์„œ ๋ฒ—์–ด๋‚  ์ˆ˜๋„ ์žˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ YAML ํŒŒ์ผ์€ JSON ํŒŒ์ผ๊ณผ ๋‹ค๋ฅด๊ฒŒ ์ฃผ์„์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ๋„ ๊ต‰์žฅํ•œ ์ด์ ์œผ๋กœ ์ž‘์šฉํ•œ๋‹ค.
JSON ํŒŒ์ผ์€ ์ฃผ์„์„ ์ž‘์„ฑํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ํŒŒ์ผ ํ•˜๋‚˜๋งŒ ๋‘๊ณ  ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜ํ•˜๊ธฐ๊ฐ€ ๊นŒ๋‹ค๋กญ์ง€๋งŒ,
YAML ํŒŒ์ผ์€ ์• ์ดˆ์— ํŒŒ์ผ ๋‚ด์— ์ฃผ์„์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜ํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ์ˆ˜์›”ํ•˜๋‹ค.

๊ทธ๋ฆฌ๊ณ  YAML์€ JSON์˜ ์ƒ์œ„ ํ˜ธํ™˜ ๊ฒฉ์ด๋ฏ€๋กœ, ๊ธฐ์กด json๋ฌธ์„œ๋ฅผ ๊ทธ๋Œ€๋กœ yamlํŒŒ์ผ๋กœ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์›ํ•˜๋Š”
๋ถ€๋ถ„๋งŒ ์†๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ yaml์„ json์œผ๋กœ ๋ณ€ํ™˜ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ ์ด ์žฅ์ ์œผ๋กœ ์ž‘์šฉํ•œ๋‹ค.


YAML ๋ฌธ๋ฒ•


YAML๋„ ์ผ์ข…์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ๋ฒ•์ด ์žˆ๋‹ค.
ํ•ด๋‹น ๋ฌธ๋ฒ•์„ ์ง€์ผœ ์ž‘์„ฑํ•˜์ง€ ์•Š์œผ๋ฉด YAML ํŒŒ์ผ๋กœ ์ฝ์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ฌธ๋ฒ•์„ ์ž˜ ์ง€์ผœ์ค˜์•ผ ํ•œ๋‹ค.

๐Ÿ’ฌ ์ฃผ์„, ๋ฌธ์„œ์˜ ์‹œ์ž‘๊ณผ ๋
---------------------------------------------

`#`  : ์ฃผ์„
`---`  : ๋ฌธ์„œ์˜ ์‹œ์ž‘ (์„ ํƒ์‚ฌํ•ญ)
`...`  : ๋ฌธ์„œ์˜ ๋ (์„ ํƒ์‚ฌํ•ญ)


๐Ÿ’ฌ ๊ธฐ๋ณธ ํ‘œํ˜„
---------------------------------------------

key: value์ด๋ฉฐ, : ๋‹ค์Œ์—๋Š” ๋ฌด์กฐ๊ฑด ๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ์™€์•ผ ํ•œ๋‹ค.


๐Ÿ’ฌ ์ž๋ฃŒํ˜•
---------------------------------------------

`int`, `string`, `boolean`, ๋ฆฌ์ŠคํŠธ, ๋งคํ•‘์„ ์ง€์›ํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ int์™€ string ํƒ€์ž…์€ ์Šค์นผ๋ผ(Scalar)๋ผ ๋ถ€๋ฅด๊ณ , ๋ฐฐ์—ด ํ˜น์€ ๋ฆฌ์ŠคํŠธ๋Š” ์‹œํ€€์Šค(Sequence)๋ผ ๋ถ€๋ฅธ๋‹ค.
๋งคํ•‘์—๋Š” ๊ธฐ๋ณธ ํ‘œํ˜„์ธ key-value ์Œ ๋ฐ hash, dictionary๊ฐ€ ํฌํ•จ๋œ๋‹ค.

#int(์ˆซ์ž)
int_type: 1

#string(๋ฌธ์ž์—ด)
string_type: "1"

#blooean(์ฐธ/๊ฑฐ์ง“)
boolean_true_type: true
boolean_false_type: false

#์ด์™ธ์— yes, no๋กœ ์ž‘์„ฑํ•˜๊ธฐ๋„ ํ•œ๋‹ค.
yaml_easy: yes
yaml_difficult: no

#๋ฆฌ์ŠคํŠธ(๋ฐฐ์—ด ํ˜•ํƒœ)
person:
  name: Chungsub Kim
  job: Developer
  skills: 
    - docker
    - kubernetes
  # JSON ํ˜•์‹์˜ "skill" : [docker, kubernetes]์™€ ๊ฐ™๋‹ค.


๐Ÿ’ฌ ๊ฐ์ฒด
---------------------------------------------

๊ฐ์ฒด ํ‘œํ˜„์€ `key` ์ž‘์„ฑ ํ›„ ๋‘ ์นธ์„ ๋“ค์—ฌ์จ์„œ key-value ํ˜•ํƒœ๋กœ ์ž‘์„ฑ์„ ํ•ด์ฃผ๊ฑฐ๋‚˜,
`key`๋ฅผ ์ž‘์„ฑ ํ›„ ์ค‘๊ด„ํ˜ธ(`{}`)๋กœ ํ•œ ๋ฒˆ ๋ฌถ๊ณ  key-value ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•œ๋‹ค.

key: 
  key: value
  key: value

# ๋˜๋Š” ์ด๋ ‡๊ฒŒ๋„ ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด ์ž‘์„ฑํ•œ๋‹ค.
key: {
  key: value,
  key: value
}


๐Ÿ’ฌ Text
---------------------------------------------

์ค„๋ฐ”๊ฟˆ ํ‘œํ˜„(`|`)๊ณผ ์ค„๋ฐ”๊ฟˆ ๋ฌด์‹œ ํ‘œํ˜„(`>`)์ด ์žˆ๋‹ค.

# |๋Š” ์ค„๋ฐ”๊ฟˆ ํ‘œํ˜„์ด๋‹ค.
# JSON ํ˜•์‹์˜ "comment_line_break": "Hello codestates.\nIm kimcoding.\n"๊ณผ ๊ฐ™๋‹ค.
comment_line_break: |
  Hello codestates.
  Im kimcoding.

# >๋Š” ์ค„๋ฐ”๊ฟˆ ๋ฌด์‹œ ํ‘œํ˜„์ด๋‹ค.
# JSON ํ˜•์‹์˜ "comment_single_line": "Hello world my first coding."๊ณผ ๊ฐ™๋‹ค.
comment_single_line: >
  Hello world
  my first coding.
  
  
๐Ÿ’ฌ ๋ฌธ์ž์—ด ๋”ฐ์˜ดํ‘œ
---------------------------------------------

key-value ์Œ์—์„œ value์— `:`๊ฐ€ ๋“ค์–ด๊ฐ„ ๊ฒฝ์šฐ๋Š” ๋ฐ˜๋“œ์‹œ ๋”ฐ์˜ดํ‘œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

# error๊ฐ€ ๋‚œ๋‹ค.
windows_drive: c:

# ์ด๋ ‡๊ฒŒ ์จ์•ผ ํ•œ๋‹ค.
windows_drive: "c:"
windows_drive: 'c:'


๐Ÿ”ฅ ๊ณผ์ œ1. Github Action ์‹ค์Šต


๋‚˜๋งŒ์˜ ์•„๊ณ ๋ผ ์Šคํ…Œ์ด์ธ  ์„œ๋ฒ„์˜ ํด๋ผ์ด์–ธํŠธ ๋ถ€๋ถ„์„ S3๋กœ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.
ํŠœํ† ๋ฆฌ์–ผ์— ์ด์–ด์„œ ํ•ด๋‹น ์‹ค์Šต์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด์— ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋˜ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ด์šฉํ•ด ๋ด…์‹œ๋‹ค.

Github Actions๋ฅผ ํ†ตํ•œ ๋ฐฐํฌ Flow (ํด๋ผ์ด์–ธํŠธ)

์ด๋ฒˆ ํด๋ผ์ด์–ธํŠธ ๋ฐฐํฌ๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ 3๊ฐ€์ง€ ๋‹จ๊ณ„๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.

  • Source: Github reference ๋ธŒ๋žœ์น˜์— ์ฝ”๋“œ๊ฐ€ ์ปค๋ฐ‹๋˜๋ฉด
  • Build: github acitons์˜ YAML ํŒŒ์ผ์— ์ ํžŒ ๋ช…๋ น์–ด๋ฅผ ํ† ๋Œ€๋กœ Webpack์„ ์ด์šฉํ•ด ๋นŒ๋“œ๋ฅผ ํ•˜๊ณ 
  • Deploy: github acitons์˜ YAML ํŒŒ์ผ์— ์ ํžŒ ๋ช…๋ น์–ด๋ฅผ ํ† ๋Œ€๋กœ s3๋กœ ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฅผ ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ ์—ฌ๋Ÿฌ๋ถ„์˜ S3๋Š” ๋ฐฐํฌ๋ฅผ ์œ„ํ•ด ์ถฉ๋ถ„ํžˆ ์ค€๋น„๋˜์–ด ์žˆ์Œ์œผ๋กœ, s3๋กœ ํŒŒ์ผ๋งŒ ์ž˜ ์ „๋‹ฌํ•˜๋ฉด ์ถฉ๋ถ„ํžˆ ๋ฐฐํฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฐจ๊ทผ์ฐจ๊ทผ ๊ณ ๋ฏผํ•˜๋ฉด์„œ ์•„๋ž˜ ์ฝ”๋“œ์˜ <?> ์„ ์ฑ„์›Œ๋ณด์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

# .github/workflows/client.yml
name: client
on:
  push:
    branches:
      - <?>
jobs:
  build:
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout source code.
        uses: actions/checkout@v2
      - name: Install dependencies
        run: <?>
        working-directory: ./my-agora-states-client-react
      - name: Build
        run: <?>
        working-directory: ./my-agora-states-client-react
      - name: SHOW AWS CLI VERSION
        run: |
          <?>
      - name: Sync Bucket
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_EC2_METADATA_DISABLED: true
        run: |
          aws s3 <?> \
            --region ap-northeast-2 \
            build s3://<?> \
            --delete
        working-directory: <?>


๐Ÿ’ฌ Sprint Review


๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ, ๊ณผ์ •์ด๋‚˜ ์ถ”๊ฐ€ ์„ค๋ช…์„ ๋ง๋ถ™์ด๊ฒ ๋‹ค.

1. ์›๊ฒฉ ๋ ˆํฌ์ง€ํ† ๋ฆฌ Clone & Push ์„ธํŒ…


ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์›๋ณธ ๋ ˆํผ์ง€ํ† ๋ฆฌ๋ฅผ ํด๋ก ํ•œ ํ›„,
๋ฏธ๋ฆฌ ๋งŒ๋“  ์›๊ฒฉ ๋ ˆํผ์ง€ํ† ๋ฆฌ๋กœ ํ‘ธ์‹œํ•ด์ค€๋‹ค.

๊ทธ๋Ÿผ ๋ฐ”๋กœ Github์—์„œ ํ™•์ธ ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ฐ”๋กœ Actions ํƒญ์—์„œ ๊ธฐ์กด์— ๋งŒ๋“ค์–ด์ ธ์žˆ๋˜, yml ํŒŒ์ผ์ด push๋ฅผ ๊ฐ์ง€ํ•ด์„œ Action์ด ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.



2. Actions secrets key ์„ค์ •


์ด์ œ yml ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๊ธฐ ์ „์—, ํ˜„์žฌ ๋ ˆํผ์ง€ํ† ๋ฆฌ์— Action์— ๋Œ€ํ•œ key๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

secrets ๋ช…์€ ๊ณผ์ œ yml ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์•Œ๊ฒ ์ง€๋งŒ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ฐ’์œผ๋กœ ์ „๋‹ฌ๋ฐ›๊ธฐ ์œ„ํ•ด์„œ ์ •ํ™•ํ•˜๊ฒŒ ๊ฐ™๋„๋ก ์„ค์ •ํ–ˆ๋‹ค.

AWS ์ ‘๊ทผ ํ‚ค์™€ ๊ฐ™์€ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.

๋‹น์—ฐํžˆ ์ด๋ ‡๊ฒŒ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•˜๋Š” ์ด์œ ๋Š” ๋ณด์•ˆ์„ ์œ„ํ•จ์ด๋ฉฐ,
GitHub Secrets๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GitHub ์ €์žฅ์†Œ์˜ ์„ค์ •์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌ๋  ๊ฒƒ์ด๋‹ค.

๋งŒ์•ฝ, AWS ์ ‘๊ทผ ํ‚ค๋ฅผ ์„ค์ •ํ•ด์ฃผ์ง€ ์•Š๋Š”๋‹ค๋ฉด Action build ๊ณผ์ •์—์„œ ์ด๋ ‡๊ฒŒ ์—๋Ÿฌ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.



3. yml ํŒŒ์ผ ์ž‘์„ฑ (GitHub Actions workflow)


์ด์ œ ๋ฐ”๋กœ yml ํŒŒ์ผ์„ ์ž‘์„ฑํ•œ๋‹ค.

GitHub Actions workflow๋กœ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋นŒ๋“œํ•˜๊ณ  AWS S3 ๋ฒ„ํ‚ท์— ๋ฐฐํฌํ•˜๋Š” ์„ค์ •์„ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

name: Fronted Client Deploy

on:
  push:
    branches: [reference]

jobs:
  build:
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout source code.
        uses: actions/checkout@v2
      - name: Install dependencies
        run: npm install
        working-directory: ./my-agora-states-client-react
      - name: Build
        run: npm run build
        working-directory: ./my-agora-states-client-react
      - name: SHOW AWS CLI VERSION
        run: |
          aws --version
      - name: Sync Bucket
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_EC2_METADATA_DISABLED: true
        run: |
          aws s3 sync \
            --region ap-northeast-2 \
            build s3://fe-2-widrns15-s3 \
            --delete
        working-directory: ./my-agora-states-client-react


branches๋Š” ํ˜„์žฌ ๋ฐฐํฌํ•  ๋ธŒ๋žœ์น˜์ธ reference๋กœ ์„ค์ •ํ–ˆ๊ณ ,
๊ฐ๊ฐ npm install, npm run build๋ฅผ ์ƒํ™ฉ์— ๋งž๊ฒŒ ๋„ฃ์–ด์คฌ๋‹ค.

ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ง€์ •๋  AWS_ACCESS_KEY_ID์™€ AWS_SECRET_ACCESS_KEY ๊ฐ’์€
secrets์—์„œ ๋ถˆ๋Ÿฌ์™€์„œ ํ• ๋‹น๋˜๋„๋ก ์•Œ๋งž๊ฒŒ ์ง€์ •ํ•ด์ค€๋‹ค.

์œ„์—์„œ key ๋ช…์„ ์ €๋ ‡๊ฒŒ ์ง€์€ ์ด์œ ๋Š” ์œ„ ์ฝ”๋“œ์™€ ๊ฐ™๊ฒŒ ํ•ด์ฃผ๊ธฐ ์œ„ํ•จ์ด์—ˆ๋‹ค.

์ด์ œ ์„ค์ •์€ ๋‹ค ๋งˆ์ณค๋‹ค.

์ปค๋ฐ‹ ๋ฉ”์„ธ์ง€๋„ ์•Œ๋งž๊ฒŒ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ์™„์ „ํžˆ ๋์ด๋‹ค. ์ด์ œ Actions ์ดˆ๊ธฐ ํƒญ์œผ๋กœ ๋Œ์•„๊ฐ€์„œ ํ™•์ธํ•ด๋ณด์ž.

์ •์ƒ์ ์œผ๋กœ build๊ฐ€ ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ 

์กฐ๊ธˆ ๊ธฐ๋‹ค๋ฆฌ๋ฉด ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.



4. AWS S3 ๋ฐฐํฌ ํ™•์ธ


๋งํฌ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์˜๋ฌธ์ด ํ•˜๋‚˜ ์žˆ์—ˆ๋‹ค.

์ €๋ฒˆ ์œ ๋‹›์—์„œ S3 ๋ฒ„ํ‚ท์— ์—…๋กœ๋“œํ–ˆ๋˜ ํŒŒ์ผ๋„ ๊ทธ๋Œ€๋กœ ์žˆ๊ณ , ๋งํฌ๋„ ๊ทธ๋Œ€๋กœ๋ผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌ๋ ์ง€๊ฐ€ ์˜๋ฌธ์ด์—ˆ๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ ๊ฑฑ์ •๊ณผ ๋‹ค๋ฅด๊ฒŒ, ๋ฐฉ๊ธˆ ๋ฐฐํฌํ•œ ํด๋ผ์ด์–ธํŠธ ํŒŒ์ผ์ด ์ •์ƒ์ ์œผ๋กœ ๋ฎ์–ด์”Œ์›Œ์ ธ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.
ํ›„์— ๋‹ค์‹œ ์—…๋กœ๋“œํ–ˆ๋˜ ํŒŒ์ผ์„ ์‚ญ์ œํ•˜๊ณ  ์žฌ์—…๋กœ๋“œํ–ˆ๋”๋‹ˆ, ๋‹ค์‹œ ์ €๋ฒˆ ์œ ๋‹› ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.



Proxy


CORS ์ •์ฑ…์ด ํ•„์š”ํ•œ ์ด์œ 

๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ API๋ฅผ ์š”์ฒญํ•  ๋•Œ์—, ๋ธŒ๋ผ์šฐ์ €์˜ ํ˜„์žฌ ์ฃผ์†Œ์™€
API์˜ ์ฃผ์†Œ์˜ ๋„๋ฉ”์ธ์ด ์ผ์น˜ํ•ด์•ผ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ์žˆ๋‹ค.

๋งŒ์•ฝ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์—์„œ API๋ฅผ ์š”์ฒญํ•ด์„œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, CORS ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์ด์ „ ์„น์…˜์—์„œ ๋‹ค๋ค˜์—ˆ๋‹ค.

  • ๐Ÿ’ก CORS

    • ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (Cross-Origin Resource Sharing, CORS)๋Š” ์ถ”๊ฐ€ HTTP ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ,
      ํ•œ ์ถœ์ฒ˜์—์„œ ์‹คํ–‰ ์ค‘์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์„ ํƒํ•œ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €์— ์•Œ๋ ค์ฃผ๋Š” ์ฒด์ œ์ด๋‹ค.
  • ๐Ÿ’ก ์ถœ์ฒ˜

    • ์›น ์ฝ˜ํ…์ธ ์˜ ์ถœ์ฒ˜(origin)๋Š” ์ ‘๊ทผํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” URL์˜ ์Šคํ‚ด(ํ”„๋กœํ† ์ฝœ), ํ˜ธ์ŠคํŠธ(๋„๋ฉ”์ธ), ํฌํŠธ๋กœ ์ •์˜๋œ๋‹ค.
      ๋‘ ๊ฐ์ฒด์˜ ์Šคํ‚ด, ํ˜ธ์ŠคํŠธ, ํฌํŠธ๊ฐ€ ๋ชจ๋‘ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐ™์€ ์ถœ์ฒ˜๋ฅผ ๊ฐ€์กŒ๋‹ค๊ณ  ๋งํ•œ๋‹ค.
      ์ผ๋ถ€ ์ž‘์—…์€ ๋™์ผ ์ถœ์ฒ˜ ์ฝ˜ํ…์ธ ๋กœ ์ œํ•œ๋˜๋‚˜, CORS๋ฅผ ํ†ตํ•ด ์ œํ•œ์„ ํ•ด์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•œ ์•ฑ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ localhost:3000์œผ๋กœ ์‹œ์ž‘ํ•œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚˜์ค‘์— ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•œ ์‹ค์ œ ์„œ๋น„์Šค ๋ฐ ํ”„๋กœ์ ํŠธ์˜ ํด๋ผ์ด์–ธํŠธ์—์„œ
์„œ๋ฒ„์˜ API๋กœ ์š”์ฒญํ•˜๊ฒŒ ๋˜๋ฉด, ์ด ํฌํŠธ๋กœ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด ์ฐจ๋‹จ๋  ๊ฒƒ์ด๋‹ค.

๋งŒ์ผ ์‹ค์ œ ์„œ๋น„์Šค๊ฐ€ ๋˜๋Š” ์ƒ์šฉ ์•ฑ์„ ์šด์˜ ์ค‘์ด๋ผ๋ฉด, ๊ตฌ์ถ•ํ•œ ํด๋ผ์ด์–ธํŠธ ๋’ค์˜
์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š” DB์—๋Š” ๋ผ์ด๋ธŒ ๋ฐ์ดํ„ฐ(live data)๊ฐ€ ์Œ“์ผ ๊ฒƒ์ด๋‹ค.

  • ๐Ÿ’ก ๋ผ์ด๋ธŒ ๋ฐ์ดํ„ฐ(live data)
    • ์‹ค์ œ ์„œ๋น„์Šค๋˜๊ณ  ์žˆ๋Š” ์•ฑ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(Data Base, DB)์— ์ ์žฌ๋˜๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
      ์œ ์ € ๋ฐ ์ƒํ’ˆ, ๊ฒฐ์ œ ๋“ฑ ๋‹ค์–‘ํ•œ ์ •๋ณด๋“ค์„ ์˜ˆ๋กœ ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์ด๋Ÿฐ ๋ผ์ด๋ธŒ ๋ฐ์ดํ„ฐ๋Š” ๋ฏผ๊ฐ์„ฑ์ด ๋†’์€ ๋ฐ์ดํ„ฐ๋“ค์ด ์œ„์ฃผ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์•ˆ์ด ๋ฌด์—‡๋ณด๋‹ค ์ค‘์š”ํ•˜๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์„œ๋น„์Šค ๋ฐ ํ”„๋กœ์ ํŠธ๊ฐ€ ๋ชจ๋“  ์ถœ์ฒ˜์˜ ์ ‘๊ทผ์„ ํ—ˆ๋ฝํ•œ๋‹ค๋ฉด ์ด๋Ÿฌํ•œ
๋ณด์•ˆ์„ฑ์ด ํ˜„์ €ํžˆ ๋‚ฎ์•„์ง€๊ณ , ํ•ดํ‚น์˜ ์œ„ํ—˜์— ๊ทธ๋Œ€๋กœ ๋…ธ์ถœ๋˜๊ฒŒ ๋œ๋‹ค.

๋”ฐ๋ผ์„œ ๋ชจ๋“  ๋„๋ฉ”์ธ์„ ํ—ˆ์šฉํ•ด์„œ๋Š” ์•ˆ ๋˜๊ณ , ํŠน์ • ๋„๋ฉ”์ธ์„ ํ—ˆ์šฉํ•˜๋„๋ก ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ ์„œ๋ฒ„ ๋„๋ฉ”์ธ์„ ํ—ˆ์šฉํ•ด ๋‹ฌ๋ผ๊ณ 
์š”์ฒญ์„ ํ•ด์•ผ ํ•˜๊ณ ,๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž๋Š” ์‘๋‹ต ํ—ค๋”์— ํ•„์š”ํ•œ ๊ฐ’๋“ค์„ ๋‹ด์•„์„œ ์ „๋‹ฌ์„ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

์„œ๋ฒ„์—์„œ ์ ์ ˆํ•œ ์‘๋‹ต ํ—ค๋”๋ฅผ ๋ฐ›์ง€ ๋ชปํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


Proxy

๊ทธ๋Ÿฌ๋‚˜ ์œ„์˜ ๊ณผ์ • ์—†์ด React ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ํ˜น์€ Webpack Dev Server์—์„œ
์ œ๊ณตํ•˜๋Š” proxy ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด CORS ์ •์ฑ…์„ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋Š” ๋ณ„๋„์˜ ์‘๋‹ต ํ—ค๋”๋ฅผ ๋ฐ›์„ ํ•„์š” ์—†์ด ๋ธŒ๋ผ์šฐ์ €๋Š” React ์•ฑ์œผ๋กœ
๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ , ํ•ด๋‹น ์š”์ฒญ์„ ๋ฐฑ์—”๋“œ๋กœ ์ „๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค.

์—ฌ๊ธฐ์„œ React ์•ฑ์ด ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์—
๋ธŒ๋ผ์šฐ์ €๋Š” CORS ์ •์ฑ…์„ ์œ„๋ฐ˜ํ–ˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒŒ ๋œ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋ฅผ proxy ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์†์ด๋Š” ๊ฒƒ์ด๋‹ค.

์œ„์˜ ๊ทธ๋ฆผ์€ proxy๋ฅผ ์ ์šฉํ•ด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์†์ด๊ธฐ ์ „ ํ๋ฆ„์ด๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ๊ฐœ๋ฐœํ•œ React ์•ฑ์—์„œ ๋ธŒ๋ผ์šฐ์ € ์ชฝ์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ฐฑ์—”๋“œ, ์ฆ‰ ์„œ๋ฒ„ ์ชฝ์œผ๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋•Œ ์ ‘๊ทผ ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€, ์ฆ‰ ์ถœ์ฒ˜๊ฐ€ ๊ฐ™์€์ง€ ํ™•์ธํ•˜๋Š”๋ฐ ์ด๋•Œ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋Š” ์ •์ƒ์ ์œผ๋กœ 200 OK ์‘๋‹ต์„ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ๋ณด๋‚ธ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ฐ›์€ ๋ฆฌ์†Œ์Šค ๋ฐ ์‘๋‹ต๊ณผ ํ•จ๊ป˜ ์ถœ์ฒ˜๊ฐ€ ๊ฐ™์€์ง€ ์•„๋‹Œ์ง€ ํ™•์ธํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋•Œ ์ถœ์ฒ˜๊ฐ€ ๋‹ค๋ฅด๋‹ค๋ฉด ์‘๋‹ต์„ ํŒŒ๊ธฐ(CORS Error) ํ•˜๊ณ , ์ถœ์ฒ˜๊ฐ€ ๊ฐ™๋‹ค๋ฉด ์‘๋‹ต์„ ํŒŒ๊ธฐํ•˜์ง€ ์•Š๊ณ  ๋‹ค์‹œ ํ”„๋ก ํŠธ์—”๋“œ ์ชฝ์œผ๋กœ ์‘๋‹ต์„ ๋ณด๋‚ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

์œ„์˜ ๊ทธ๋ฆผ์€ proxy๋ฅผ ์ ์šฉํ•ด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์†์ธ ํ›„ ํ๋ฆ„์ด๋‹ค. React ์•ฑ์—์„œ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด API๋ฅผ ์š”์ฒญํ•  ๋•Œ, proxy๋ฅผ ํ†ตํ•ด ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ์šฐํšŒํ•˜์—ฌ ๋ณด๋‚ด๊ฒŒ ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋Š” ์‘๋‹ต์„ React ์•ฑ์œผ๋กœ ๋ณด๋‚ด๊ณ , React ์•ฑ์€ ๋ฐ›์€ ์‘๋‹ต์„ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ๋Œ€์‹  ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ถœ์ฒ˜๊ฐ€ ๊ฐ™์•„์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ €๋Š” ์ด ์‚ฌ์‹ค์„ ๋ˆˆ์น˜์ฑ„์ง€ ๋ชปํ•˜๊ณ  ํ—ˆ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.



Proxy ์‚ฌ์šฉ๋ฒ•


์˜ค๋Š˜์€ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ Proxy๋ฅผ ๋‹ค๋ค„๋ณผ ๊ฒƒ์ด๋‹ค.

  • webpack dev server proxy
  • http-proxy-middleware ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

webpack dev server proxy


๋จผ์ € webpack dev server์—์„œ ์ œ๊ณตํ•˜๋Š” proxy ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

webpack dev server์˜ proxy๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, ๋ธŒ๋ผ์šฐ์ € API๋ฅผ ์š”์ฒญํ•  ๋•Œ
๋ฐฑ์—”๋“œ ์„œ๋ฒ„์— ์ง์ ‘์ ์œผ๋กœ ์š”์ฒญ์„ ํ•˜์ง€ ์•Š๊ณ , ํ˜„์žฌ ๊ฐœ๋ฐœ์„œ๋ฒ„์˜ ์ฃผ์†Œ๋กœ ์šฐํšŒ ์š”์ฒญ์„ ํ•˜๊ฒŒ ๋œ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์›นํŒฉ ๊ฐœ๋ฐœ ์„œ๋ฒ„์—์„œ ํ•ด๋‹น ์š”์ฒญ์„ ๋ฐ›์•„ ๊ทธ๋Œ€๋กœ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๊ณ ,
๋ฐฑ์—”๋“œ ์„œ๋ฒ„์—์„œ ์‘๋‹ตํ•œ ๋‚ด์šฉ์„ ๋‹ค์‹œ ๋ธŒ๋ผ์šฐ์ € ์ชฝ์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์›นํŒฉ ๊ฐœ๋ฐœ์„œ๋ฒ„์˜ proxy ์„ค์ •์€ ์›๋ž˜ ์›นํŒฉ ์„ค์ •์„ ํ†ตํ•ด์„œ ์ ์šฉ์„ ํ•˜์ง€๋งŒ, CRA๋ฅผ ํ†ตํ•ด ๋งŒ๋“  ๋ฆฌ์•กํŠธ
ํ”„๋กœ์ ํŠธ์—์„œ๋Š” package.json ์—์„œ "proxy" ๊ฐ’์„ ์„ค์ •ํ•˜์—ฌ ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑ์ด ๋˜์–ด ์žˆ๋‹ค.

...

"browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
	"proxy" : "์šฐํšŒํ•  API ์ฃผ์†Œ"
}


๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด์˜ fetch, ํ˜น์€ axios๋ฅผ ํ†ตํ•ด ์š”์ฒญํ•˜๋˜ ๋ถ€๋ถ„์—์„œ ๋„๋ฉ”์ธ ๋ถ€๋ถ„์„ ์ œ๊ฑฐํ•œ๋‹ค.

// ๋ณ€๊ฒฝ ์ „
export async function getAllfetch() {

    const response = await fetch('์šฐํšŒํ•  api์ฃผ์†Œ/params');
    .then(() => {
			...
		})
}

// ๋ณ€๊ฒฝ ํ›„
export async function getAllfetch() {

    const response = await fetch('/params');
    .then(() => {
			...
		})
}


React Proxy ์‚ฌ์šฉ๋ฒ•


webpack dev server์—์„œ ์ œ๊ณตํ•˜๋Š” proxy๋Š” ์ „์—ญ์ ์ธ ์„ค์ •์ด๊ธฐ ๋•Œ๋ฌธ์—,
์ข…์ข… ํ•ด๋‹น ๋ฐฉ๋ฒ•์ด ์ถฉ๋ถ„ํžˆ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธฐ๊ธฐ๋„ ํ•œ๋‹ค.

๊ทธ๋ž˜์„œ ์ˆ˜๋™์œผ๋กœ proxy๋ฅผ ์ ์šฉํ•ด์ค˜์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ,
์ด๋•Œ๋Š” http-proxy-middleware ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

http-proxy-middleware ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

npm install http-proxy-middleware --save


๊ทธ๋ฆฌ๊ณ  React App์˜ src ํŒŒ์ผ ์•ˆ์—์„œ setupProxy.js ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ ,
์•ˆ์—์„œ ์„ค์น˜ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜จ ๋‹ค์Œ, ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑ์„ ํ•œ๋‹ค.

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api', // proxy๊ฐ€ ํ•„์š”ํ•œ path prameter๋ฅผ ์ž…๋ ฅํ•œ๋‹ค.
    createProxyMiddleware({
      target: 'http://localhost:5000', // ํƒ€๊ฒŸ์ด ๋˜๋Š” api url๋ฅผ ์ž…๋ ฅํ•œ๋‹ค.
      changeOrigin: true, // ๋Œ€์ƒ ์„œ๋ฒ„ ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ํ˜ธ์ŠคํŠธ ํ—ค๋”๊ฐ€ ๋ณ€๊ฒฝ๋˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค.
    })
  );
};


๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด์˜ fetch, ํ˜น์€ axios๋ฅผ ํ†ตํ•ด ์š”์ฒญํ•˜๋˜ ๋ถ€๋ถ„์—์„œ ๋„๋ฉ”์ธ ๋ถ€๋ถ„์„ ์ œ๊ฑฐํ•œ๋‹ค.
๋ฐ‘์˜ ๋ถ€๋ถ„์€ webpack dev server์—์„œ ์ œ๊ณตํ•˜๋Š” proxy ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋™์ผํ•˜๋‹ค.

// ๋ณ€๊ฒฝ ์ „
export async function getAllfetch() {

    const response = await fetch('์šฐํšŒํ•  api์ฃผ์†Œ/params');
    .then(() => {
			...
		})
}

// ๋ณ€๊ฒฝ ํ›„
export async function getAllfetch() {

    const response = await fetch('/params');
    .then(() => {
			...
		})
}


๐Ÿ”ฅ ๊ณผ์ œ2. Proxy๋ฅผ ์„ค์ •ํ•ด HTTP ํ†ต์‹ ํ•˜๊ธฐ


์•ž์„œ proxy์— ๋Œ€ํ•ด ๋ฐฐ์›Œ๋ณด์•˜์Šต๋‹ˆ๋‹ค.
proxy๋ฅผ ์ž˜ ์„ค์ •ํ•˜๋ฉด CORS ์ •์ฑ…์„ ์šฐํšŒํ•˜์—ฌ ๊ฐœ๋ฐœ ๋‹จ๊ณ„์—์„œ๋„ http ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ”ฅ Bare Minimum Requirement

์—ฌ๊ธฐ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋กœ ๋“ค์–ด๊ฐ€ git clone ํ•œ ๋’ค, ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋ฐฑ์—”๋“œ์˜ ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์—ญํ• ์„ ํ•ด์ค„ api์™€, ํ”„๋ก ํŠธ์—”๋“œ์˜ ๊ฐœ๋ฐœ
์„œ๋ฒ„ ์—ญํ• ์„ ํ•ด์ค„ my-app์— ๊ฐ๊ฐ ์ ‘๊ทผํ•˜์—ฌ npm install์„ ํ•ฉ๋‹ˆ๋‹ค.

cd api
npm install

cd my-app
npm install


์ด์–ด api์— ์ ‘๊ทผํ•œ ํ„ฐ๋ฏธ๋„์—์„œ๋Š” npm run dev๋ฅผ,
my-app์— ์ ‘๊ทผํ•œ ํ„ฐ๋ฏธ๋„์—์„œ๋Š” npm start๋ฅผ ํ†ตํ•ด ๊ฐ๊ธฐ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์—ฝ๋‹ˆ๋‹ค.

//api terminal
npm run dev

//my-app terminal
npm start


๊ทธ๋Ÿฌ๋ฉด ํ„ฐ๋ฏธ๋„์ด ๊ฐ๊ธฐ ์ด๋Ÿฐ ํ™”๋ฉด์œผ๋กœ ์—ฌ๋Ÿฌ๋ถ„์„ ๋งž์ดํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋‹ค์Œ http://localhost:3000/์œผ๋กœ ์ด๋™ํ•ด๋ด…์‹œ๋‹ค.

์ด ์ƒํƒœ์—์„œ ํด๋ผ์ด์–ธํŠธ Get all Books๋ผ๊ณ  ์“ฐ์—ฌ ์žˆ๋Š” ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋ด…์‹œ๋‹ค.

CORS ์—๋Ÿฌ๊ฐ€ ๋œจ๋ฉฐ ์‘๋‹ต์„ ์ œ๋Œ€๋กœ ๋ฐ›์•„์˜ค์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๋‹จ๊ณ„์—์„œ๋ถ€ํ„ฐ proxy ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด ํŽ˜์–ด์™€ ํ•จ๊ป˜ CORS ์—๋Ÿฌ๋ฅผ ํ•ด๊ฒฐํ•ด ๋‚˜๊ฐˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ณผ์ œ1

ํŽ˜์–ด์™€ ํ•จ๊ป˜ webpack dev server์˜ proxy ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด ์šฐํšŒํ•˜์—ฌ ์‘๋‹ต์„ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค.


๊ณผ์ œ2

๋ ˆํฌ์ง€ํ† ๋ฆฌ๋กœ ๋ฐ›์•„์˜จ ๊ณผ์ œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด api2๋ผ๋Š” ํด๋”๊ฐ€ ์กด์žฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ํ”„๋กœ์ ํŠธ ๋ฐ ์‹ค๋ฌด๋ฅผ ํ•  ๋•Œ, ํ•˜๋‚˜์˜ ๋„๋ฉ”์ธ์ด ์•„๋‹Œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋„๋ฉ”์ธ์—์„œ ์‘๋‹ต์„ ๋ฐ›์•„์™€์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ข…์ข… ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿด ๋•Œ๋Š” ์œ ์—ฐํ•˜๊ฒŒ proxy๋ฅผ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํŽ˜์–ด์™€ ํ•จ๊ป˜ webpack dev server์˜ proxy ๊ธฐ๋Šฅ ๋Œ€์‹  http-proxy-middleware์˜
    proxy ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ proxy๋ฅผ ์œ ์—ฐํžˆ ์„ค์ •ํ•ด 2๊ฐœ์˜ ๋„๋ฉ”์ธ์—์„œ ๋ชจ๋‘ ์‘๋‹ต์„ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค.
  • ํŽ˜์–ด์™€ ํ•จ๊ป˜ api2์— ๊ด€๋ จ๋œ fetch ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ , ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•˜๋‚˜ ์ด์ƒ ๋งŒ๋“ค์–ด
    2๊ฐœ์˜ ๋„๋ฉ”์ธ์—์„œ ๋ชจ๋‘ ์‘๋‹ต์„ ๋ฐ›์•„์˜ค๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ด๋ด…๋‹ˆ๋‹ค.


๐Ÿ’ฌ Sprint Review


๊ณผ์ œ๋Š” ์ด 2๊ฐœ๋กœ ์œ„ ๊ณผ์ œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ณผ์ •๊ณผ ์ถ”๊ฐ€ ์„ค๋ช…์„ ๋ง๋ถ™์ด๊ฒ ๋‹ค.

๋จผ์ € ๊ฒฐ๊ณผ ์ „์ฒด ์ฝ”๋“œ๋ฅผ CodeSandbox๋กœ ์ฒจ๋ถ€ํ•ด๋‘๊ฒ ๋‹ค.




๊ณผ์ œ 1


webpack dev server๋Š” package.json์— proxy๋ฅผ ์„ค์ •ํ•ด์ฃผ๊ณ ,
src ํด๋” ์•ˆ์— ์žˆ๋Š” BookService์—์„œ ๋„๋ฉ”์ธ ๋ถ€๋ถ„์„ ์ œ๊ฑฐํ•ด์„œ ๊ฐ„ํŽธํ•˜๊ฒŒ ๊ตฌํ˜„ํ–ˆ๋‹ค.

ํ›„์— ํ„ฐ๋ฏธ๋„์—์„œ api๋Š” npm run dev๋กœ my-app(client)๋Š” npm start๋กœ ๊ฐ๊ฐ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ํฌํŠธ๋ฅผ ์—ด์—ˆ๋‹ค.

Get all Books ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋„ ์—๋Ÿฌ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š์œผ๋ฉฐ, ์ •์ƒ์ ์œผ๋กœ ์ถ”๊ฐ€๊นŒ์ง€ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.


๊ณผ์ œ 2


๊ณผ์ œ 2๋Š” ์ถ”๊ฐ€์ ์œผ๋กœ api2๊นŒ์ง€ ๋‹ค๋ฃจ๋ฏ€๋กœ, ToDo๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์„œ
api2 ๋„๋ฉ”์ธ์„ fetch ํ•ด์˜ค๋Š”์ง€ ์œก์•ˆ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  http-proxy-middleware ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ด์ฃผ์—ˆ์œผ๋ฉฐ,
package.json์—์„œ ์„ค์ •ํ•ด์ฃผ์—ˆ๋˜ proxy๋ฅผ ์ง€์›Œ์ฃผ์—ˆ๋‹ค.

์ด์ œ ์ด ์—ญํ• ์€ ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ setupProxy๊ฐ€ ํ•  ๊ฒƒ์ด๋‹ค.

// setupProxy.js

const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = function (app) {
  app.use(
    ["/api", "/api2"],
    createProxyMiddleware({
      target: process.env.REACT_APP_API_URL,
      changeOrigin: true,
      router: {
        "/api2": process.env.REACT_APP_API_URL2,
      },
    })
  );
};


๋„๋ฉ”์ธ์€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์œผ๋ฉฐ, ๋‘ ๋„๋ฉ”์ธ์„ ํ•˜๋‚˜์ฒ˜๋Ÿผ ๋ฌถ์–ด์ฃผ์—ˆ๋‹ค.

์ดํ›„ package.json์—์„œ ๊ธฐ์กด webpack dev server proxy๋ฅผ ์ง€์›Œ์ฃผ์—ˆ๋Š”๋ฐ๋„
api, api2, client port๋ฅผ ์ „์ฒด ์ผœ๊ณ  ํ…Œ์ŠคํŠธํ•ด๋ณด๋‹ˆ ์ •์ƒ์ ์œผ๋กœ ์ง„ํ–‰๋˜์—ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ์ถ”๊ฐ€์ ์œผ๋กœ ๊ตฌํ˜„ํ•œ ToDo ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ธฐ์กด๊ณผ ํ•ฉ์ณ ์ •์ƒ์ ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ๊ณ ,
์„œ๋ฒ„์—์„œ ์ •์ƒ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ๋ฟŒ๋ ค์คฌ๋‹ค. ์ถ”๊ฐ€๋กœ ํ„ฐ๋ฏธ๋„์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ด ์ƒํ™ฉ์„ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ •์ƒ์ ์œผ๋กœ http-proxy-middleware ๊ตฌํ˜„์„ ๋งˆ์นœ ๊ฒƒ์ด๋‹ค !



๐Ÿ’ก Error Note.


๐Ÿ’ก http-proxy-middleware๋ฅผ ์“ฐ๋Š” ์ด์œ _#Remind

  • api๋Š” ๊ธฐ์กด์— **webpack dev server proxy**๋กœ CORS ์ •์ฑ…์„ ํ”ผํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.
  • โœจ ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์„ ๊ฐ€์ง„ api2๋ฅผ ๋™์‹œ์— ๋‹ค๋ฃจ๋ ค๋ฉด ๋˜ ๋‹ค์‹œ CORS ์ •์ฑ…์— ๊ฑธ๋ฆฌ๊ฒŒ ๋œ๋‹ค.
  • โœจ ๋”ฐ๋ผ์„œ http-proxy-middleware๋ฅผ ์‚ฌ์šฉํ•ด์„œ api, api2๊ฐ€
    ๊ฐ™์€ ๋„๋ฉ”์ธ์—์„œ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋„๋ก ํ•  ์ˆ˜ ์žˆ์–ด CORS ์ •์ฑ…์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ‘‰ http-proxy-middleware๋Š” ์›น ๊ฐœ๋ฐœ ์‹œ, ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ
ํ”„๋ก์‹œ(proxy) ์„ค์ •์„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” Node.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

์›นํŒฉ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋‚˜ ๋‹ค๋ฅธ ์„œ๋ฒ„ ์‚ฌ์ด์— ์žˆ๋Š” API ์„œ๋ฒ„ ๋˜๋Š” ๋‹ค๋ฅธ ํ˜ธ์ŠคํŠธ์— ๋Œ€ํ•œ ์š”์ฒญ์„ ํ”„๋ก์‹œํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

  • ์ฃผ์š”ํ•œ ์ƒํ™ฉ๊ณผ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:

  1. CORS(Cross-Origin Resource Sharing) ์ด์Šˆ ํ•ด๊ฒฐ: ์›น ๊ฐœ๋ฐœ ์ค‘์—, ๋ณด์•ˆ ์ƒ์˜ ์ด์œ ๋กœ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์— ๋Œ€ํ•œ AJAX ์š”์ฒญ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฐจ๋‹จ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœ ์„œ๋ฒ„์™€ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๊ฐ€ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์— ์œ„์น˜ํ•ด ์žˆ๋‹ค๋ฉด, ๋ธŒ๋ผ์šฐ์ €์—์„œ AJAX ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ CORS ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋•Œ http-proxy-middleware๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ ์„œ๋ฒ„์—์„œ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ํ”„๋ก์‹œํ•˜๋ฉด, ๊ฐ™์€ ๋„๋ฉ”์ธ์—์„œ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ์„œ๋ฒ„ ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ: ๊ฐœ๋ฐœ ์ค‘์—๋Š” ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ํŠน์ • ๊ฒฝ๋กœ์— ๋Œ€ํ•œ ์š”์ฒญ์„ ํ”„๋ก์‹œํ•˜์—ฌ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ๊ฐœ๋ฐœ ์‹œ ๋ฐฑ์—”๋“œ API๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์ง์ ‘ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„๋„ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ ํšจ์œจ์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.
  3. ๋กœ์ปฌ ๊ฐœ๋ฐœ ์„œ๋ฒ„์™€์˜ ์—ฐ๋™: ์ผ๋ถ€ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” ์›นํŒฉ ๊ฐœ๋ฐœ ์„œ๋ฒ„์™€ API ์„œ๋ฒ„ ๋˜๋Š” ๋‹ค๋ฅธ ์„œ๋ฒ„๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ์ด ๋•Œ ํ”„๋ก์‹œ ์„ค์ •์„ ํ†ตํ•ด ๊ฐœ๋ฐœ ์„œ๋ฒ„์—์„œ API ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ์ „๋‹ฌํ•˜๋ฉด, ๋ณ„๋„์˜ ๋„๋ฉ”์ธ ๋˜๋Š” ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๋ถˆํŽธํ•จ์„ ํ•ด์†Œํ•  ์ˆ˜ ์žˆ๋‹ค.
profile
์•„์ด๋””์–ด๊ฐ€ ๋„˜์น˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ฟˆ๊ฟ‰๋‹ˆ๋‹ค ๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€