CD - 100-hours-a-week/21-iceT-wiki GitHub Wiki

3๋‹จ๊ณ„: CD(์ง€์†์  ๋ฐฐํฌ) ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•


1. CD ๋„์ž… ์ด์œ 

1. ๋ฐฐํฌ ์†๋„ ๋ฐ ์ •ํ™•์„ฑ ํ–ฅ์ƒ

  • ๊ธฐ์กด Koco ์„œ๋น„์Šค์—๋Š” ๋กœ์ปฌ ๋นŒ๋“œ โ†’ SCP ์ „์†ก ๋ฐ SSH ์ ‘์† โ†’ ์ˆ˜๋™ ์žฌ์‹œ์ž‘ ๋“ฑ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋ฅผ ์‚ฌ๋žŒ์ด ์ง์ ‘ ์ˆ˜ํ–‰
  • ์ด ๊ณผ์ •์—์„œ ์‹ค์ˆ˜ ๊ฐ€๋Šฅ์„ฑ์ด ์กด์žฌํ•˜๊ณ , ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆผ (์•ฝ 30๋ถ„ ์†Œ์š”)
  • CD ํŒŒ์ดํ”„๋ผ์ธ์„ ํ†ตํ•ด ๋ฐฐํฌ ๊ณผ์ •์„ ์ž๋™ํ™”ํ•˜๋ฉด, ํด๋ฆญ ํ•œ ๋ฒˆ ๋˜๋Š” Git ํƒœ๊ทธ ํ‘ธ์‹œ๋งŒ์œผ๋กœ 3~5๋ถ„ ๋‚ด ์•ˆ์ •์ ์œผ๋กœ ๋ฐฐํฌ ๊ฐ€๋Šฅ
  • ๋˜ํ•œ, ๋งค์ผ ์ƒˆ๋กœ์šด ์ฝ”ํ…Œ ์ •๋‹ต ์—…๋ฐ์ดํŠธ, ์ฑ—๋ด‡, ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ๋ณธ ์„œ๋น„์Šค๋Š” ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ์„ ์ž์ฃผ ์—…๋ฐ์ดํŠธํ•  ํ•„์š”๊ฐ€ ์žˆ์–ด, ๋น ๋ฅด๊ณ  ์‹ ๋ขฐ์„ฑ ์žˆ๋Š” ์ž๋™ ๋ฐฐํฌ ์ฒด๊ณ„๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

2. ๋ฌด์ค‘๋‹จ ์„œ๋น„์Šค ์šด์˜

  • ์„œ๋น„์Šค๋Š” ๋งค์ผ ์˜ค์ „ 9์‹œ 30๋ถ„~10์‹œ ์‚ฌ์ด๊ฐ€ ์ตœ๋Œ€ ํŠธ๋ž˜ํ”ฝ ์‹œ๊ฐ„๋Œ€(๋™์‹œ ์ ‘์†์ž ์•ฝ 150๋ช… ์˜ˆ์ƒ)
  • ์ •๊ธฐ ๋ฐฐํฌ๋Š” ๊ธˆ์š”์ผ 18์‹œ๋กœ ์„ค์ •๋˜์–ด ์žˆ์ง€๋งŒ, ๋ฐฐํฌ ์‹คํŒจ ์‹œ ๋ณต๊ตฌ๊ฐ€ ๋А๋ฆฌ๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ํ–ฅ์ด ๊ฐˆ ์ˆ˜ ์žˆ์Œ
  • CD๋ฅผ ํ†ตํ•ด ํ—ฌ์Šค ์ฒดํฌ + ๋กค๋ฐฑ ์ „๋žต ํฌํ•จ๋œ Blue-Green ๋ฐฐํฌ๋ฅผ ๊ตฌ์„ฑํ•จ์œผ๋กœ์จ(์ถ”ํ›„ ์นด๋‚˜๋ฆฌ ๋ฐฐํฌ ์ ์šฉ), ๋ฐฐํฌ ์ค‘์—๋„ ์„œ๋น„์Šค ์ค‘๋‹จ ์—†์ด ์•ˆ์ •์ ์ธ ์ „ํ™˜ ๊ฐ€๋Šฅ

3. ์„œ๋น„์Šค ์‹ ๋ขฐ๋„ ํ™•๋ณด

  • ํ•ด์„ค ์ œ๊ณต ์„œ๋น„์Šค๋Š” ์ •ํ™•์„ฑ๊ณผ ์‹ ๋ขฐ๊ฐ€ ํ•ต์‹ฌ์ธ๋ฐ, ๋ฐฐํฌ ์˜ค๋ฅ˜๋‚˜ ์žฅ์• ๊ฐ€ ๋นˆ๋ฒˆํ•˜๋ฉด ์‚ฌ์šฉ์ž ์‹ ๋ขฐ๊ฐ€ ๊ธ‰๊ฒฉํžˆ ์ €ํ•˜๋จ
  • ์ž๋™ํ™”๋œ CD ํŒŒ์ดํ”„๋ผ์ธ์€ ํ…Œ์ŠคํŠธ, ํ—ฌ์Šค ์ฒดํฌ, ๋ชจ๋‹ˆํ„ฐ๋ง๊นŒ์ง€ ํฌํ•จํ•˜์—ฌ ๋ฐฐํฌ ์ดํ›„ ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•˜๊ณ , ์ด์ƒ ์ง•ํ›„ ๋ฐœ์ƒ ์‹œ ๋น ๋ฅด๊ฒŒ ๋Œ€์‘ ๊ฐ€๋Šฅํ•จ

4. ๊ฐœ๋ฐœ ํšจ์œจ์„ฑ ํ–ฅ์ƒ ๋ฐ ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ๋ฐฐํฌ

  • ์ˆ˜๋™ ๋ฐฐํฌ๋Š” ๋‹ด๋‹น์ž๊ฐ€ ์—†์œผ๋ฉด ์‹คํ–‰์ด ์–ด๋ ต๊ณ , ์ฃผ์„/๋ช…๋ น ์‹ค์ˆ˜๋กœ ๋ฐฐํฌ ์ƒํƒœ๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ
  • CD๋Š” ๋ˆ„๊ฐ€ ํ•ด๋„ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š” ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ๋ฐฐํฌ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜์—ฌ, ํŒ€์›Œํฌ์™€ ์ƒ์‚ฐ์„ฑ ํ–ฅ์ƒ์— ๊ธฐ์—ฌํ•จ

5. MVP ๋‹จ๊ณ„์—์„œ์˜ ๋ฏผ์ฒฉํ•œ ๋ฐ˜๋ณต ๊ฐœ์„ ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•จ

  • ํ˜„์žฌ๋Š” MVP ๋‹จ๊ณ„๋กœ, ๊ธฐ๋Šฅ ๊ฐœ์„ ๊ณผ ์ˆ˜์ •์ด ๋นˆ๋ฒˆํ•˜๊ฒŒ ์ด๋ค„์ง
  • CD ํŒŒ์ดํ”„๋ผ์ธ์„ ํ†ตํ•ด ์ž‘์€ ๋ณ€๊ฒฝ๋„ ๋น ๋ฅด๊ฒŒ ๋ฐ˜์˜ํ•˜๊ณ  ์ฆ‰์‹œ ๋ฐฐํฌ ๊ฐ€๋Šฅ, ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ์„ ๋น ๋ฅด๊ฒŒ ๋ฐ˜์˜ํ•˜๋Š” ์• ์ž์ผํ•œ ๊ฐœ๋ฐœ/๋ฐฐํฌ ์‚ฌ์ดํด์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Œ

2. CD ์ ์šฉ ๋ฒ”์œ„ ๋ฐ ๋ฐฉ์‹ ๊ฒฐ์ •

์ ์šฉ ๋ฒ”์œ„

  • ์Šคํ…Œ์ด์ง• ํ™˜๊ฒฝ: ์ž๋™ ๋ฐฐํฌ(Continuous Deployment) ์ ์šฉ
  • ์šด์˜(ํ”„๋กœ๋•์…˜) ํ™˜๊ฒฝ: ์Šน์ธ ํ›„ ๋ฐฐํฌ(Continuous Delivery) ๋ฐฉ์‹ ์ฑ„ํƒ

์„ ํƒํ•œ ๋ฐฐํฌ ์ „๋žต

  • ์ดˆ๊ธฐ: Blue-Green ๋ฐฐํฌ ์ „๋žต ์ ์šฉ
    • ๊ธฐ์กด ์„œ๋น„์Šค ๋ฒ„์ „(Green)์„ ์œ ์ง€ํ•œ ์ƒํƒœ์—์„œ ์ƒˆ๋กœ์šด ๋ฒ„์ „(Blue)์„ ๋ณ„๋„๋กœ ๋ฐฐํฌ
    • ๋ฐฐํฌ ์™„๋ฃŒ ํ›„ ๊ฒ€์ฆ์„ ๊ฑฐ์ณ ํŠธ๋ž˜ํ”ฝ์„ ์ƒˆ๋กœ์šด ๋ฒ„์ „์œผ๋กœ ์ „ํ™˜
    • ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ์ฆ‰์‹œ ๊ธฐ์กด ๋ฒ„์ „์œผ๋กœ ๋ณต๊ท€ ๊ฐ€๋Šฅ

  • ์ถ”ํ›„: ์นด๋‚˜๋ฆฌ ๋ฐฐํฌ ์ „๋žต ๋„์ž… ์˜ˆ์ •
    • ์ดˆ๊ธฐ์—๋Š” ์ผ๋ถ€ ์‚ฌ์šฉ์ž์—๊ฒŒ๋งŒ ์ƒˆ๋กœ์šด ๋ฒ„์ „์„ ๋…ธ์ถœํ•˜์—ฌ ์•ˆ์ •์„ฑ์„ ๊ฒ€์ฆ
    • ์ ์ง„์ ์œผ๋กœ ์ „์ฒด ์‚ฌ์šฉ์ž๋กœ ํŠธ๋ž˜ํ”ฝ์„ ํ™•์žฅ
    • ์žฅ์•  ๋ฐœ์ƒ ์‹œ ์˜ํ–ฅ์„ ์ตœ์†Œํ™”ํ•˜๊ณ  ๋น ๋ฅด๊ฒŒ ๋ณต๊ตฌ ๊ฐ€๋Šฅ

์„ ํƒ ์ด์œ 

์šฐ๋ฆฌ ์„œ๋น„์Šค๋Š” ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ํ•ด์„ค์ง‘์„ ์ œ๊ณตํ•˜๋Š” ํ”Œ๋žซํผ์œผ๋กœ, ๋งค์ผ ์˜ค์ „ 9์‹œ 30๋ถ„๋ถ€ํ„ฐ 10์‹œ๊นŒ์ง€๊ฐ€ ์ตœ๋Œ€ ํŠธ๋ž˜ํ”ฝ ์‹œ๊ฐ„๋Œ€์ด๋ฉฐ, ์ด๋•Œ ์ตœ๋Œ€ ๋™์‹œ ์ ‘์†์ž ์ˆ˜๋Š” ์•ฝ 150๋ช…์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค.

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

MVP ์ดˆ๊ธฐ์—๋Š” ์„œ๋น„์Šค ์‹ ๋ขฐ์„ฑ๊ณผ ๋ฌด์ค‘๋‹จ์„ ์ตœ์šฐ์„ ์œผ๋กœ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ๊ฒ€์ฆ ํ›„ ํ•œ ๋ฒˆ์— ์ „์ฒด ํŠธ๋ž˜ํ”ฝ์„ ์ „ํ™˜ํ•˜๋Š” Blue-Green ๋ฐฐํฌ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋น ๋ฅธ ๋กค๋ฐฑ์ด ๊ฐ€๋Šฅํ•˜๊ณ , ์„œ๋น„์Šค ์ดˆ๊ธฐ ํ’ˆ์งˆ์„ ์•ˆ์ •์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„œ๋น„์Šค๊ฐ€ ์ ์ฐจ ์•ˆ์ •๋˜๊ณ  ๊ธฐ๋Šฅ ๊ฐœ์„  ๋ฐ ๋ฒ„๊ทธ ์ˆ˜์ •์ด ์žฆ์•„์งˆ ๊ฒฝ์šฐ,

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

๋”ฐ๋ผ์„œ ์ผ๋ถ€ ์‚ฌ์šฉ์ž ๊ทธ๋ฃน์—๋งŒ ์ƒˆ ๋ฒ„์ „์„ ๋…ธ์ถœํ•˜์—ฌ ์•ˆ์ •์„ฑ์„ ๊ฒ€์ฆํ•˜๊ณ , ๋ฌธ์ œ๊ฐ€ ์—†์„ ๋•Œ ์ ์ง„์ ์œผ๋กœ ๋ฐฐํฌ๋ฅผ ํ™•์žฅํ•˜๋Š” ์นด๋‚˜๋ฆฌ ๋ฐฐํฌ ์ „๋žต์„ ํ†ตํ•ด ์šด์˜ ๋ฆฌ์Šคํฌ๋ฅผ ์ตœ์†Œํ™”ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ์šฐ๋ฆฌ ์„œ๋น„์Šค๋Š” ๋งค์ผ ์ƒˆ๋กœ์šด ๋ฌธ์ œ์™€ ํ•ด์„ค ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•œ ๊ตฌ์กฐ์ด๊ธฐ ๋•Œ๋ฌธ์—,

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

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

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


3. CD ํŒŒ์ดํ”„๋ผ์ธ ์„ค๊ณ„

CD ํŒŒ์ดํ”„๋ผ์ธ ํ๋ฆ„๋„

๋Œ€์ฒดํ…์ŠคํŠธ

CD ์ „์ฒด ํ๋ฆ„ ์„ค๋ช…

์ด๋ฒˆ CD(Continuous Delivery/Deployment) ํŒŒ์ดํ”„๋ผ์ธ์€ ์Šคํ…Œ์ด์ง• ์ž๋™ํ™” ๋ฐฐํฌ โ†’ ์šด์˜ ๋ฐฐํฌ ์Šน์ธ โ†’ Blue-Green ๋˜๋Š” ์นด๋‚˜๋ฆฌ ๋ฐฐํฌ โ†’ QA ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง โ†’ ์ตœ์ข… ํ™•์ •๊นŒ์ง€ ์ฒด๊ณ„์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ๋กœ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ, Blue-Green ๋ฐฐํฌ์™€ ์นด๋‚˜๋ฆฌ ๋ฐฐํฌ๋ฅผ ์ ์šฉํ•˜๋“ , ์ˆ˜๋™ ๋ฐฐํฌ๋ฅผ ์ง„ํ–‰ํ•˜๋“  ๊ด€๊ณ„์—†์ด, Slack ์•Œ๋ฆผ ๋ฐœ์†ก, ์šด์˜ QA ์ ๊ฒ€, ์ดˆ๊ธฐ ์ง‘์ค‘ ๋ชจ๋‹ˆํ„ฐ๋ง ๋“ฑ์˜ ์šด์˜ ํ๋ฆ„์€ ๋™์ผํ•˜๊ฒŒ ํ•„์ˆ˜ ์ ˆ์ฐจ๋กœ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜๋™ ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ๋„ ์ด๋Ÿฌํ•œ ์šด์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ์—„๊ฒฉํžˆ ์ค€์ˆ˜ํ•˜์—ฌ ์„œ๋น„์Šค ์•ˆ์ •์„ฑ๊ณผ ๋ฐฐํฌ ์‹ ๋ขฐ์„ฑ์„ ํ™•๋ณดํ•ฉ๋‹ˆ๋‹ค.

1. ๊ธฐ๋ณธ CI/CD ์ดˆ๊ธฐ ๋‹จ๊ณ„

  • Push release tag
  • Build artifact
  • ์Šคํ…Œ์ด์ง• ์ž๋™ ๋ฐฐํฌ
  • ์Šคํ…Œ์ด์ง• ์ž๋™ํ™” ํ…Œ์ŠคํŠธ

2. ์Šคํ…Œ์ด์ง• ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅธ ๋ถ„๊ธฐ

  • ์„ฑ๊ณต ์‹œ: ์šด์˜ ๋ฐฐํฌ ์Šน์ธ ์š”์ฒญ, ์šด์˜ ๋ฐฐํฌ ์Šน์ธ
  • ์‹คํŒจ ์‹œ: ๋ฐฐํฌ ์ฐจ๋‹จ ๋ฐ Slack ์•Œ๋ฆผ

3. ์šด์˜ ๋ฐฐํฌ ์ง„ํ–‰

Blue-Green ๋ฐฐํฌ ํ๋ฆ„

  • Blue ๋ฒ„์ „ ๋ฐฐํฌ
  • Health Check ์„ฑ๊ณต ์‹œ ํŠธ๋ž˜ํ”ฝ ์ „ํ™˜ (Green โ†’ Blue)
  • ๋ฐฐํฌ ์™„๋ฃŒ ํ›„ QA ๊ฒ€์ฆ ๋ฐ ์ดˆ๊ธฐ ์ง‘์ค‘ ๋ชจ๋‹ˆํ„ฐ๋ง
  • ์ด์ƒ ๋ฐœ์ƒ ์‹œ Green์œผ๋กœ ๋กค๋ฐฑ

์นด๋‚˜๋ฆฌ ๋ฐฐํฌ ํ๋ฆ„ (์ถ”ํ›„ ์ ์šฉ)

  • 5~10% ์นด๋‚˜๋ฆฌ ๋ฐฐํฌ
  • ๋ชจ๋‹ˆํ„ฐ๋ง ํ›„ ์ ์ง„์  ํŠธ๋ž˜ํ”ฝ ํ™•์žฅ (10%โ†’30%โ†’70%โ†’100%)
  • ์ด์ƒ ๋ฐœ์ƒ ์‹œ ์นด๋‚˜๋ฆฌ ๋กค๋ฐฑ

4. ๊ธด๊ธ‰ ์ƒํ™ฉ ๋Œ€์‘

  • Health Check ์‹คํŒจ ์‹œ ๋ฐฐํฌ ์ค‘๋‹จ ๋ฐ ๋กค๋ฐฑ
  • ์ดˆ๊ธฐ ๋ชจ๋‹ˆํ„ฐ๋ง ์ค‘ ์ด์ƒ ๋ฐœ์ƒ ์‹œ ๊ธด๊ธ‰ ๋กค๋ฐฑ ๋˜๋Š” ํ•ซํ”ฝ์Šค

์ฃผ์š” ์•Œ๋ฆผ ํฌ์ธํŠธ (Slack)

  • ์Šคํ…Œ์ด์ง• ํ…Œ์ŠคํŠธ ์‹คํŒจ ์‹œ ์•Œ๋ฆผ
  • ์šด์˜ ๋ฐฐํฌ ์Šน์ธ ์š”์ฒญ ์•Œ๋ฆผ
  • ๋ฐฐํฌ ์‹œ์ž‘, ์™„๋ฃŒ, ์ด์ƒ ๋ฐœ์ƒ, ๋กค๋ฐฑ ๋“ฑ ์ƒํƒœ๋ณ„ ์•Œ๋ฆผ

์š”์•ฝ

๋‹จ๊ณ„ Blue-Green ์นด๋‚˜๋ฆฌ ๋ฐฐํฌ
์ดˆ๊ธฐ ๋ฐฐํฌ ๋ฐฉ์‹ ์ „์ฒด ํŠธ๋ž˜ํ”ฝ ํ•œ ๋ฒˆ์— ์ „ํ™˜ ์†Œ์ˆ˜ ํŠธ๋ž˜ํ”ฝ๋ถ€ํ„ฐ ์ ์ง„์  ์ „ํ™˜
์žฅ์•  ๋Œ€์‘ Green์œผ๋กœ ์ „์ฒด ๋ณต๊ท€ ์นด๋‚˜๋ฆฌ ํŠธ๋ž˜ํ”ฝ๋งŒ ๋กค๋ฐฑ
๋ฆฌ์Šคํฌ ๊ด€๋ฆฌ ๋น ๋ฅธ ๋กค๋ฐฑ ๊ฐ€๋Šฅ ์ ์ง„์  ํ™•์žฅ์œผ๋กœ ๋ฆฌ์Šคํฌ ์ตœ์†Œํ™”
์ ์šฉ ์‹œ์  MVP ๋ฐฐํฌ ์ดํ›„ ์ ์šฉ ์„œ๋น„์Šค ๊ณ ๋„ํ™” ์ดํ›„ ์ ์šฉ

ํ‚ค์›Œ๋“œ: ์Šคํ…Œ์ด์ง• ์ž๋™ํ™” โ†’ ์šด์˜ ์Šน์ธ โ†’ Blue-Green/์นด๋‚˜๋ฆฌ ๋ฐฐํฌ โ†’ QA โ†’ ๋ชจ๋‹ˆํ„ฐ๋ง โ†’ ํ™•์ • or ๋กค๋ฐฑ ๋Œ€์‘



Slack ์•Œ๋ฆผ ํ๋ฆ„

  • ์Šคํ…Œ์ด์ง• ์ž๋™ํ™” ํ…Œ์ŠคํŠธ ์‹คํŒจ ์‹œ: Slack ์•Œ๋ฆผ ๋ฐœ์†ก
  • ์Šคํ…Œ์ด์ง• ํ…Œ์ŠคํŠธ ์„ฑ๊ณต ์‹œ: ์šด์˜ ๋ฐฐํฌ ์Šน์ธ ์š”์ฒญ Slack ์•Œ๋ฆผ
  • ์šด์˜ ๋ฐฐํฌ ์‹œ์ž‘ ์‹œ: Slack ์•Œ๋ฆผ ๋ฐœ์†ก
  • ์šด์˜ ๋ฐฐํฌ ์„ฑ๊ณต ์‹œ: Slack ์•Œ๋ฆผ ๋ฐœ์†ก
  • ํ—ฌ์Šค์ฒดํฌ ์‹คํŒจ/๊ธด๊ธ‰ ๋กค๋ฐฑ ๋ฐœ์ƒ ์‹œ: ๊ธด๊ธ‰ ๋กค๋ฐฑ Slack ์•Œ๋ฆผ
  • ์ตœ์ข… QA ์™„๋ฃŒ ํ›„ ๋ฐฐํฌ ํ™•์ •: Slack ์•Œ๋ฆผ ๋ฐœ์†ก

GitHub Actions - Slack ๋ฐœ์†ก ์Šคํฌ๋ฆฝํŠธ

Slack Webhook ์„ค์ •

  • Slack Incoming Webhook์„ ์ƒ์„ฑํ•˜์—ฌ GitHub Secrets์— SLACK_WEBHOOK_URL๋กœ ์ €์žฅ

Slack ๋ฐœ์†ก ์Šคํฌ๋ฆฝํŠธ (curl ์ด์šฉ)

์Šคํ…Œ์ด์ง• ์ž๋™ํ™” ํ…Œ์ŠคํŠธ ์‹คํŒจ ์‹œ ์•Œ๋ฆผ
- name: Slack ์•Œ๋ฆผ - ์Šคํ…Œ์ด์ง• ํ…Œ์ŠคํŠธ ์‹คํŒจ
  if: failure()
  run: |
    curl -X POST -H 'Content-type: application/json' \
    --data '{"text":"โš ๏ธ [์Šคํ…Œ์ด์ง• ํ…Œ์ŠคํŠธ ์‹คํŒจ] - ๋ฐฐํฌ๊ฐ€ ์ฐจ๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."}' \
    ${{ secrets.SLACK_WEBHOOK_URL }}
์Šคํ…Œ์ด์ง• ์ž๋™ํ™” ํ…Œ์ŠคํŠธ ์„ฑ๊ณต ์‹œ ์šด์˜ ๋ฐฐํฌ ์Šน์ธ ์š”์ฒญ ์•Œ๋ฆผ
- name: Slack ์•Œ๋ฆผ - ์šด์˜ ๋ฐฐํฌ ์Šน์ธ ์š”์ฒญ
  if: success()
  run: |
    curl -X POST -H 'Content-type: application/json' \
    --data '{"text":"๐Ÿš€ [์Šคํ…Œ์ด์ง• ํ…Œ์ŠคํŠธ ์„ฑ๊ณต] ์šด์˜ ๋ฐฐํฌ ์Šน์ธ ์š”์ฒญ์„ ํ•ด์ฃผ์„ธ์š”."}' \
    ${{ secrets.SLACK_WEBHOOK_URL }}
์šด์˜ ๋ฐฐํฌ ์‹œ์ž‘ ์•Œ๋ฆผ
- name: Slack ์•Œ๋ฆผ - ์šด์˜ ๋ฐฐํฌ ์‹œ์ž‘
  run: |
    curl -X POST -H 'Content-type: application/json' \
    --data '{"text":"๐Ÿš€ [์šด์˜ ๋ฐฐํฌ ์‹œ์ž‘] ๋ฐฐํฌ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค."}' \
    ${{ secrets.SLACK_WEBHOOK_URL }}
์šด์˜ ๋ฐฐํฌ ์„ฑ๊ณต ์•Œ๋ฆผ
- name: Slack ์•Œ๋ฆผ - ์šด์˜ ๋ฐฐํฌ ์™„๋ฃŒ
  run: |
    curl -X POST -H 'Content-type: application/json' \
    --data '{"text":"๐ŸŽ‰ [์šด์˜ ๋ฐฐํฌ ์™„๋ฃŒ] QA๋ฅผ ์‹œ์ž‘ํ•ด์ฃผ์„ธ์š”."}' \
    ${{ secrets.SLACK_WEBHOOK_URL }}
ํ—ฌ์Šค์ฒดํฌ ์‹คํŒจ ๋ฐ ๊ธด๊ธ‰ ๋กค๋ฐฑ ์•Œ๋ฆผ
- name: Slack ์•Œ๋ฆผ - ํ—ฌ์Šค์ฒดํฌ ์‹คํŒจ ๋ฐ ๋กค๋ฐฑ
  if: failure()
  run: |
    curl -X POST -H 'Content-type: application/json' \
    --data '{"text":"๐Ÿ”ฅ [์šด์˜ ํ—ฌ์Šค์ฒดํฌ ์‹คํŒจ] ๊ธด๊ธ‰ ๋กค๋ฐฑ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค!"}' \
    ${{ secrets.SLACK_WEBHOOK_URL }}
์ตœ์ข… QA ์™„๋ฃŒ ํ›„ ๋ฐฐํฌ ํ™•์ • ์•Œ๋ฆผ
- name: Slack ์•Œ๋ฆผ - ์ตœ์ข… ๋ฐฐํฌ ํ™•์ •
  run: |
    curl -X POST -H 'Content-type: application/json' \
    --data '{"text":"โœ… [์šด์˜ ๋ฐฐํฌ ํ™•์ •] ์„œ๋น„์Šค๊ฐ€ ์ •์ƒ ์šด์˜ ์ค‘์ž…๋‹ˆ๋‹ค."}' \
    ${{ secrets.SLACK_WEBHOOK_URL }}

Slack ์•Œ๋ฆผ ํ‚ค์›Œ๋“œ ์ •๋ฆฌ

  • โš ๏ธ ๊ฒฝ๊ณ  (ํ…Œ์ŠคํŠธ ์‹คํŒจ)
  • ๐Ÿš€ ์‹œ์ž‘ (๋ฐฐํฌ ์‹œ์ž‘)
  • ๐ŸŽ‰ ์„ฑ๊ณต (๋ฐฐํฌ ์™„๋ฃŒ)
  • ๐Ÿ”ฅ ๊ธด๊ธ‰ (๋กค๋ฐฑ)
  • โœ… ์ตœ์ข… ์™„๋ฃŒ (QA ํ™•์ •)

QA ์ฒดํฌ๋ฆฌ์ŠคํŠธ ํ…œํ”Œ๋ฆฟ

ํ•ญ๋ชฉ ๋ฒˆํ˜ธ ์ฒดํฌ ํ•ญ๋ชฉ ํ™•์ธ ์—ฌ๋ถ€
1 ๋ฉ”์ธ ํŽ˜์ด์ง€ ์ •์ƒ ์ ‘์† ์—ฌ๋ถ€ โœ… / โŒ
2 ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ์ •์ƒ ์ž‘๋™ ์—ฌ๋ถ€ โœ… / โŒ
3 ์˜ค๋Š˜์˜ ๋ฌธ์ œ ๋ฆฌ์ŠคํŠธ ์ •์ƒ ํ‘œ์‹œ ์—ฌ๋ถ€ โœ… / โŒ
4 ๋ฌธ์ œ ์ƒ์„ธ ํŽ˜์ด์ง€ ์ •์ƒ ์กฐํšŒ ์—ฌ๋ถ€ โœ… / โŒ
5 ํ•ด์„ค ํŽ˜์ด์ง€ ์ •์ƒ ์กฐํšŒ ์—ฌ๋ถ€ โœ… / โŒ
6 ์ฃผ์š” ๋ฒ„ํŠผ(์ œ์ถœ, ํ•ด์„ค ํ™•์ธ ๋“ฑ) ์ •์ƒ ๋™์ž‘ ์—ฌ๋ถ€ โœ… / โŒ
7 ์—๋Ÿฌ ํŽ˜์ด์ง€(404, 500) ๋ฐœ์ƒ ์—ฌ๋ถ€ โœ… / โŒ
8 ์‘๋‹ต ์†๋„ ์ง€์—ฐ ์—ฌ๋ถ€ ํ™•์ธ (API ํ˜ธ์ถœ) โœ… / โŒ
9 ๋ฐฐํฌ ํ›„ ์‹ ๊ทœ ์—๋Ÿฌ ๋กœ๊ทธ ์œ ์ž… ์—ฌ๋ถ€ โœ… / โŒ
10 ๊ธฐํƒ€ ์ด์ƒ ํ˜„์ƒ ๋ฐœ์ƒ ์—ฌ๋ถ€ โœ… / โŒ

๋‹ด๋‹น์ž ์ง€์ •

ํ•ญ๋ชฉ ์—ญํ•  ์„ค๋ช… ๋‹ด๋‹น์ž
๋ฐฐํฌ ์Šน์ธ์ž ์ตœ์ข… ๋ฐฐํฌ ์Šน์ธ evan.kim
๋ชจ๋‹ˆํ„ฐ๋ง ๋‹ด๋‹น์ž ๋ฐฐํฌ ์งํ›„ ์‹œ์Šคํ…œ ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง noah.hwang, sophie.kim
๋กค๋ฐฑ ๋‹ด๋‹น์ž ์žฅ์•  ๋ฐœ์ƒ ์‹œ ์ฆ‰์‹œ ๋กค๋ฐฑ evan.kim, noah.hwang
๊ธด๊ธ‰ ํ•ซํ”ฝ์Šค ๋‹ด๋‹น์ž ๋น ๋ฅธ ์ˆ˜์ • ๋ฐ ์žฌ๋ฐฐํฌ ๋‹ด๋‹น noah.hwang
์‚ฌ์šฉ์ž ๋ฌธ์˜ ๋Œ€์‘ ๋‹ด๋‹น์ž (CS) ์‚ฌ์šฉ์ž ๋ฌธ์ œ ๋Œ€์‘ sophie.kim
๋ฆฌํฌํŠธ ์ •๋ฆฌ ๋‹ด๋‹น์ž ๋ฐฐํฌ/QA ๊ฒฐ๊ณผ ๊ธฐ๋ก ๋ฐ ๊ณต์œ  sophie.kim
Slack ์•Œ๋ฆผ ๋‹ด๋‹น์ž ๋ฐฐํฌ ์™„๋ฃŒ ๋“ฑ ์•Œ๋ฆผ ๋ฐœ์†ก evan.kim
QA ์ฒดํฌ๋ฆฌ์ŠคํŠธ ์ž‘์„ฑ์ž ์šด์˜ QA ์ฒดํฌ๋ฆฌ์ŠคํŠธ ์ž‘์„ฑ ๋ฐ ์ ๊ฒ€ noah.hwang

๋„๊ตฌ/๋ฐฉ์‹ ์„ ํƒ

  • ๋ฐฐํฌ ๋Œ€์ƒ: AWS EC2 ์ธ์Šคํ„ด์Šค (Ubuntu, Amazon Linux2 ๋“ฑ ์˜ˆ์ƒ)
  • ๋ฐฉ์‹: GitHub Actions + SSH ๋ฐฐํฌ + systemd ์„œ๋น„์Šค ์žฌ์‹œ์ž‘
  • ํ…Œ์ŠคํŠธ ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง: Health Check ์Šคํฌ๋ฆฝํŠธ + Slack ์•Œ๋ฆผ

GitHub Actions๋ฅผ CD ๋„๊ตฌ๋กœ ์„ ํƒํ•œ ์ด์œ 

1. CI์™€ CD๋ฅผ ํ•˜๋‚˜์˜ ํ”Œ๋žซํผ์—์„œ ํ†ตํ•ฉ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ

  • ์ด๋ฏธ CI ํŒŒ์ดํ”„๋ผ์ธ์„ GitHub Actions๋กœ ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ณ„๋„์˜ ๋„๊ตฌ ์—†์ด CD๊นŒ์ง€ GitHub Actions ๋‚ด์—์„œ ์ด์–ด์„œ ๊ตฌ์„ฑ ๊ฐ€๋Šฅ
  • ๋นŒ๋“œ, ํ…Œ์ŠคํŠธ, ๋ฐฐํฌ๊นŒ์ง€ ์ „์ฒด DevOps ํ๋ฆ„์„ ํ•˜๋‚˜์˜ ์›Œํฌํ”Œ๋กœ์šฐ ํŒŒ์ผ๋กœ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ

2. GitHub ์ €์žฅ์†Œ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์ž๋™ํ™”์— ์ตœ์ ํ™”

  • release-* ํƒœ๊ทธ ํ‘ธ์‹œ ๋“ฑ GitHub ๋‚ด ์ด๋ฒคํŠธ(trigger)์— ๋งค์šฐ ์‰ฝ๊ฒŒ ์—ฐ๋™ ๊ฐ€๋Šฅ
  • push, pull_request, tag, schedule ๋“ฑ ๋‹ค์–‘ํ•œ ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ๋ฐฐํฌ ์ž๋™ํ™” ๊ตฌ์„ฑ์ด ๊ฐ„๋‹จ

3. ํ•™์Šต ๋ฐ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๊ฐ„๋‹จํ•จ

  • ๋‹ค๋ฅธ CD ๋„๊ตฌ(Jenkins, ArgoCD ๋“ฑ)์— ๋น„ํ•ด ์„ค์ •์ด ์ง๊ด€์ ์ด๊ณ , YAML ๊ธฐ๋ฐ˜์œผ๋กœ ์‰ฝ๊ฒŒ ์ดํ•ด ๊ฐ€๋Šฅ
  • ์ž‘์€ ํŒ€์ด๋‚˜ MVP ๋‹จ๊ณ„์—์„œ ๋„์ž… ์žฅ๋ฒฝ์ด ๋‚ฎ๊ณ , ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์›€

4. ์™ธ๋ถ€ ๋„๊ตฌ ์„ค์น˜ ์—†์ด ๋ฐ”๋กœ ์‹คํ–‰ ๊ฐ€๋Šฅ

  • GitHub Actions๋Š” GitHub ํ™˜๊ฒฝ ๋‚ด์—์„œ ๋ฐ”๋กœ ์‹คํ–‰๋˜๋ฏ€๋กœ, Jenkins์ฒ˜๋Ÿผ ๋ณ„๋„ ์„œ๋ฒ„ ๊ตฌ์„ฑ ์—†์ด๋„ ์šด์˜ ๊ฐ€๋Šฅ
  • AWS EC2๋ฐฐํฌ ์‹œ์—๋„ scp, ssh ์•ก์…˜์„ ํ†ตํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฐฐํฌ ์ž๋™ํ™” ๊ตฌํ˜„ ๊ฐ€๋Šฅ

5. ๋น„์šฉ ํšจ์œจ์„ฑ๊ณผ GitHub ์—ฐ๋™์„ฑ

  • GitHub Actions๋Š” ๊ฐœ์ธ ๋˜๋Š” ์†Œ๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ๋ฌด๋ฃŒ ์š”๊ธˆ์ œ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • GitHub์™€์˜ ์‹œํฌ๋ฆฟ ๊ด€๋ฆฌ, ๋ฒ„์ „ ์ปจํŠธ๋กค, PR ์—ฐ๋™ ๋“ฑ ํ†ตํ•ฉ์„ฑ์ด ๋›ฐ์–ด๋‚จ

CD ํ๋ฆ„ ๋‹จ๊ณ„

๋‹จ๊ณ„ ์„ค๋ช…
ํŠธ๋ฆฌ๊ฑฐ main ๋ธŒ๋žœ์น˜์— ํƒœ๊ทธ(release-*)๊ฐ€ push๋˜๋ฉด CD ์‹œ์ž‘
์•„ํ‹ฐํŒฉํŠธ ๋‹ค์šด๋กœ๋“œ CI์—์„œ ์ƒ์„ฑ๋œ ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ(.jar, React build/, FastAPI/) ๋‹ค์šด๋กœ๋“œ
์ „์†ก AWS EC2์— ftp๋กœ ์—…๋กœ๋“œ
์‹ ๊ทœ ๋ฒ„์ „ ๋ฐฐํฌ ์ค€๋น„ ์ƒˆ ๋ฒ„์ „ ๋””๋ ‰ํ† ๋ฆฌ์— ๋ฐฐ์น˜, systemd ์„œ๋น„์Šค ์ค€๋น„
ํ—ฌ์Šค ์ฒดํฌ FastAPI์™€ SpringBoot API /health ํ˜ธ์ถœ ๊ฒฐ๊ณผ ํ™•์ธ
ํŠธ๋ž˜ํ”ฝ ์ „ํ™˜ (Nginx switch) symlink ๋ณ€๊ฒฝ ๋˜๋Š” Nginx config ์Šค์™‘ ํ›„ reload
๋ชจ๋‹ˆํ„ฐ๋ง 10๋ถ„๊ฐ„ ์‘๋‹ต ๋ชจ๋‹ˆํ„ฐ๋ง ํ›„ ๋ฌธ์ œ ์—†์œผ๋ฉด green ๋ฒ„์ „ ์ œ๊ฑฐ
์‹คํŒจ ์‹œ ๋กค๋ฐฑ symlink ์ด์ „ ๋ฒ„์ „์œผ๋กœ ๋ณต์› + ์„œ๋น„์Šค ์žฌ์‹œ์ž‘

๋กค๋ฐฑ ์ „๋žต

  • systemd service์— ExecStartPre๋กœ ํ—ฌ์Šค ์ฒดํฌ ํ›„ ์‹คํ–‰
  • ์‹คํŒจ ์‹œ ๋””์Šค์ฝ”๋“œ ์•Œ๋ฆผ โ†’ ๊ธฐ์กด ๋””๋ ‰ํ† ๋ฆฌ๋กœ symlink ๋ณต๊ตฌ โ†’ ์žฌ์‹œ์ž‘

4. ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์„ฑ ๋ช…์„ธ

GitHub Actions CD Trigger ์กฐ๊ฑด

on:
  push:
    tags:
      - 'release-*'
  • release-๋กœ ์‹œ์ž‘ํ•˜๋Š” ํƒœ๊ทธ(ex. release-v1.0)๋ฅผ ํ‘ธ์‹œํ•˜๋ฉด ์ž๋™์œผ๋กœ CD ํŒŒ์ดํ”„๋ผ์ธ์ด ์‹คํ–‰๋ผ์„œ AWS ์„œ๋ฒ„์— ๋ฐฐํฌ๊ฐ€ ์ง„ํ–‰

CD ์Šคํฌ๋ฆฝํŠธ (React)


- name: Download React Build Artifact
  uses: actions/download-artifact@v3
  with:
    name: react-build
  • name: Deploy React via SSH uses: appleboy/[email protected] with: host: ${{ secrets.AWS_HOST }} username: ubuntu key: ${{ secrets.AWS_SSH_KEY }} source: "frontend/build/" target: "/home/ubuntu/deployments/react-build/"

  • name: Replace Nginx Static Files uses: appleboy/ssh-action@master with: host: ${{ secrets.AWS_HOST }} username: ubuntu key: ${{ secrets.AWS_SSH_KEY }} script: | sudo rm -rf /var/www/html/* sudo cp -r /home/ubuntu/deployments/react-build/* /var/www/html/ sudo systemctl reload nginx

CD ์Šคํฌ๋ฆฝํŠธ (SpringBoot)

- name: Download Build Artifact
  uses: actions/download-artifact@v3
  with:
    name: springboot-jar
  • name: Deploy via SSH uses: appleboy/[email protected] with: host: ${{ secrets.AWS_HOST }} username: ubuntu key: ${{ secrets.AWS_SSH_KEY }} source: "build/libs/myapp.jar" target: "/home/ubuntu/deployments/myapp-blue.jar"

  • name: Run Remote Deploy Script uses: appleboy/ssh-action@master with: host: ${{ secrets.AWS_HOST }} username: ubuntu key: ${{ secrets.AWS_SSH_KEY }} script: | sudo systemctl stop spring.service sudo cp /home/ubuntu/deployments/myapp-blue.jar /opt/myapp/app.jar sudo systemctl start spring.service

CD ์Šคํฌ๋ฆฝํŠธ (FastAPI)

- name: Download FastAPI Artifact
  uses: actions/download-artifact@v3
  with:
    name: fastapi-src
  • name: Deploy FastAPI via SSH uses: appleboy/[email protected] with: host: ${{ secrets.AWS_HOST }} username: ubuntu key: ${{ secrets.AWS_SSH_KEY }} source: "fastapi/" target: "/home/ubuntu/deployments/fastapi-blue/"

  • name: Run FastAPI Deploy Script uses: appleboy/ssh-action@master with: host: ${{ secrets.AWS_HOST }} username: ubuntu key: ${{ secrets.AWS_SSH_KEY }} script: | sudo systemctl stop fastapi.service sudo rm -rf /opt/fastapi/* sudo cp -r /home/ubuntu/deployments/fastapi-blue/* /opt/fastapi/ sudo systemctl start fastapi.service

Health Check ์Šคํฌ๋ฆฝํŠธ (SpringBoot)


// ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํฌํŠธ (๊ธฐ๋ณธ: 8080) PORT=8080

// ํ—ฌ์Šค์ฒดํฌ ์š”์ฒญ RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$URL")

if [ "$RESPONSE" -eq 200 ]; then echo "โœ… Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค." exit 0 else echo "โŒ ํ—ฌ์Šค์ฒดํฌ ์‹คํŒจ: ์ƒํƒœ ์ฝ”๋“œ $RESPONSE" exit 1 fi

Health Check ์Šคํฌ๋ฆฝํŠธ (FastAPI)


PORT=8000 ENDPOINT="/health" URL="<http://localhost&gt;:$PORT$ENDPOINT"

RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$URL")

if [ "$RESPONSE" -eq 200 ]; then echo "โœ… FastAPI ํ—ฌ์Šค์ฒดํฌ ์„ฑ๊ณต (HTTP 200)" exit 0 else echo "โŒ FastAPI ํ—ฌ์Šค์ฒดํฌ ์‹คํŒจ: ์ƒํƒœ ์ฝ”๋“œ $RESPONSE" exit 1 fi

Nginx ํŠธ๋ž˜ํ”ฝ ์ „ํ™˜ (Blue-Green)

# ์‹ฌ๋ณผ๋ฆญ ๋งํฌ ๊ต์ฒด ๋ฐฉ์‹
ln -sfn /var/www/app-blue /var/www/html
sudo systemctl reload nginx

๐Ÿ“Œ ๋ณด์•ˆ ๋ฐ ์‹œํฌ๋ฆฟ ๊ด€๋ฆฌ

  • GitHub Secrets ์‚ฌ์šฉ:
    • AWS_HOST
    • AWS_SSH_KEY
  • ์„œ๋น„์Šค ๋‚ด๋ถ€ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋Š” .env ํŒŒ์ผ์ด ์•„๋‹Œ systemd ํ™˜๊ฒฝ ์„ค์ • ํŒŒ์ผ๋กœ ๊ด€๋ฆฌ
โš ๏ธ **GitHub.com Fallback** โš ๏ธ