Back-End/Spring

ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ์‹ฌํ™”: ์ฑ•ํ„ฐ 2 (CI/CD)

Kr1 2026. 5. 14. 00:15

 

 

๐Ÿ—จ๏ธ CI/CD

๐Ÿ“Œ CI/CD์˜ ๊ฐœ๋…์„ ์ดํ•ดํ•˜๊ณ , ์ด๋ฅผ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜์—ฌ ์ž๋™ํ™”๋œ ๋นŒ๋“œ, ํ…Œ์ŠคํŠธ, ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
  • CI/CD์˜ ๊ธฐ๋ณธ ๊ฐœ๋…
    • CI์™€ CD์˜ ์ •์˜์™€ ๋ชฉ์ ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.
    • CI/CD๋ฅผ ๋„์ž…ํ•จ์œผ๋กœ์จ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.
  • CI/CD ๋„๊ตฌ ์†Œ๊ฐœ
    • ๋‹ค์–‘ํ•œ CI/CD ๋„๊ตฌ๋“ค(GitHub Actions, Jenkins, GitLab CI ๋“ฑ)์˜ ํŠน์ง•๊ณผ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.
    • GitLab๋ฅผ ์ด์šฉํ•œ CI/CD ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•
    • GitLab์˜ ์„ค์ • ํŒŒ์ผ ์ž‘์„ฑ ๋ฐฉ๋ฒ•์„ ์ตํžˆ๊ณ , ์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ž๋™ํ™”๋œ ๋นŒ๋“œ ๋ฐ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค. 
  • ๋ฐฐํฌ ์ž๋™ํ™”
    • AWS์™€ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ํ”Œ๋žซํผ์„ ์ด์šฉํ•˜์—ฌ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋ฐฐํฌ ๋‹จ๊ณ„๋ฅผ ์ž๋™ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

CI/CD ๊ฐœ์š”

CI/CD๋ž€?

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

 

CI/CD์˜ ์žฅ์ 

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

 

CI/CD ๋„๊ตฌ

GitHub Actions

  • GitHub Actions๋Š” GitHub ์ €์žฅ์†Œ์— ์ง์ ‘ ํ†ตํ•ฉ๋˜์–ด ์žˆ๋Š” CI/CD ๋„๊ตฌ๋กœ, YAML ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์—ฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํŠน์ง•
    • GitHub ์ €์žฅ์†Œ์™€์˜ ๊ฐ•๋ ฅํ•œ ํ†ตํ•ฉ
    • ๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ํŠธ๋ฆฌ๊ฑฐ
    • ํ’๋ถ€ํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ฐ Marketplace ์ง€์›
    • ๋ฌด๋ฃŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ (์ œํ•œ๋œ ๋Ÿฐํƒ€์ž„ ์ œ๊ณต)

Jenkins

  • Jenkins๋Š” ์˜คํ”ˆ ์†Œ์Šค CI/CD ๋„๊ตฌ๋กœ, ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํŠน์ง•
    • ๋†’์€ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๊ฐ€๋Šฅ
    • ๋‹ค์–‘ํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ง€์›
    • ๋ถ„์‚ฐ ๋นŒ๋“œ ๋ฐ ๋‹ค์ค‘ ํ”Œ๋žซํผ ์ง€์›
    • ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉ

GitLab CI

  • GitLab CI๋Š” GitLab๊ณผ ํ†ตํ•ฉ๋œ CI/CD ๋„๊ตฌ๋กœ, GitLab ์ €์žฅ์†Œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํŠน์ง•
    • GitLab๊ณผ์˜ ํ†ตํ•ฉ
    • ๊ฐ•๋ ฅํ•œ ํŒŒ์ดํ”„๋ผ์ธ ํŽธ์ง‘๊ธฐ ์ œ๊ณต
    • ์ž๋™ํ™”๋œ DevOps ์ˆ˜๋ช… ์ฃผ๊ธฐ ๊ด€๋ฆฌ
    • ํด๋ผ์šฐ๋“œ ๋ฐ ์˜จํ”„๋ ˆ๋ฏธ์Šค ๋ชจ๋‘ ์ง€์›

 

๐Ÿ—จ๏ธ Amazon ECS

Amazon ECS ๊ฐœ์š”

Amazon ECS๋ž€?

  • AWS Elastic Container Service๋Š” docker ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‰ฝ๊ฒŒ ๋ฐฐํฌํ•˜๊ณ  ์šด์˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•˜๋Š” ์™„์ „๊ด€๋ฆฌํ˜• Container Orchestration ์„œ๋น„์Šค
    • ์ปจํ…Œ์ด๋„ˆ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ (Container Orchestration): ์ˆ˜์‹ญ~์ˆ˜๋ฐฑ ๊ฐœ์˜ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ๋“ค์ด ๋ฌธ์ œ์—†์ด ๋Œ์•„๊ฐ€๋„๋ก, ์˜ค์ผ€์ŠคํŠธ๋ผ ์ง€ํœ˜์ž์ฒ˜๋Ÿผ ์ž๋™์œผ๋กœ ๋ฐฐํฌ, ๋ณต๊ตฌ, ํ™•์žฅ(Scaling)์„ ์ด๊ด„ ์ง€ํœ˜ํ•˜๋Š” ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค.
  • Kubernetes์™€ ๊ฐ™์€ container Orchestration ์„œ๋น„์Šค
  • Kubernetes ๋ณด๋‹ค ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ , ๋น„์šฉ์ ์œผ๋กœ๋„ ์ €๋ ดํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์†Œ/์ค‘ ๊ทœ๋ชจ์˜ ํ”„๋กœ์ ํŠธ์— ๋„๋ฆฌ ์‚ฌ์šฉ
  • serverless๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ธ์Šคํ„ด์Šค(๊ฐ€์„ฑ์„œ๋ฒ„)๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•  ํ•„์š”๋„ ์—†์Œ
    • ์„œ๋ฒ„๋ฆฌ์Šค (Serverless): ์„œ๋ฒ„๊ฐ€ ์•„์˜ˆ ์—†๋‹ค๋Š” ๋œป์ด ์•„๋‹ˆ๋ผ, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ฐ€์ƒ ์„œ๋ฒ„(EC2 ๋“ฑ)๋ฅผ ์„ธํŒ…ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ท€์ฐฎ์€ ์ž‘์—… ์—†์ด ํด๋ผ์šฐ๋“œ(AWS)๊ฐ€ ์•Œ์•„์„œ ์„œ๋ฒ„ ์ธํ”„๋ผ๋ฅผ ๋„์›Œ์ฃผ๋Š” ๊ธฐ์ˆ 

 

๊ตฌ์กฐ

  • ECS๋Š” ํฌ๊ฒŒ ECR, ECS Cluster, ECS Service, ECS Task๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.
    • ECR: Docker image ์ €์žฅ์†Œ
    • ECS Cluster: ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ Cluster๋กœ ์—ฌ๋Ÿฌ ์ธ์Šคํ„ด์Šค๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ์ด ์ธ์Šคํ„ด์Šค์— Docker container๊ฐ€ ๋ถ„์‚ฐ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. Serverless๋กœ ํ•  ๊ฒฝ์šฐ์—๋Š” ์ธ์Šคํ„ด์Šค๋„ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
    • ECS Server: Docker ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹คํ–‰ ๊ทธ๋ฃน์ž…๋‹ˆ๋‹ค.
    • ECS Task: ECS Server์— ์‹ค์ œ๋กœ ์‹คํ–‰๋˜๋Š” docker container๋“ค์„ Task ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
    • ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ์™€, ๋ชจ๋‹ˆํ„ฐ๋ง, Auto Scaling ๋“ฑ์˜ ์š”์†Œ๋„ ์žˆ์Œ. ECS๋ฅผ ์ด์šฉํ•˜๋ฉด ์ด๋Ÿฐ ์š”์†Œ๋“ค๊นŒ์ง€ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌ
๐Ÿ†š ECS ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ ๋ฐฉ์‹ (EC2 vs Fargate) ์™„๋ฒฝ ์š”์•ฝ
  1. ์ธ์Šคํ„ด์Šค(EC2) ์ง์ ‘ ๊ด€๋ฆฌ
    • ๊ฐœ๋…: ๊ฐ€์ƒ ์„œ๋ฒ„์˜ ์šด์˜์ฒด์ œ(OS), ๋ณด์•ˆ, ๋„คํŠธ์›Œํฌ ๋“ฑ ๊ธฐ๋ฐ˜ ์ธํ”„๋ผ ์ „์ฒด๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ํ†ต์ œํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
    • ๋น„์œ : "์›”์„ธ ๋‚ด๊ณ  ํ†ต์งธ๋กœ ๋นŒ๋ฆฐ ๋‚ด ์ƒ๊ฐ€." ์ง์ ‘ ์ฒญ์†Œ/๊ด€๋ฆฌํ•ด์•ผ ํ•˜์ง€๋งŒ ๋‚ด ๋ง˜๋Œ€๋กœ ๊ฐœ์กฐํ•  ์ˆ˜ ์žˆ๊ณ , 24์‹œ๊ฐ„ ๋‚ด๋‚ด ์žฅ์‚ฌํ•  ๋•Œ๋Š” ๊ฐ€์„ฑ๋น„๊ฐ€ ์ข‹์Šต๋‹ˆ๋‹ค. (๋Œ€๊ทœ๋ชจ/๊ณ ์ • ํŠธ๋ž˜ํ”ฝ์šฉ)
  2. ์„œ๋ฒ„๋ฆฌ์Šค(Fargate) ๋ฐฉ์‹
    • ๊ฐœ๋…: ๊ท€์ฐฎ์€ ์ธํ”„๋ผ ๊ด€๋ฆฌ๋Š” AWS์— ์ „๋ฉด ์œ„์ž„ํ•˜๊ณ , ๊ฐœ๋ฐœ์ž๋Š” ์˜ค์ง '๋„์ปค ์ปจํ…Œ์ด๋„ˆ(์•ฑ) ์‹คํ–‰' ์ž์ฒด์—๋งŒ ์ง‘์ค‘ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
    • ๋น„์œ : "ํ•„์š”ํ•  ๋•Œ๋งŒ ๋นŒ๋ ค ์“ฐ๋Š” ํ”„๋ฆฌ๋ฏธ์—„ ๊ณต์œ  ์˜คํ”ผ์Šค." ๊ด€๋ฆฌํ•ด ์ฃผ๋Š” ์ง์›์ด ์žˆ์–ด ๊ฐœ๋ฐœ์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์žฅ๊ธฐ๊ฐ„ ํ’€๊ฐ€๋™ํ•˜๋ฉด ์š”๊ธˆ์ด ๋น„์Œ‰๋‹ˆ๋‹ค. (์†Œ๊ทœ๋ชจ/๋ณ€๋™์„ฑ ํŠธ๋ž˜ํ”ฝ์šฉ)

 

  • Task definition
    • ECS์˜ ์ตœ์†Œ ์‹คํ–‰๋‹จ์œ„๋Š” “Task”
    • “Service”๋Š” Task๊ฐ€ ๋‘ ๊ฐœ ์ด์ƒ ๋ชจ์ธ ๊ฒƒ 
    • Task๋Š” docker ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
    • ์–ด๋А ํฌํŠธ์—์„œ ๋ช‡ ๊ฐœ์˜ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์–ด๋–ค ์ด๋ฏธ์ง€๋กœ ์‹คํ–‰ํ• ์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•จ.
    • ์ด ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด Task definition

 

๐Ÿ—จ๏ธ ์‹ค์Šต ๊ฐœ์š”

  • Gitlab์„ ์‚ฌ์šฉํ•˜์—ฌ CI/CD๋ฅผ ์‹ค์Šตํ•ฉ๋‹ˆ๋‹ค.
  • Gitlab ํŒŒ์ดํ”„๋ผ์ธ์—์„œ build๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ AWS ECR์— ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ํŒŒ์ดํ”„๋ผ์ธ์˜ deploy์—์„œ ECS์— ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ—จ๏ธ GitLab

์†Œ๊ฐœ

  • GitLab์„ ์ด์šฉํ•ด์„œ CI/CD ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•˜๊ณ  CI ๊ณผ์ •์„ ์ž๋™ํ™” ํ•ฉ๋‹ˆ๋‹ค.
    • GitLab ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์—ฌ๊ธฐ์— ๊ฐœ๋ฐœํ•œ ์ฝ”๋“œ๋ฅผ PUSH ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ทธ๋Ÿฌ๋ฉด GitLab์€ ์ฝ”๋“œ Push๊ฐ€ ๋œ ๊ฒƒ์„ ํ™•์ธํ•˜๊ณ  Docker Image๋ฅผ ์ƒ์„ฑ ECR์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.
    • ์ด Docker Image๋กœ๋ถ€ํ„ฐ docker container๋ฅผ ECS์— ์‹คํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

GitLab ๊ฐ€์ž… ๋ฐ ๊ทธ๋ฃน, ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

  • GitLab ์‚ฌ์ดํŠธ์— ๊ฐ€์ž…
    • https://about.gitlab.com/ ํŽ˜์ด์ง€์—์„œ gitlab ์„œ๋น„์Šค์— ๊ฐ€์ž…์„ ํ•ฉ๋‹ˆ๋‹ค.
  • GitLab์— ๊ทธ๋ฃน์„ ์ƒ์„ฑํ•˜๊ณ  ๋ธ”๋žญํฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑ

 

spring ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ๋ฐ ์ค€๋น„(GtiLab ์—ฐ๋™)

์Šคํ”„๋ง ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ IDE์—์„œ ์—ด๊ณ  GitLab๊ณผ ์—ฐ๋™ํ•ฉ๋‹ˆ๋‹ค.
  • ์Šคํ”„๋ง ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

  • Gitlab ํ”„๋กœ์ ํŠธ์— ๋“ค์–ด๊ฐ€์„œ Code ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ Clone with HTTPS ์•ˆ์— ํ…์ŠคํŠธ๋ฅผ ๋ณต์‚ฌ

  • ํ”„๋กœ์ ํŠธ ์—ฐ๋™ ์›๊ฒฉ ์ •์˜ URL์— ์œ„์˜ ์ฃผ์†Œ๋ฅผ ๋ถ™์—ฌ ๋„ฃ์Šต๋‹ˆ๋‹ค.

  • ํ”„๋กœ์ ํŠธ๋ฅผ ํ’€ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ’€์„ ํด๋ฆญํ•˜์—ฌ ๋‚˜์˜จ ์ฐฝ์— main ์ด๋ผ๋Š” ๋ธŒ๋žœ์น˜๊ฐ€ ์•ˆ ๋‚˜์˜จ๋‹ค๋ฉด IDE๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ๋‹ค์‹œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • ํ”„๋กœ์ ํŠธ์— ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. (src/main/java/com/spring/sample/SampleController.java)
package com.spring.sample;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SampleController {

    @GetMapping("/sample")
    public String sample() {
        return "Hello World";
    }
}
  • application.properties๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. (src/main/resources/application.properties)
spring.application.name=sample

server.port=8080
  • ๋ฃจํŠธ์— Dockerfile์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. (Dockerfile)
FROM openjdk:17-jdk-slim

VOLUME /tmp

ARG JAR_FILE=build/libs/*.jar

COPY ${JAR_FILE} app.jar

ENTRYPOINT ["java","-jar","/app.jar"]

 

๐Ÿ—จ๏ธ AWS ๋ณด์•ˆ๊ทธ๋ฃน ์ถ”๊ฐ€

๐Ÿ“Œ ์™ธ๋ถ€์—์„œ ์ปจํ…Œ์ด๋„ˆ์— ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋„๋ก ํฌํŠธ์„ ์—ด์–ด์ค๋‹ˆ๋‹ค.
  • EC2 ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•˜์—ฌ ๋ณด์•ˆ ๊ทธ๋ฃน์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  • ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” ๋ณด์•ˆ ๊ทธ๋ฃน์˜ ์•„์ด๋””๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  • ์ธ๋ฐ”์šด๋“œ ๊ทœ์น™ ํŽธ์ง‘์„ ํด๋ฆญํ•˜๊ณ  8080ํฌํŠธ์™€ 80 ํฌํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • ๋‘ ํฌํŠธ ๋ชจ๋‘ 0.0.0.0/0 ์„ ์ž…๋ ฅํ•ด์ค๋‹ˆ๋‹ค.

๐Ÿ›ก๏ธ AWS ์ธ๋ฐ”์šด๋“œ ๊ทœ์น™ ์„ค์ • (ํฌํŠธ์™€ 0.0.0.0/0) ํ•ต์‹ฌ ์š”์•ฝ
  1. 80๊ณผ 8080 ํฌํŠธ๋ฅผ ์—ฌ๋Š” ์ด์œ : 80๋ฒˆ ํฌํŠธ๋Š” ์ผ๋ฐ˜์ ์ธ ์ธํ„ฐ๋„ท ์›น(HTTP) ์ ‘์†์„ ์œ„ํ•œ '๊ธฐ๋ณธ ๋Œ€๋ฌธ'์ด๊ณ , 8080๋ฒˆ ํฌํŠธ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ์Šคํ”„๋ง ๋ถ€ํŠธ ์„œ๋ฒ„๊ฐ€ ์†๋‹˜์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” '์ „์šฉ ๋ฐฉ๋ฌธ'์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  2. 0.0.0.0/0์˜ ์ง„์งœ ์˜๋ฏธ (์™„์ „ ๊ฐœ๋ฐฉ): "์ „ ์„ธ๊ณ„ ์–ด๋–ค ์ปดํ“จํ„ฐ(IP)์—์„œ ์ ‘์†ํ•˜๋“  ๋ชจ๋‘ ํ—ˆ๋ฝํ•˜๊ฒ ๋‹ค"๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋’ค์— ๋ถ™์€ /0์€ ๋„คํŠธ์›Œํฌ ์ œํ•œ ๋ฒ”์œ„๋ฅผ ์ •ํ•˜๋Š” ๋ฌธ๋ฒ•(CIDR)์ธ๋ฐ, ์ˆซ์ž๊ฐ€ 0์ด๋ฉด '์•„๋ฌด๋Ÿฐ ์ œํ•œ์„ ๋‘์ง€ ์•Š๊ฒ ๋‹ค(Anywhere)'๋Š” ์˜๋ฏธ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

๐Ÿ—จ๏ธ AWS ECR

๐Ÿ“Œ Amazon ECR์€ AWS์—์„œ ์ œ๊ณตํ•˜๋Š” ์™„์ „ ๊ด€๋ฆฌํ˜• docker image ์ €์žฅ์†Œ์ž…๋‹ˆ๋‹ค. Amazon์˜ ECS, EKS, Elastic Beanstalk ๋“ฑ ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์™€ ํ†ตํ•ฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ผ๋‹จ ์ด๋ฏธ์ง€๋ฅผ ECR์— ๋“ฑ๋ก์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

  • AWS์— ๊ฐ€์ž… ํ›„ ECR ๋Œ€์‹œ๋ณด๋“œ์— ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ƒ์„ฑ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ์‹๋ณ„ํ•˜๊ธฐ ์‰ฝ๋„๋ก ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ด๋ฆ„์„ ๊นƒ๋žฉ์˜ ๊ทธ๋ฃน/๋ฆฌํฌ์ง€ํ† ๋ฆฌ์™€ ์ผ์น˜์‹œํ‚ต๋‹ˆ๋‹ค.

  • ์ƒ์„ฑํ•œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ํด๋ฆญํ•˜์—ฌ ํ‘ธ์‰ฌ ๋ช…๋ น ๋ณด๊ธฐ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ช…๋ น์–ด๋“ค์€ ๊นƒ๋žฉ CI/CD์—์„œ ์‚ฌ์šฉ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๐Ÿ—จ๏ธ AWS ECS

๐Ÿ“Œ Amazon ECS (Elastic Container Service)๋Š” Amazon Web Services (AWS)์—์„œ ์ œ๊ณตํ•˜๋Š” ์™„์ „ ๊ด€๋ฆฌํ˜• ์ปจํ…Œ์ด๋„ˆ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ์ด๋Š” Docker ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‰ฝ๊ฒŒ ์‹คํ–‰, ์ •์ง€, ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค๋‹ˆ๋‹ค. 

 

  • ECS ๋Œ€์‹œ๋ณด๋“œ์— ์ ‘์†ํ•˜์—ฌ ํด๋Ÿฌ์Šคํ„ฐ ์ƒ์„ฑ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฆ„๋งŒ ์„ค์ •ํ•˜๊ณ  ์ธํ”„๋ผ๋Š” ์„œ๋ฒ„๋ฆฌ์Šค ์„ ํƒ ํ›„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • ํƒœ์Šคํฌ ์ •์˜ ๋ฉ”๋‰ด์—์„œ ์ƒˆ ํƒœ์Šคํฌ ์ •์˜ ์ƒ์„ฑ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํŒจ๋ฐ€๋ฆฌ ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ค๋‹ˆ๋‹ค.

  • ์Šคํฌ๋กค ํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ์— ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ URL์—๋Š” ECR์˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ URL์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    • ํฌํŠธ์— 80 ํฌํŠธ๋ฅผ 8080์œผ๋กœ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ทธ ํ›„ ์ƒ์„ฑ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  • ํด๋Ÿฌ์Šคํ„ฐ ๋ฉ”๋‰ด๋กœ ๋Œ์•„๊ฐ€์„œ ์ƒ์„ฑ๋œ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ํด๋ฆญํ•œ ํ›„, ์„œ๋น„์Šค์—์„œ ์ƒ์„ฑ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
    • ๋ฐฐํฌ ๊ตฌ์„ฑ์—์„œ ํŒจ๋ฐ€๋ฆฌ๋ฅผ ์•ž์„œ ์ƒ์„ฑํ–ˆ๋˜ ํƒœ์Šคํฌ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์„œ๋น„์Šค ์ด๋ฆ„๋„ ์ž…๋ ฅํ•ด์ค๋‹ˆ๋‹ค.

  • ์Šคํฌ๋กค ํ•˜์—ฌ ์•„๋ž˜์žˆ๋Š” ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ์—์„œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    • ์ •๋ณด๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. ํฌํŠธ๋Š” 80์ž„์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

 

โš–๏ธ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ(ALB)์˜ ํฌํŠธ๊ฐ€ 80์ธ ์ด์œ 
  1. 80๋ฒˆ ํฌํŠธ์˜ ์ •์ฒด: "์ธํ„ฐ๋„ท์˜ ํ‘œ์ค€ ๋Œ€๋ฌธ"
    • ์šฐ๋ฆฌ๊ฐ€ ์ธํ„ฐ๋„ท ๋ธŒ๋ผ์šฐ์ €์—์„œ http://๋กœ ์‹œ์ž‘ํ•˜๋Š” ์›น์‚ฌ์ดํŠธ์— ์ ‘์†ํ•  ๋•Œ, ๋ธŒ๋ผ์šฐ์ €๋Š” ์‚ฌ์šฉ์ž ๋ชฐ๋ž˜ ๊ธฐ๋ณธ์ ์œผ๋กœ 80๋ฒˆ ํฌํŠธ๋ฅผ ํ–ฅํ•ด ์ฐพ์•„๊ฐ‘๋‹ˆ๋‹ค.
    • ์ฆ‰, ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๋“ค์ด ์ฃผ์†Œ์ฐฝ ๋’ค์— :8080 ๊ฐ™์€ ๊ท€์ฐฎ์€ ์ˆซ์ž๋ฅผ ๋ถ™์ด์ง€ ์•Š๊ณ  ๊น”๋”ํ•˜๊ฒŒ ์ฃผ์†Œ๋งŒ ์ณ์„œ ๋“ค์–ด์˜ค๊ฒŒ ํ•˜๋ ค๋ฉด, ๋ฐ–์œผ๋กœ ํ†ตํ•˜๋Š” ๋Œ€๋ฌธ์€ ๋ฐ˜๋“œ์‹œ 80๋ฒˆ์œผ๋กœ ์—ด์–ด๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ์™€ ์ปจํ…Œ์ด๋„ˆ์˜ ์™„๋ฒฝํ•œ ์—ญํ•  ๋ถ„๋‹ด
    • ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ (80๋ฒˆ ๋Œ€๊ธฐ): ์‹๋‹น์˜ '์ •๋ฌธ'์ž…๋‹ˆ๋‹ค. ๋ฐ–์—์„œ ์˜ค๋Š” ์†๋‹˜(ํŠธ๋ž˜ํ”ฝ)์„ 80๋ฒˆ ๋ฌธ์—์„œ ๊ฐ€์žฅ ๋จผ์ € ๋งž์ดํ•ฉ๋‹ˆ๋‹ค.
    • ์Šคํ”„๋ง ๋ถ€ํŠธ ์ปจํ…Œ์ด๋„ˆ (8080๋ฒˆ ๋Œ€๊ธฐ): ์‹๋‹น์˜ '์ฃผ๋ฐฉ'์ž…๋‹ˆ๋‹ค. ์•ž์„œ ํƒœ์Šคํฌ ์ •์˜์—์„œ ์„œ๋ฒ„๊ฐ€ ์ผํ•  ๊ณต๊ฐ„์„ 8080์œผ๋กœ ์„ค์ •ํ–ˆ์—ˆ์ฃ .
    • ์—ฐ๊ฒฐ ๊ณผ์ •: ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๊ฐ€ ์ •๋ฌธ(80๋ฒˆ)์œผ๋กœ ๋“ค์–ด์˜จ ํŠธ๋ž˜ํ”ฝ์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฐ›์•„์„œ, ๋’ค์—์„œ ๋ฌต๋ฌตํžˆ ์ผํ•˜๊ณ  ์žˆ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ ์ฃผ๋ฐฉ(8080๋ฒˆ)์œผ๋กœ ํ† ์Šค(์ „๋‹ฌ)ํ•ด ์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•œ ์ค„ ์š”์•ฝ: "์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ์†Œ์ฐฝ์— ํฌํŠธ ๋ฒˆํ˜ธ ์—†์ด ํŽธํ•˜๊ฒŒ ์ ‘์†(HTTP ๊ธฐ๋ณธ ํฌํŠธ 80)ํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ , ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๊ฐ€ ์ด ์š”์ฒญ์„ ๋ฐ›์•„์„œ ๋‚ด๋ถ€์˜ ์Šคํ”„๋ง ๋ถ€ํŠธ ์„œ๋ฒ„(8080)๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ํ† ์Šคํ•ด ์ฃผ๊ธฐ ์œ„ํ•œ ์„ค์ •์ž…๋‹ˆ๋‹ค!"

 

๐Ÿ—จ๏ธ AWS IAM

  • AWS IAM ์— ์ ‘์†ํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ƒ์„ฑ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
    • ์ง์ ‘ ์ •์ฑ… ์—ฐ๊ฒฐ์„ ํด๋ฆญํ•˜์—ฌ AdministratorAccess ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • ์ƒ์„ฑํ•œ ์‚ฌ์šฉ์ž ์ƒ์„ธํŽ˜์ด์ง€์— ์ ‘์†ํ•˜์—ฌ ์•ก์„ธ์Šค ํ‚ค ๋งŒ๋“ค๊ธฐ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„ ๊ธฐํƒ€๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ์•ก์„ธ์Šค ํ‚ค๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋ฉด .csv ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ๋ฅผ ํด๋ฆญํ•˜์—ฌ ํŒŒ์ผ์„ ์ž˜ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค ํŒŒ์ผ์—๋Š” ์—‘์„ธ์Šค์— ๊ด€๋ จ๋œ ํ‚ค๊ฐ€ ์ €์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ—จ๏ธ ๊นƒ๋žฉ CI ํŒŒ์ผ ์ž‘์„ฑ ๋ฐ ํ‘ธ์‰ฌ

  • ๊นƒ๋žฉ ํ”„๋กœ์ ํŠธ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋ฉ”๋‰ด์—์„œ Settings > CI/CD > Variables ๋ฅผ ํด๋ฆญํ•˜๊ณ  2๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
    • โžก๏ธ ์ด ๋‘ ํ‚ค์˜ ๊ฐ’์€ ์•„๊นŒ AWS IAM ์—์„œ ๋‹ค์šด๋ฐ›์€ csv์— ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ” GitLab CI/CD Variables & Expand ์„ค์ • ํ•ต์‹ฌ ์š”์•ฝ
  1. ํ”„๋กœ์ ํŠธ Variables (๋ณ€์ˆ˜)
    1. ์—ญํ• : ์ฝ”๋“œ์— ์ง์ ‘ ๋…ธ์ถœ๋˜๋ฉด ์œ„ํ—˜ํ•œ '๋น„๋ฐ€ ์ •๋ณด(AWS ์ ‘์† ํ‚ค, DB ๋น„๋ฐ€๋ฒˆํ˜ธ, API ํ† ํฐ ๋“ฑ)'๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด๊ด€ํ•˜๋Š” ๊ธˆ๊ณ ์ž…๋‹ˆ๋‹ค.
    2. ์ด์œ : ์†Œ์Šค ์ฝ”๋“œ์— ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๊ทธ๋Œ€๋กœ ์ ์–ด์„œ ์˜ฌ๋ฆฌ๋ฉด ํ•ดํ‚น์˜ ํ‘œ์ ์ด ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๊ณณ์—๋งŒ ๋”ฐ๋กœ ๋“ฑ๋กํ•ด๋‘๊ณ , CI/CD(์ž๋™ ๋ฐฐํฌ)๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งŒ ์•ˆ์ „ํ•˜๊ฒŒ ๊ฐ€์ ธ๋‹ค ์“ฐ๋„๋ก ๊ฒฉ๋ฆฌํ•ด ๋‘๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
      • Protected
        → main/master ๊ฐ™์€ ๋ณดํ˜ธ ๋ธŒ๋žœ์น˜์—์„œ๋งŒ Variables ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ œํ•œํ•˜๋Š” ์˜ต์…˜
      • Masked
        → CI/CD ๋กœ๊ทธ์— ๋น„๋ฐ€๋ฒˆํ˜ธ๋‚˜ ํ† ํฐ ๊ฐ’์ด ๋…ธ์ถœ๋˜์ง€ ์•Š๋„๋ก ์ˆจ๊ธฐ๋Š” ์˜ต์…˜
      • โ€ป ์‹ค์Šต ํ™˜๊ฒฝ์—์„œ๋Š” ํ…Œ์ŠคํŠธ ํŽธ์˜๋ฅผ ์œ„ํ•ด ์˜ต์…˜์„ ํ•ด์ œํ•˜๊ณ  ์‚ฌ์šฉ
  2. Expand variable reference (๋ณ€์ˆ˜ ํ™•์žฅ ์ฐธ์กฐ)
    • ์—ญํ• : ์ž…๋ ฅํ•œ ๊ฐ’ ์•ˆ์— $ ๊ธฐํ˜ธ๊ฐ€ ์žˆ์„ ๋•Œ, ์ด๋ฅผ '๋˜ ๋‹ค๋ฅธ ๋ณ€์ˆ˜'๋กœ ํ•ด์„ํ• ์ง€ ์•„๋‹ˆ๋ฉด '๊ทธ๋ƒฅ ํŠน์ˆ˜๋ฌธ์ž $'๋กœ ์ฝ์„์ง€ ๊ฒฐ์ •ํ•˜๋Š” ์˜ต์…˜์ž…๋‹ˆ๋‹ค.
    • โœ… ์ฒดํฌํ•  ๋•Œ: ๊ฐ’ ์•ˆ์— ๋‹ค๋ฅธ ๋ณ€์ˆ˜๋ฅผ ์กฐํ•ฉํ•ด์„œ ์“ธ ๋•Œ (์˜ˆ: $USER_NAME์ด๋ผ๊ณ  ์ ์œผ๋ฉด ์‹ค์ œ ์ด๋ฆ„์œผ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๊ฐ€์ ธ์˜ด)
    • โŒ ์ฒดํฌ ํ•ด์ œํ•  ๋•Œ (๋งค์šฐ ์ค‘์š” ๐Ÿšจ): ๋น„๋ฐ€๋ฒˆํ˜ธ๋‚˜ ํ‚ค ๊ฐ’์— ํŠน์ˆ˜๋ฌธ์ž๋กœ $๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์„ ๋•Œ! ์ด ์ฒดํฌ๊ฐ€ ์ผœ์ ธ ์žˆ์œผ๋ฉด ๊นƒ๋žฉ์ด $ ๋’ค์˜ ๊ธ€์ž๋“ค์„ ๋ณ€์ˆ˜๋กœ ์ฐฉ๊ฐํ•ด์„œ ๊ฐ’์„ ์—‰๋šฑํ•˜๊ฒŒ ๋ง๊ฐ€๋œจ๋ฆฝ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋“ฑ๋กํ•  ๋•Œ๋Š” ๊ผญ ์ฒดํฌ๋ฅผ ํ•ด์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

  • ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ํด๋”์— .gitlab-ci.yml์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. docker build ์•ˆ์— ์Šคํฌ๋ฆฝํŠธ๋Š” ECR์—์„œ ํ‘ธ์‰ฌ ๋ช…๋ น ๋ณด๊ธฐ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • deploy ์•ˆ์— ์žˆ๋Š” ํ•ญ๋ชฉ์€ ECS์˜ ์ƒ์„ฑ ํ•ญ๋ชฉ๋“ค ์ด๋ฆ„์„ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค.
services:
  - docker:stable-dind
  
# โญ๏ธ [ํ•ต์‹ฌ 1] ํŒŒ์ดํ”„๋ผ์ธ ์ „์ฒด 3๋‹จ๊ณ„ ํ๋ฆ„ (์ด ์ˆœ์„œ๋Œ€๋กœ ์ž‘์—…์ด ์ง„ํ–‰๋จ)
stages:
  - build jar
  - build and push docker image
  - deploy
  
variables:
  APPLICATION_NAME: "01"
  TAG_NAME: "latest"
  DOCKER_IMAGE: "group-18934028/project-01"
  
build:
  image: openjdk:17-jdk-slim
  stage: build jar
  script:
    - chmod +x gradlew
    - ./gradlew clean build
    
  # โญ๏ธ [ํ•ต์‹ฌ 2] ํŒŒ์ผ ๋„˜๊ฒจ์ฃผ๊ธฐ (๋ฐฉ๊ธˆ ๋งŒ๋“  .jar ํŒŒ์ผ์„ ๋ฒ„๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค์Œ ๋„์ปค ์ž‘์—…์œผ๋กœ ์ „๋‹ฌ!)
  artifacts:
    paths:
      - build/libs/*.jar
      
docker build:
  image: docker:latest
  stage: build and push docker image
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_REF_NAME == "main"
      variables:
        TAG_NAME: "latest"
    - if: $CI_COMMIT_BRANCH == "develop" || $CI_COMMIT_REF_NAME == "develop"
      variables:
        TAG_NAME: "develop"

  script:
    # ๐Ÿ—‘๏ธ ์ด ๋ถ€๋ถ„์€ ๋‹จ์ˆœํžˆ AWS ์ ‘์† ๋„๊ตฌ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์„ค์น˜ํ•˜๋Š” ๋ช…๋ น์–ด๋“ค์ž…๋‹ˆ๋‹ค.
    - apk add --update --no-cache curl py3-pip py3-virtualenv
    - python3 -m venv /tmp/venv
    - source /tmp/venv/bin/activate
    - pip install awscli
    # โญ๏ธ [ํ•ต์‹ฌ 3] ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆจ๊ฒจ์„œ ์“ฐ๊ธฐ! (๊นƒ๋žฉ์— ๋“ฑ๋กํ•œ ๋ณด์•ˆํ‚ค๋ฅผ $ ๊ธฐํ˜ธ๋กœ ๋ถˆ๋Ÿฌ์™€์„œ ์•ˆ์ „ํ•˜๊ฒŒ ์„ธํŒ…)
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
    - aws configure set region ap-northeast-2
    
    # (๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค๊ณ , AWS ECR ์ €์žฅ์†Œ ์ด๋ฆ„ํ‘œ๋ฅผ ๋ถ™์ธ ๋’ค ๋ฐ€์–ด ์˜ฌ๋ฆฌ๋Š” ํ•ต์‹ฌ ์ž‘์—…๋“ค)
    - docker build -t $DOCKER_IMAGE .
    - docker tag $DOCKER_IMAGE:latest 730335597998.dkr.ecr.ap-northeast-2.amazonaws.com/$DOCKER_IMAGE:$TAG_NAME
    - aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 730335597998.dkr.ecr.ap-northeast-2.amazonaws.com
    - docker push 730335597998.dkr.ecr.ap-northeast-2.amazonaws.com/$DOCKER_IMAGE:$TAG_NAME

deploy:
  image: python:3.9-slim
  stage: deploy
  script:
    # ๐Ÿ—‘๏ธ ์—ฌ๊ธฐ๋„ 2๋‹จ๊ณ„์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋‹จ์ˆœ ๋„๊ตฌ ์„ค์น˜ ๊ณผ์ •์ž…๋‹ˆ๋‹ค.
    - python3 -m venv /tmp/venv
    - source /tmp/venv/bin/activate
    - pip install awscli
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
    - aws configure set region ap-northeast-2
    
    # โญ๏ธ [ํ•ต์‹ฌ 4] ๋Œ€๋ง์˜ ์ž๋™ ๋ฐฐํฌ ๋ฒ„ํŠผ! (AWS ECS์—๊ฒŒ "์ƒˆ ์ด๋ฏธ์ง€ ์˜ฌ๋ผ์™”์œผ๋‹ˆ ๊ฐ•์ œ๋กœ ์„œ๋ฒ„ ์ƒˆ๋กœ๊ณ ์นจ ํ•ด!" ๋ผ๊ณ  ์ง€์‹œ)
    - aws ecs update-service --cluster project-cluster --service project-01-service --task-definition project-01-task:1 --force-new-deployment
  • IDE์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ปค๋ฐ‹, ํ‘ธ์‰ฌํ•˜์—ฌ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์ค„ ๊ตฌ๋ถ„ ๊ธฐํ˜ธ ๊ฒฝ๊ณ ๊ฐ€ ๋‚˜์˜ค๋ฉด ๊ทธ๋Œ€๋กœ ์ปค๋ฐ‹์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

  • GitLab์˜ ํŒŒ์ดํ”„๋ผ์ธ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์Šคํ…Œ์ด์ง€๊ฐ€ ๋ชจ๋‘ ์„ฑ๊ณตํ•˜์ง€ ์•Š์œผ๋ฉด ์‹คํŒจํ•œ ์Šคํ…Œ์ด์ง€๋ฅผ ํด๋ฆญํ•˜์—ฌ ์˜ค๋ฅ˜ ๋‚ด์šฉ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿš€ [CI/CD] GitLab + Docker + AWS(ECR/ECS) ์ž๋™ ๋ฐฐํฌ ํ๋ฆ„ ์ •๋ฆฌ

  • ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  Push๋งŒ ํ•˜๋ฉด, ๋นŒ๋“œ๋ถ€ํ„ฐ AWS ์„œ๋ฒ„ ๋ฐฐํฌ๊นŒ์ง€ ๋ชจ๋“  ๊ณผ์ •์ด ์ž๋™์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋Š” CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค.

๐ŸŒŠ 1. ์ „์ฒด ์ž๋™ ๋ฐฐํฌ ํ๋ฆ„ (Pipeline)

  • git push ํ•œ ๋ฒˆ์œผ๋กœ ์•„๋ž˜์˜ 4๋‹จ๊ณ„๊ฐ€ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
  1. ๋‚ด PC: git push (GitLab์œผ๋กœ ์ฝ”๋“œ ์ „์†ก)
  2. GitLab CI/CD (build jar): Gradle๋กœ Spring Boot ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ
  3. Docker (docker build & push): Docker Image ์ƒ์„ฑ ํ›„ AWS ECR์— ์—…๋กœ๋“œ
  4. AWS ECS (deploy): ECR์—์„œ ์ด๋ฏธ์ง€๋ฅผ Pull ๋ฐ›์•„ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ (์„œ๋ฒ„ ์žฌ๋ฐฐํฌ)

๐Ÿ’ก 2. ๋ฐฐํฌ ๊ณผ์ • ํ•„์ˆ˜ ํ•ต์‹ฌ ๊ฐœ๋…

  • Dockerfile: "์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ ์–ด๋–ป๊ฒŒ ์‹คํ–‰ํ• ์ง€" ์ ์–ด๋‘” ์‹คํ–‰ ์„ค๋ช…์„œ.
  • ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€: ์ปจํ…Œ์ด๋„ˆ ์•ˆ์˜ "๊ธฐ๋ณธ ์ปดํ“จํ„ฐ ํ™˜๊ฒฝ(Java/Linux)". (์ด๊ฒŒ ์—†์œผ๋ฉด Docker ์ปจํ…Œ์ด๋„ˆ ์ž์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์Œ!)
  • Docker Image: ์‹คํ–‰์— ํ•„์š”ํ•œ ์ฝ”๋“œ + Java + ์„ค์ • ๋“ฑ์„ ์ „๋ถ€ ๋ฌถ์€ ์‹คํ–‰ ํŒจํ‚ค์ง€.
  • AWS ECR: ์™„์„ฑ๋œ Docker ์ด๋ฏธ์ง€๋ฅผ ์ €์žฅํ•˜๋Š” ์ €์žฅ์†Œ.
  • AWS ECS: ECR์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์™€ ์ปจํ…Œ์ด๋„ˆ๋กœ ๋„์šฐ๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์‹คํ–‰/๊ด€๋ฆฌ ์„œ๋น„์Šค.

๐Ÿšจ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… (Troubleshooting) ํ•ต์‹ฌ ์ •๋ฆฌ

โŒ OpenJDK ์ด๋ฏธ์ง€ Pull ์‹คํŒจ (๋ฒ ์ด์Šค ์ด๋ฏธ์ง€ ๋ถ€์žฌ)

  • ์—๋Ÿฌ ๋ฉ”์‹œ์ง€:
  manifest for openjdk:17-jdk-slim not found
  • ์›์ธ: Docker Hub์— ํ•ด๋‹น ์ด๋ฏธ์ง€ ํƒœ๊ทธ(openjdk:17-jdk-slim)๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•„ GitLab Runner๊ฐ€ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ์ง€ ๋ชปํ•จ.
  • ํ•ด๊ฒฐ: Dockerfile๊ณผ GitLab CI์—์„œ Java ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€๋ฅผ ์•ˆ์ •์ ์ธ eclipse-temurin:17-jdk๋กœ ๋ณ€๊ฒฝ.
build:
  image: eclipse-temurin:17-jdk
  stage: build jar
  script:
    - chmod +x gradlew
    - ./gradlew clean build
  artifacts:
    paths:
      - build/libs/*.jar

 

โŒ ECS ์ด๋ฏธ์ง€ Pull ์‹คํŒจ (๋ธŒ๋žœ์น˜๋ช… ๋ถˆ์ผ์น˜๋กœ ์ธํ•œ Docker Build ์Šคํ‚ต)

  • ์—๋Ÿฌ ๋ฉ”์‹œ์ง€:
์ค‘์ง€ ์ฝ”๋“œ: TaskFailedToStart
CannotPullContainerError: pull image manifest has been retried 7 time(s): failed to resolve ref ... :latest: not found
  • ์›์ธ: ECS๊ฐ€ ECR์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค ํ–ˆ์œผ๋‚˜ ์ €์žฅ์†Œ๊ฐ€ ๋น„์–ด์žˆ์—ˆ์Œ. ํŒŒ์ดํ”„๋ผ์ธ ๋กœ๊ทธ๋ฅผ ์ถ”์ ํ•ด ๋ณด๋‹ˆ ์ „์ฒด 3๋‹จ๊ณ„ ์ค‘ ์ž‘์—…์ด 2๊ฐœ(build jar, deploy)๋งŒ ์‹คํ–‰๋˜์—ˆ์Œ. ํ˜„์žฌ GitLab ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ณธ ๋ธŒ๋žœ์น˜๋Š” master์ธ๋ฐ, .gitlab-ci.yml์˜ ์‹คํ–‰ ์กฐ๊ฑด(rules)์—๋Š” main ๋ธŒ๋žœ์น˜๋งŒ ์„ค์ •๋˜์–ด ์žˆ์–ด ์ค‘๊ฐ„์˜ Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ๋ฐ ECR ์—…๋กœ๋“œ ๋‹จ๊ณ„๊ฐ€ ํ†ต์งธ๋กœ ์Šคํ‚ต(Skip) ๋œ ๊ฒƒ์ด ๊ทผ๋ณธ ์›์ธ.
  • ํ•ด๊ฒฐ: .gitlab-ci.yml ํŒŒ์ผ์˜ docker build ์ž‘์—… rules ์กฐ๊ฑด์— master ๋ธŒ๋žœ์น˜๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•˜์—ฌ, ์ฝ”๋“œ๋ฅผ ํ‘ธ์‹œํ•  ๋•Œ ๋„์ปค ๋นŒ๋“œ์™€ ECR ์—…๋กœ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋„๋ก ์ˆ˜์ •.
docker build:
  image: docker:latest
  stage: build and push docker image
  rules:
    # ๊ธฐ์กด main ์กฐ๊ฑด ๋’ค์— master ๋ธŒ๋žœ์น˜ ์กฐ๊ฑด์„ ์ถ”๊ฐ€!
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_REF_NAME == "main" || $CI_COMMIT_BRANCH == "master" || $CI_COMMIT_REF_NAME == "master"
      variables:
        TAG_NAME: "latest"
    - if: $CI_COMMIT_BRANCH == "develop" || $CI_COMMIT_REF_NAME == "develop"
      variables:
        TAG_NAME: "develop"

 

โŒ Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ์‹คํŒจ (GitLab ํ™˜๊ฒฝ vs ์‹ค์ œ ๋ฐฐํฌ ํ™˜๊ฒฝ์˜ ์ฐจ์ด)

  • ์ฆ์ƒ: .gitlab-ci.yml์˜ ์ž๋ฐ” ์ด๋ฏธ์ง€๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ build jar ๋‹จ๊ณ„๋Š” ์„ฑ๊ณตํ–ˆ์œผ๋‚˜, docker build ๋‹จ๊ณ„์—์„œ ๋‹ค์‹œ ์‹คํŒจํ•จ.
  • ์›์ธ: Java๊ฐ€ ํ•„์š”ํ•œ ๊ณณ์ด ๋‘ ๊ตฐ๋ฐ์˜€๋Š”๋ฐ ํ•œ ๊ณณ๋งŒ ์ˆ˜์ •ํ–ˆ๊ธฐ ๋•Œ๋ฌธ.
    1. yml ํŒŒ์ผ: ์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•  ๋•Œ ์ž ๊น ๋นŒ๋ ค ์“ฐ๋Š” '์ž„์‹œ ์ž‘์—…์‹ค'
    2. Dockerfile: ์‹ค์ œ AWS ์„œ๋ฒ„์—์„œ ๊ณ„์† ๋Œ์•„๊ฐˆ '์ตœ์ข… ์‹คํ–‰ ํ™˜๊ฒฝ' ์ž„์‹œ ์ž‘์—…์‹ค์˜ ์˜ค๋ฅ˜๋Š” ๊ณ ์ณค์ง€๋งŒ, ์ตœ์ข… ์‹คํ–‰ ํ™˜๊ฒฝ์˜ ๋ผˆ๋Œ€๊ฐ€ ๋˜๋Š” Dockerfile์˜ ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€(openjdk:17)๋Š” ์—ฌ์ „ํžˆ Docker Hub์—์„œ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ์ƒํƒœ์˜€์Œ.
  • ํ•ด๊ฒฐ: Dockerfile์˜ FROM ๊ตฌ๋ฌธ ์—ญ์‹œ ์•ˆ์ •์ ์ธ ๊ณต์‹ ๋ฐฐํฌํŒ์ธ eclipse-temurin:17-jdk๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ํ•ด๊ฒฐ.
FROM eclipse-temurin:17-jdk

VOLUME /tmp

ARG JAR_FILE=build/libs/*.jar

COPY ${JAR_FILE} app.jar

ENTRYPOINT ["java","-jar","/app.jar"]

 

 

๐Ÿ—จ๏ธ ํ™•์ธํ•˜๊ธฐ

  • ECS ๋Œ€์‹œ๋ณด๋“œ์—์„œ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ํด๋ฆญํ•˜๊ณ  ์„œ๋น„์Šค ์ƒ์„ธ ํŽ˜์ด์ง€๊นŒ์ง€ ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ ๋ณด๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

 

  • ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ ํŽ˜์ด์ง€์—์„œ DNS ์ด๋ฆ„์„ ๋ณต์‚ฌํ•˜์—ฌ ์›น์— ์ž…๋ ฅํ•˜๊ณ  ์Šคํ”„๋ง ํ”„๋กœ์ ํŠธ์˜ ์—”๋“œ ํฌ์ธํŠธ์— ์ ‘๊ทผํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ—จ๏ธ ์ถ”๊ฐ€ ์ •๋ณด) ๊นƒํ—ˆ๋ธŒ ์•ก์…˜

  • ์ธํ…”๋ฆฌ์ œ์ด ์„ค์ •์—์„œ ๊นƒํ—ˆ๋ธŒ๋ฅผ ๋กœ๊ทธ์ธํ›„ ๋ฉ”๋‰ด์—์„œ VCS ๋˜๋Š” Git ๋ฉ”๋‰ด์—์„œ Github์— ํ”„๋กœ์ ํŠธ ๊ณต์œ ๋ฅผ ํด๋ฆญํ•˜์—ฌ ๊นƒํ—ˆ๋ธŒ์—๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • Actions ํŽ˜์ด์ง€์—์„œ Ecs๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  “Configure”๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

 

  • ์ดํ›„ ๋‚˜์˜ค๋Š” ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ์„ ์•„๋ž˜์˜ ๋‚ด์šฉ์œผ๋กœ ๋Œ€์ฒด ํ•ฉ๋‹ˆ๋‹ค.
    • ๋‚ด์šฉ์„ ๋Œ€์ฒดํ•  ๋•Œ, env ์˜์—ญ์˜ ์ •๋ณด๋ฅผ ๋‚˜์˜ AWS ์ •๋ณด๋กœ ๋Œ€์ฒดํ•˜์—ฌ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„ “Commit changes” ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

# This workflow will build and push a new container image to Amazon ECR,
# and then will deploy a new task definition to Amazon ECS, when there is a push to the "main" branch.
#
# To use this workflow, you will need to complete the following set-up steps:
#
# 1. Create an ECR repository to store your images.
#    For example: `aws ecr create-repository --repository-name my-ecr-repo --region us-east-2`.
#    Replace the value of the `ECR_REPOSITORY` environment variable in the workflow below with your repository's name.
#    Replace the value of the `AWS_REGION` environment variable in the workflow below with your repository's region.
#
# 2. Create an ECS task definition, an ECS cluster, and an ECS service.
#    For example, follow the Getting Started guide on the ECS console:
#      https://us-east-2.console.aws.amazon.com/ecs/home?region=us-east-2#/firstRun
#    Replace the value of the `ECS_SERVICE` environment variable in the workflow below with the name you set for the Amazon ECS service.
#    Replace the value of the `ECS_CLUSTER` environment variable in the workflow below with the name you set for the cluster.
#
# 3. Store your ECS task definition as a JSON file in your repository.
#    The format should follow the output of `aws ecs register-task-definition --generate-cli-skeleton`.
#    Replace the value of the `ECS_TASK_DEFINITION` environment variable in the workflow below with the path to the JSON file.
#    Replace the value of the `CONTAINER_NAME` environment variable in the workflow below with the name of the container
#    in the `containerDefinitions` section of the task definition.
#
# 4. Store an IAM user access key in GitHub Actions secrets named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
#    See the documentation for each action used below for the recommended IAM policies for this IAM user,
#    and best practices on handling the access key credentials.

name: Deploy to Amazon ECS

on:
  push:
    branches: [ "main" ]

env:
  AWS_REGION: ap-southeast-2                  # set this to your preferred AWS region, e.g. us-west-1
  ECR_REPOSITORY: group-18934028/test-01         # set this to your Amazon ECR repository name
  ECS_SERVICE: test-01-service                 # set this to your Amazon ECS service name
  ECS_CLUSTER: test-01-cluster                # set this to your Amazon ECS cluster name
  ECS_TASK_DEFINITION: .github/workflows/project-01-task-revision1.json # set this to the path to your Amazon ECS task definition
                                               # file, e.g. .aws/task-definition.json
  CONTAINER_NAME: test-01-container           # set this to the name of the container in the
                                               # containerDefinitions section of your task definition

permissions:
  contents: read

jobs:
  build:
    name: Build Jar
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'

    - name: Grant execute permission for gradlew
      run: chmod +x gradlew

    - name: Build with Gradle
      run: ./gradlew clean build

    - name: Upload Build Artifacts
      uses: actions/upload-artifact@v3
      with:
        name: build-libs
        path: build/libs/*.jar

        
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    needs: build
    environment: production

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Download Build Artifacts
      uses: actions/download-artifact@v3
      with:
        name: build-libs
        path: build/libs

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Build, tag, and push image to Amazon ECR
      id: build-image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ github.sha }}
      run: |
        # Build a docker container and
        # push it to ECR so that it can
        # be deployed to ECS.
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
        echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

    - name: Fill in the new image ID in the Amazon ECS task definition
      id: task-def
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ env.ECS_TASK_DEFINITION }}
        container-name: ${{ env.CONTAINER_NAME }}
        image: ${{ steps.build-image.outputs.image }}

    - name: Deploy Amazon ECS task definition
      uses: aws-actions/amazon-ecs-deploy-task-definition@v1
      with:
        task-definition: ${{ steps.task-def.outputs.task-definition }}
        service: ${{ env.ECS_SERVICE }}
        cluster: ${{ env.ECS_CLUSTER }}
        wait-for-service-stability: true

 

  • ๊นƒํ—ˆ๋ธŒ ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์—์„œ Code ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ณ  Codespaces ํƒญ์—์„œ Create codespace on main์„ ํด๋ฆญํ•˜์—ฌ ์›น IDE๋ฅผ ์—ฝ๋‹ˆ๋‹ค. (์ด ๋‚ด์šฉ์€ ์ธํ…”๋ฆฌ์ œ์ด์—์„œ ํ•ด๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค.)

 

  • .github/workflows ํด๋”์— project-01-task-revision1.json์ด๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. AWS์˜ ํ…Œ์Šคํฌ ์ •์˜ ์ƒ์„ธ ํŽ˜์ด์ง€์—์„œ JSON ํƒญ์„ ํด๋ฆญํ•˜์—ฌ ํด๋ฆฝ๋ณด๋“œ๋กœ ๋ณต์‚ฌ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
    • project-01-task-revision1.json ํŒŒ์ผ์— ๋ณต์‚ฌํ•œ ๋‚ด์šฉ์„ ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•˜๊ณ  ์ปค๋ฐ‹, ํ‘ธ์‰ฌ ํ•ฉ๋‹ˆ๋‹ค.
      1. ์ € ํŒŒ์ผ์˜ ์ •์ฒด: CPU, ๋ฉ”๋ชจ๋ฆฌ, ์—ด์–ด๋‘˜ ํฌํŠธ ๋“ฑ ์„œ๋ฒ„๋ฅผ ์–ด๋–ป๊ฒŒ ๊ตฌ๋™ํ• ์ง€ ๋ช…์‹œํ•ด ๋‘” 'ECS ์„œ๋ฒ„ ์‹คํ–‰ ์„ค๊ณ„๋„'์ž…๋‹ˆ๋‹ค.
      2. AWS์— ์žˆ๋Š”๋ฐ ๊ตณ์ด GitHub์— ๋„ฃ๋Š” ์ด์œ : ๋ฐฐํฌ์˜ ์ฃผ๋„๊ถŒ์ด AWS์—์„œ GitHub๋กœ ๋„˜์–ด์™”๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ž๋™ํ™” ํˆด์ธ GitHub Actions๊ฐ€ ์›๊ฒฉ์œผ๋กœ AWS ์„œ๋ฒ„๋ฅผ ์กฐ์ข…ํ•˜์—ฌ ์ƒˆ ๋ฒ„์ „์„ ๋„์šฐ๋ ค๋ฉด, ๊ทธ '์‹คํ–‰ ๊ธฐ์ค€ ํ…œํ”Œ๋ฆฟ'์„ ์ž์‹ ์˜ ์ €์žฅ์†Œ ๋‚ด๋ถ€์— ์ง์ ‘ ๋“ค๊ณ  ์žˆ์–ด์•ผ ๋ช…๋ น์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • "์ฆ‰, AWS์— ์žˆ๋Š” ๊ธฐ์กด ์„ค์ •์„ ๊ทธ๋Œ€๋กœ ๋– ์™€์„œ, GitHub๊ฐ€ ๋ฐฐํฌํ•  ๋•Œ๋งˆ๋‹ค '์ด ์„ค๊ณ„๋„(JSON) ์„ค์ • ๊ทธ๋Œ€๋กœ ๋ฐฉ๊ธˆ ๋งŒ๋“  ์ƒˆ ์ด๋ฏธ์ง€๋ฅผ ์‹คํ–‰ํ•ด ์ค˜!'

  • ๊นƒํ—ˆ๋ธŒ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ Settngs > Secrity > Secrets and variables > Actions์˜ ํŽ˜์ด์ง€์—์„œ Secrets ํƒญ์—์„œ ์ƒˆ๋กœ์šด ์‹œํฌ๋ฆฟ์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    • AWS IAM ์—์„œ ์ƒ์„ฑํ•œ ์—‘์„ธ์Šค ํ‚ค์˜ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋ฉฐ 2๊ฐœ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY

 

  • ์ด์ œ Actions ํƒญ์˜ workflow ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  Gitlab์—์„œ์™€ ๊ฐ™์ด ์›น์—์„œ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ์˜ DNS ์ด๋ฆ„์œผ๋กœ ์ ‘์†ํ•˜์—ฌ ๋ฐฐํฌ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿš€ [CI/CD] GitHub Actions + Docker + AWS (ECR/ECS) ์ž๋™ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•

 

๐ŸŒŠ 1. ์ „์ฒด ์ž๋™ ๋ฐฐํฌ ์›Œํฌํ”Œ๋กœ์šฐ (Workflow Flow)

  • GitLab์˜ Pipeline์— ํ•ด๋‹นํ•˜๋Š” GitHub์˜ ์›Œํฌํ”Œ๋กœ์šฐ ์‹คํ–‰(Workflow Run) ์ˆœ์„œ์ž…๋‹ˆ๋‹ค. git push ํ•œ ๋ฒˆ์œผ๋กœ ์•„๋ž˜ ๊ณผ์ •์ด ์ž๋™์œผ๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.
  1. ๐Ÿ’ป GitHub Push: ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ main ๋˜๋Š” master ๋ธŒ๋žœ์น˜์— ํ‘ธ์‹œ
  2. ๐Ÿ› ๏ธ Build Job: GitHub Runner๊ฐ€ ์ž„์‹œ ํ™˜๊ฒฝ(JDK 17)์„ ๋„์šฐ๊ณ  ./gradlew clean build ์‹คํ–‰
  3. ๐Ÿ“ฆ Artifact ์ž„์‹œ ์ €์žฅ: ๋นŒ๋“œ๋œ .jar ํŒŒ์ผ์„ ๋‹ค์Œ ๋ฐฐํฌ ๋‹จ๊ณ„๋กœ ๋„˜๊ธฐ๊ธฐ ์œ„ํ•ด ๋ณด๊ด€ (upload-artifact)
  4. ๐Ÿ” AWS ์ธ์ฆ: GitHub Secrets์— ์ˆจ๊ฒจ๋‘” ์ž๊ฒฉ ์ฆ๋ช…(ACCESS_KEY)์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋กœ๊ทธ์ธ
  5. ๐Ÿณ Docker Build & Push: Dockerfile์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค๊ณ  AWS ECR(์ €์žฅ์†Œ)์— ์—…๋กœ๋“œ
  6. ๐Ÿ“„ Task Definition ๊ฐฑ์‹ : AWS ECS ์‹คํ–‰ ์„ค๊ณ„๋„(JSON)์˜ ์ด๋ฏธ์ง€ ์ฃผ์†Œ๋ฅผ ๋ฐฉ๊ธˆ ๋งŒ๋“  ์ƒˆ ์ด๋ฏธ์ง€๋กœ ๊ต์ฒด
  7. ๐Ÿš€ ECS Deploy: ECS ์„œ๋น„์Šค๊ฐ€ ์ƒˆ๋กœ์šด ์„ค์ •์œผ๋กœ ์„œ๋ฒ„(์ปจํ…Œ์ด๋„ˆ)๋ฅผ ์ž๋™ ์žฌ๋ฐฐํฌ

๐Ÿ’ก 2. ํŒŒ์ดํ”„๋ผ์ธ ํ•„์ˆ˜ ํ•ต์‹ฌ ๊ฐœ๋… ์‚ฌ์ „

  • [GitHub & ๋นŒ๋“œ ๊ด€๋ จ]
    • .github/workflows/aws.yml: GitHub Actions์˜ ์ž๋™ํ™” ์Šคํฌ๋ฆฝํŠธ. ์–ธ์ œ, ์–ด๋–ค ์ˆœ์„œ๋กœ ๋™์ž‘ํ• ์ง€ ์ •์˜ํ•˜๋Š” ํ•ต์‹ฌ ์„ค์ • ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.
    • Artifact (์•„ํ‹ฐํŒฉํŠธ): ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ž‘์—…(Job) ๊ฐ„์— ์ฃผ๊ณ ๋ฐ›๋Š” ๊ฒฐ๊ณผ๋ฌผ. ์—ฌ๊ธฐ์„œ๋Š” ์•ž์„œ ๋นŒ๋“œํ•œ .jar ํŒŒ์ผ์„ ๋’ค์˜ ๋„์ปค ๋ฐฐํฌ ๋‹จ๊ณ„๋กœ ๋„˜๊ฒจ์ฃผ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
    • GitHub Secrets: AWS ์ ‘์† ํ‚ค(ACCESS_KEY_ID ๋“ฑ)์ฒ˜๋Ÿผ ์ฝ”๋“œ์— ์ง์ ‘ ๋…ธ์ถœ๋˜๋ฉด ์•ˆ ๋˜๋Š” ๋ฏผ๊ฐํ•œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด๊ด€ํ•˜๋Š” ๊ธˆ๊ณ ์ž…๋‹ˆ๋‹ค.
  • [Docker ํ™˜๊ฒฝ ๊ด€๋ จ]
    • Dockerfile: Spring Boot ์•ฑ์„ ์‹คํ–‰ํ•  "๋ฆฌ๋ˆ…์Šค ์‹คํ–‰ ํ™˜๊ฒฝ ๋ฐ•์Šค(์ปจํ…Œ์ด๋„ˆ)"๋ฅผ ๋งŒ๋“œ๋Š” ์กฐ๋ฆฌ ์„ค๋ช…์„œ์ž…๋‹ˆ๋‹ค.
    • eclipse-temurin:17-jdk: Docker Hub์—์„œ ์ œ๊ณตํ•˜๋Š” Java 17 ์‹คํ–‰์šฉ ๋ฆฌ๋ˆ…์Šค ๊ธฐ๋ฐ˜ ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€. ์‹ค์ œ ECS์—์„œ Spring Boot๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ๋ผˆ๋Œ€๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • [AWS ์ธํ”„๋ผ ๊ด€๋ จ]
    • ECR (Elastic Container Registry): ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  Docker ์ด๋ฏธ์ง€๋ฅผ ์ฐจ๊ณก์ฐจ๊ณก ๋ณด๊ด€ํ•˜๋Š” AWS ์ „์šฉ ์ €์žฅ์†Œ์ž…๋‹ˆ๋‹ค.
    • ECS (Elastic Container Service): ECR์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๊บผ๋‚ด์™€ ์‹ค์ œ ์ปจํ…Œ์ด๋„ˆ ์„œ๋ฒ„๋กœ ์‹คํ–‰ํ•˜๊ณ  ๊ด€๋ฆฌํ•ด ์ฃผ๋Š” ์ง€ํœ˜์ž์ž…๋‹ˆ๋‹ค.
    • Task Definition (ํƒœ์Šคํฌ ์ •์˜): ECS๊ฐ€ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ "์–ด๋–ค ์ด๋ฏธ์ง€, ๋ช‡ ๋ฒˆ ํฌํŠธ, ์–ผ๋งŒํผ์˜ ๋ฉ”๋ชจ๋ฆฌ"๋กœ ์‹คํ–‰ํ• ์ง€ ์ ์–ด๋‘” ์„œ๋ฒ„ ์‹คํ–‰ ์„ค๊ณ„๋„(JSON)์ž…๋‹ˆ๋‹ค.
    • Load Balancer DNS: ์ปจํ…Œ์ด๋„ˆ๋Š” ์žฌ์‹œ์ž‘๋  ๋•Œ๋งˆ๋‹ค ๋‚ด๋ถ€ IP๊ฐ€ ๊ณ„์† ๋ฐ”๋€๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์ž๊ฐ€ IP ๋Œ€์‹  ์–ธ์ œ๋‚˜ ๋ณ€ํ•จ์—†์ด ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณตํ•ด ์ฃผ๋Š” ๊ณ ์ • ์ ‘์† ์ฃผ์†Œ(๋Œ€๋ฌธ)์ž…๋‹ˆ๋‹ค.

๐Ÿ†š 3. ํ•œ๋ˆˆ์— ๋ณด๋Š” ๋น„๊ต (GitLab CI/CD vs GitHub Actions)

  • ๋‘ ํ”Œ๋žซํผ ๋ชจ๋‘ ํฐ ํ๋ฆ„(Push ํŠธ๋ฆฌ๊ฑฐ → ๋นŒ๋“œ → Docker ์ƒ์„ฑ → ECR ์—…๋กœ๋“œ → ECS ๋ฐฐํฌ)์€ ์™„๋ฒฝํ•˜๊ฒŒ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ํ”Œ๋žซํผ๊ณผ ๋ฌธ๋ฒ•์˜ ์ฐจ์ด๋งŒ ์กด์žฌํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.
๊ตฌ๋ถ„ GitLab CI/CD GitHub Actions
์„ค์ • ํŒŒ์ผ ์œ„์น˜ ์ตœ์ƒ๋‹จ .gitlab-ci.yml .github/workflows/aws.yml
์ž‘์—… ๋‹จ์œ„ ๋ช…์นญ Pipeline (ํŒŒ์ดํ”„๋ผ์ธ) Workflow Run (์›Œํฌํ”Œ๋กœ์šฐ ๋Ÿฐ)
์ž‘์—… ํ๋ฆ„ ์ •์˜ stages ์™€ jobs๋กœ ๊ตฌ์„ฑ jobs ์™€ steps๋กœ ๊ตฌ์„ฑ
๋น„๋ฐ€ ๋ณ€์ˆ˜ ๊ด€๋ฆฌ Settings > CI/CD > Variables Settings > Secrets and variables
๐Ÿ“ ์š”์•ฝํ•˜์ž๋ฉด: GitLab์—์„œ๋Š” ํ•˜๋‚˜์˜ ํŒŒ์ดํ”„๋ผ์ธ ์•ˆ์—์„œ ๋‹จ๊ณ„๋ฅผ ๋‚˜๋ˆ„์–ด ์‹คํ–‰ํ–ˆ๋‹ค๋ฉด, GitHub Actions์—์„œ๋Š” .yml ํŒŒ์ผ์„ ์ฝ์–ด ์ •ํ•ด์ง„ ์ž‘์—…(Job)๊ณผ ์„ธ๋ถ€ ๋‹จ๊ณ„(Step)๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์–ด๋–ค ๋„๊ตฌ๋ฅผ ์“ฐ๋“  CI/CD์˜ ๋ณธ์งˆ์ ์ธ ์•„ํ‚คํ…์ฒ˜๋Š” ๋™์ผํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค!

 

๐Ÿšจ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… (Troubleshooting) ํ•ต์‹ฌ ์ •๋ฆฌ

โŒ GitHub Actions ํŒŒ์ดํ”„๋ผ์ธ ์•„์˜ˆ ์‹คํ–‰ ์•ˆ ๋จ (ํŠธ๋ฆฌ๊ฑฐ ๋ธŒ๋žœ์น˜ ๋ถˆ์ผ์น˜)

  • ์ฆ์ƒ: ์ฝ”๋“œ๋ฅผ ์ปค๋ฐ‹ํ•˜๊ณ  ํ‘ธ์‹œ(git push)ํ–ˆ๋Š”๋ฐ๋„ GitHub Actions ํƒญ์— ์•„๋ฌด๋Ÿฐ ์ž‘์—…์ด ๋œจ์ง€ ์•Š๊ณ  ์กฐ์šฉํ•จ.
  • ์›์ธ: GitHub Actions๋Š” ์„ค์ • ํŒŒ์ผ(.yml)์˜ ์‹คํ–‰ ์กฐ๊ฑด์ด ๋งž์•„์•ผ๋งŒ ๋™์ž‘ํ•จ. aws.yml ํŒŒ์ผ์˜ ์‹คํ–‰ ์กฐ๊ฑด(on: push)์€ main ๋ธŒ๋žœ์น˜๋กœ ์ ํ˜€ ์žˆ์—ˆ์œผ๋‚˜, ํ˜„์žฌ ๊นƒํ—ˆ๋ธŒ์˜ ์‹ค์ œ ๋ธŒ๋žœ์น˜๋Š” master์˜€๊ธฐ ๋•Œ๋ฌธ์— GitHub๊ฐ€ ์‹คํ–‰ ์กฐ๊ฑด์ด ์•„๋‹ˆ๋ผ๊ณ  ํŒ๋‹จํ•˜์—ฌ ์•„์˜ˆ ์ž‘๋™์„ ์Šคํ‚ตํ•œ ๊ฒƒ.
  • ํ•ด๊ฒฐ: aws.yml ์•ˆ์˜ ๋ธŒ๋žœ์น˜ ์กฐ๊ฑด์„ branches: [ "master" ]๋กœ ์ˆ˜์ •ํ•˜์—ฌ ์ •์ƒ ์ž‘๋™ ํ™•์ธ.
on:
  push:
    branches: [ "master" ]

โŒ ํŒŒ์ดํ”„๋ผ์ธ ์ค‘๊ฐ„ ๋ฉˆ์ถค (Artifact Action ๊ตฌ๋ฒ„์ „ ๋งŒ๋ฃŒ)

  • ์—๋Ÿฌ ๋ฉ”์‹œ์ง€:
    deprecated version of `actions/upload-artifact: v3`
    
  • ์›์ธ: ๋นŒ๋“œ๋œ ํŒŒ์ผ(.jar ๋“ฑ)์„ ์ž„์‹œ๋กœ ์ €์žฅํ•ด๋‘๋Š” GitHub์˜ ๊ธฐ๋ณธ ์•ก์…˜(upload-artifact) ๋ฒ„์ „์ด ๊ตฌ๋ฒ„์ „(v3)์ด์—ˆ๋Š”๋ฐ, GitHub ์ธก์—์„œ ํ•ด๋‹น ๋ฒ„์ „์˜ ์ง€์›์„ ๊ฐ•์ œ๋กœ ์ข…๋ฃŒ(Deprecated)ํ•ด๋ฒ„๋ ค์„œ ๋ฐœ์ƒํ•œ ์‹œ์Šคํ…œ์  ์˜ค๋ฅ˜.
  • ํ•ด๊ฒฐ: aws.yml ์ฝ”๋“œ ๋‚ด๋ถ€์˜ upload-artifact@v3์™€ download-artifact@v3๋ฅผ ๋ชจ๋‘ ์ตœ์‹  ๋ฒ„์ „์ธ @v4๋กœ ๋ณ€๊ฒฝ.

โŒ ECS ์ตœ์ข… ๋ฐฐํฌ ์‹คํŒจ (Task Definition JSON ํ˜ธํ™˜์„ฑ ์˜ค๋ฅ˜)

  • ์—๋Ÿฌ ๋ฉ”์‹œ์ง€:
    Unexpected key 'enableFaultInjection'
    
  • ์›์ธ: AWS ์ฝ˜์†”์ด ์ตœ๊ทผ ์—…๋ฐ์ดํŠธ๋˜๋ฉด์„œ ECS ์„ค์ • JSON ํŒŒ์ผ์— ์ตœ์‹  ์˜ต์…˜(enableFaultInjection: ์ธ์œ„์  ์žฅ์•  ํ…Œ์ŠคํŠธ์šฉ)์„ ์ž๋™์œผ๋กœ ์ถ”๊ฐ€ํ•ด์„œ ๋ฐœ๊ธ‰ํ•ด ์คŒ. ํ•˜์ง€๋งŒ GitHub Action์˜ ๋ฐฐํฌ ๊ธฐ๋Šฅ์€ ์•„์ง ์ด ์ตœ์‹  ํ‚ค์›Œ๋“œ๋ฅผ ์ธ์‹ํ•˜์ง€ ๋ชปํ•ด์„œ ๋ชจ๋ฅด๋Š” ์„ค์ •์ด ๋“ค์–ด์™”๋‹ค๋ฉฐ ์—๋Ÿฌ๋ฅผ ๋ฑ‰์–ด๋‚ธ ์ƒํ™ฉ.
  • ํ•ด๊ฒฐ: ํ•ด๋‹น ๊ธฐ๋Šฅ์€ ๋‹จ์ˆœ ๋ฐฐํฌ ํ๋ฆ„์— ์ „ํ˜€ ํ•„์š” ์—†๋Š” ๊ณ ๊ธ‰ ์˜ต์…˜์ด๋ฏ€๋กœ, ํ”„๋กœ์ ํŠธ ๋‚ด์˜ project-01-task.json ํŒŒ์ผ์—์„œ ํ•ด๋‹น ์ค„("enableFaultInjection": false,)์„ ์ฐพ์•„ ์‚ญ์ œํ•œ ํ›„ ๋‹ค์‹œ ํ‘ธ์‹œํ•˜์—ฌ ์ตœ์ข… ๋ฐฐํฌ ์„ฑ๊ณต!