본문 바로가기
IT 트렌드/AWS & 클라우드 쉬운 활용법

인플레이스 배포 지쳤나요? CodePipeline Blue Green으로 AWS 배포 자동화 및 Spring Boot EC2 무중단 배포! 😃

by KBerry 2025. 8. 5.

목차

    여러분은 배포할 때마다 심장이 쫄깃해지는 경험을 하고 있나요? 밤늦은 시간 트래픽이 적을 때를 골라 서비스를 재시작하고, 배포 중 서비스가 다운될까 노심초사했던 기억이 있을 것입니다. Spring Boot 애플리케이션을 EC2에 올려 인플레이스 방식으로 업데이트할 때는 이러한 배포 지옥이 반복되곤 합니다. 실수 한 번이면 전체 서비스 장애로 이어질까 봐 배포 내내 가슴 졸이게 되죠.

    하지만 걱정 마세요. 이 글에서는 기존 인플레이스 배포를 Blue/Green 배포로 전환하여 무중단 배포를 구현함으로써 그런 배포 스트레스를 날려버리는 방법을 소개합니다. GitHub 코드 푸시부터 AWS CodePipeline Blue Green 배포 파이프라인을 거쳐, AWS 배포 자동화Spring Boot EC2 배포를 무중단으로 수행하는 과정을 하나씩 따라가 보겠습니다. 이제 더 이상 배포 때문에 주말 밤을 반납하지 않아도 됩니다!

     

    ※ 이전글

    2025.08.01 - [IT 트렌드/AWS & 클라우드 쉬운 활용법] - AWS Elastic Beanstalk를 활용한 Spring Boot 자동 배포: CodePipeline 연동 가이드

     

    AWS Elastic Beanstalk를 활용한 Spring Boot 자동 배포: CodePipeline 연동 가이드

    목차 AWS Elastic Beanstalk, Spring Boot 자동 배포, CodePipeline 연동 – 이 세 가지 키워드로 대표되는 이번 가이드에서는 Spring Boot 애플리케이션을 AWS 클라우드에 자동 배포하는 방법을 단계별로 알아봅

    kberry.tistory.com

    2025.07.31 - [IT 트렌드/AWS & 클라우드 쉬운 활용법] - AWS CodePipeline에서 GitHub 연동 – 실무 후기 및 CI/CD 구축 가이드

     

    AWS CodePipeline에서 GitHub 연동 – 실무 후기 및 CI/CD 구축 가이드

    목차GitHub에 있는 코드를 AWS CodePipeline으로 빌드하고 배포하는 CI/CD 파이프라인을 구축해보았습니다. 이번 포스트에서는 “AWS CodePipeline에서 GitHub 연동”하는 방법을 실무 관점에서 공유하고, 자

    kberry.tistory.com

     

    기존 In-place 방식의 한계와 문제점

    먼저 현재 많이 사용하는 인플레이스(In-place) 배포 방식의 한계를 짚어보겠습니다. 인플레이스 배포란 실행 중인 서버에 직접 새 어플리케이션 버전을 덮어씌워 업데이트하는 방법입니다. 배포 시 서비스 중단을 최소화하려고 Auto Scaling 그룹의 인스턴스를 한 대씩 순차 배포하거나, 또는 한꺼번에 배포(All-at-once) 하기도 합니다. 하지만 규모와 상관없이, 이 방식에는 몇 가지 근본적인 문제가 있습니다:

    • 다운타임 발생 위험: 새 버전을 배포하는 동안 기존 애플리케이션 프로세스를 중지해야 한다면 그 시간 동안 서비스가 중단될 수밖에 없습니다. 순차 배포로 일부 인스턴스를 유지한다 해도 배포 진행 중에는 가용 인스턴스 수가 줄어 성능 저하나 오류 가능성이 있습니다. 결국 배포 때 짧은 다운타임은 감수해야 한다는 전제가 깔려 있습니다.
    • 롤백 어려움: 업데이트 후 문제가 발견되면 기존 버전을 다시 배포해야 합니다. 인플레이스 환경에서는 이전 버전이 이미 덮어씌워져 사라졌으므로, 롤백하려면 코드를 재배포해야 하고 시간도 더 소요됩니다. 서비스 장애 상황에서는 이 재배포 과정조차 굉장한 압박으로 다가옵니다.
    • 실환경 테스트 곤란: 새로운 버전을 배포하기 전에는 실제 프로덕션과 동일한 환경에서 테스트하기 어렵습니다. 결국 배포하자마자 모든 사용자가 새 버전을 쓰게 되므로, 사소한 버그도 곧바로 서비스 이슈로 이어질 위험이 있습니다. 배포 전 충분한 검증이 어려워 배포가 곧 긴장으로 직결됩니다.
    • 환경 드리프트 및 누적 문제: 같은 EC2 서버에 수차례 배포를 거듭하다 보면, 오래된 파일이나 이전 설정 등이 누적되어 환경 불일치(drift)가 생길 수 있습니다. 예를 들어 임시 파일이나 캐시, 과거 버전 라이브러리 등이 남아서 새 버전 동작에 영향을 줄 수 있습니다. 인스턴스를 새로 교체하지 않고 장기간 활용하는 만큼 이러한 히스토리 문제가 내재합니다.
    • 운영 부담 가중: 배포 과정에서 개발자와 운영자는 실시간으로 서버 상태를 주시하며 긴장할 수밖에 없습니다. 장애에 대비해 심야 시간대를 택해 배포하느라 업무 피로도도 높습니다. (많은 분들이 금요일 저녁 배포를 꺼리는 이유이기도 합니다! 😅) 작은 실수도 치명적일 수 있어 사람에 대한 의존도와 스트레스가 큽니다.

    이처럼 인플레이스 배포는 간단하지만 잠재적 위험을 늘 안고 있습니다. 이제 이러한 한계를 어떻게 극복할지, Blue/Green 배포 방식을 통해 살펴보겠습니다.

    Blue/Green 배포 방식의 개념과 장점

    Figure: Blue/Green 배포 개념도. 배포에 Blue(현재 운영) 환경과 Green(새 배포) 두 개의 환경을 사용하여, 새 버전을 기존 서비스와 동시에 운영하는 전략입니다. 초기에는 모든 트래픽이 Blue 환경(예: 기존 버전 EC2 인스턴스들)으로 향합니다. 새로운 버전은 분리된 Green 환경(동일 구성의 새로운 EC2 그룹)에 배포되어 충분히 테스트를 거친 후, 최종 검증이 되면 로드 밸런서(ALB)의 트래픽을 Blue에서 Green으로 전환합니다. 이 과정에서 사용자에게는 서비스 중단이 발생하지 않아 무중단 배포가 가능해집니다.

    Blue/Green 배포의 주요 장점은 다음과 같습니다:

    • 무중단 배포: 새 버전을 Green 환경에 미리 배포하고 테스트한 뒤, 사용자 트래픽을 Green으로 라우팅 하기만 하면 배포가 완료됩니다. 즉 서비스 전환 시 다운타임이 발생하지 않으며, 오직 사용자 트래픽의 방향만 바뀌는 셈입니다.
    • 쉬운 롤백: 배포 후 문제가 생기면 다시 트래픽을 Blue 환경으로 돌리기만 하면 됩니다. 새 버전을 제거하거나 재빌드할 필요 없이, 로드 밸런서의 라우팅만 재설정하면 빠르게 이전 안정된 버전으로 복귀할 수 있습니다. (Blue 인스턴스들을 배포 후 바로 지우지 않고 일정 기간 유지하면 더욱 안전하게 롤백을 고려할 수 있습니다.)
    • 충분한 검증 가능: Green 환경에서 실제 운영과 동일한 조건으로 새 버전을 사전에 검증할 수 있습니다. 필요하면 소수의 내부 사용자나 QA 트래픽만 Green에 보내서 시험 운영도 가능합니다. Blue 환경은 영향을 받지 않으므로 안전한 테스트를 거쳐 자신 있게 전환할 수 있어 품질 향상에 도움이 됩니다.
    • 환경 일관성과 최신화: 배포마다 새로운 EC2 인스턴스를 신규 프로비저닝하기 때문에, 오래된 설정이나 누적된 쓰레기 없이 깨끗한 환경(Immutable Infrastructure)에서 앱이 실행됩니다. 이는 환경 구성의 드리프트를 피하고 일관된 배포 상태를 유지하게 해 줍니다.
    • 배포 중 용량 유지: Blue와 동일한 규모의 Green 인스턴스가 추가로 띄워지므로, 배포 중에도 전체 서비스 용량이 유지됩니다. 사용자는 배포 중에도 성능 저하를 느끼지 못하고, 오히려 일시적으로 이중 리소스로 안정성이 높아지는 효과도 얻을 수 있습니다. (물론 그만큼 잠깐의 추가 인프라 비용은 들지만, 안정성 확보의 대가로 볼 수 있습니다.)

    이처럼 Blue/Green은 한 번 설정해 두면 서비스 가용성을 극대화할 수 있는 배포 전략입니다. 초기 구축은 다소 복잡해 보일 수 있지만, AWS의 도구들을 활용하면 이를 자동화하여 손쉽게 적용할 수 있습니다. 이제 실제로 AWS CodePipelineCodeDeploy를 이용해 인플레이스 환경을 Blue/Green으로 전환하는 실무 시나리오를 알아보겠습니다.

    실무 구축 사례 소개 (GitHub → CodePipeline → CodeDeploy → ALB → ASG)

    Blue/Green의 개념을 알았다면, 이를 CI/CD 파이프라인에 접목해 보는 일이 남았습니다. 여기서는 Spring Boot 애플리케이션을 예시로, GitHub에 코드를 푸시하면 AWS CodePipeline이 빌드 및 배포를 자동 수행하고, CodeDeploy가 EC2에 Blue/Green 배포를 진행하여 Application Load Balancer(ALB)를 통해 트래픽을 새로운 버전으로 자동 전환하는 구조를 살펴보겠습니다. 전체 흐름을 단계별로 정리하면 다음과 같습니다:

    1. 소스 (GitHub 연동): 먼저 CodePipeline의 소스(Stage 1)를 GitHub 리포지토리에 연동합니다. 예를 들어 main 브랜치에 새로운 커밋이 푸시되면 CodePipeline이 실행되도록 트리거를 설정합니다. CodePipeline은 해당 커밋의 소스 코드를 자동으로 가져와 다음 단계에 넘깁니다. (AWS CodePipeline에서 GitHub 외에 CodeCommit 등의 소스도 사용할 수 있지만 여기선 GitHub를 사용합니다.)
    2. 빌드 (CodeBuild): CodePipeline의 빌드(Stage 2) 단계에서는 AWS CodeBuild가 동작하여 애플리케이션을 빌드합니다. 예를 들어 Maven을 사용해 Spring Boot 프로젝트를 컴파일 및 패키징하고, 단위 테스트도 수행합니다. 빌드가 완료되면 산출물로써 jar 파일과 배포에 필요한 스크립트, 설정 파일(appspec.yml) 등을 묶어 S3에 아티팩트 패키지(zip)로 업로드합니다. (이를 위해 CodeBuild에 사전에 buildspec.yml이 작성되어 있어야 합니다.) 빌드 단계가 끝나면 S3에 배포준비된 패키지가 생성되고, 다음 배포 단계에 이 경로가 전달됩니다.
    3. 배포 (CodeDeploy Blue/Green): CodePipeline의 배포(Stage 3) 단계에서는 AWS CodeDeploy를 사용하여 EC2에 새 버전을 배포합니다. 여기서 배포 방식으로 Blue/Green을 선택함으로써, CodeDeploy는 기존 Auto Scaling Group(ASG) 환경을 복사하여 새 EC2 인스턴스들을 생성하고 거기에 새 코드를 설치합니다.
      • Blue 환경: 현재 운영 중인 EC2 인스턴스 그룹을 의미합니다. CodeDeploy 설정에서 Blue 대상 그룹(예: 기존 ASG 또는 특정 태그의 인스턴스들)이 지정되어 있습니다. 이 예시에서는 Blue가 Spring Boot 1.x 버전을 돌리고 있는 기존 EC2 ASG입니다.
      • Green 환경: CodeDeploy가 새로 띄운 EC2 인스턴스들입니다. CodeDeploy는 Blue ASG를 자동으로 복제하여 동일한 스펙의 Green ASG를 만들고, 필요한 수의 EC2 인스턴스를 기동 합니다. 이렇게 생성된 Green 인스턴스들은 미리 설치된 CodeDeploy 에이전트를 통해 S3에 업로드된 새 애플리케이션 패키지를 내려받고, 배포 스크립트(appspec.yml의 훅)에 따라 새로운 Spring Boot 애플리케이션 버전을 설치합니다.
      • 로드 밸런서(ALB) 연결: Blue/Green 배포를 위해 ALB와 Target Group을 이용합니다. Deployment Group 설정 시 이미 ALB의 리스너와 두 개의 Target Group(Blue용, Green용)이 연결돼 있습니다. 초기에는 ALB의 리스너가 Blue 대상 그룹을 가리키고 있어서 모든 트래픽이 Blue 인스턴스로 가고 있습니다. CodeDeploy는 Green 인스턴스들을 새로운 Target Group(Green)에 등록하고, Green 쪽 헬스 체크(Health Check)가 정상 통과할 때까지 대기합니다.
      • 트래픽 전환: Green 환경이 정상으로 판정되면, CodeDeploy는 ALB의 리스너를 Green 대상 그룹으로 변경하여 사용자 트래픽을 새 버전으로 전환합니다. (전환 방식은 All-at-once 등으로 설정 가능하며, 여기서는 즉시 100% 전환을 가정합니다.) 이 시점부터 새로운 Spring Boot 버전이 사용자 요청을 처리하게 되고, Blue 환경은 더 이상 트래픽을 받지 않습니다. CodeDeploy 콘솔에는 이 단계가 AllowTraffic 등의 이벤트로 표시됩니다.
      • Clean-up(원본 종료): 트래픽 전환 후에도 Blue 인스턴스들을 바로 종료하지 않고 대기 시간을 둘 수 있습니다. 예를 들어 Termination wait time을 1시간으로 설정했다면, 전환 후 1시간 동안 Blue 인스턴스들을 유지합니다. 문제가 없으면 그 후 자동으로 원본(Blue) 인스턴스들이 종료 및 ASG가 삭제되어 리소스 정리가 완료됩니다. (만약 문제 발생 시 이 대기 시간 동안 롤백할 수 있게 해주는 안전장치입니다.)
      이렇게 CodeDeploy가 배포부터 트래픽 스위칭까지 자동화해 주므로, 사람 개입 없이도 새로운 버전을 안전하게 배포할 수 있습니다. 요약하면 “기존 ASG (Blue)를 복제해서 새 ASG (Green)를 만들고 → 새 코드 배포 → 새 인스턴스 준비되면 ALB 연결 전환 → 일정 시간 후 기존 인스턴스 종료”의 흐름입니다. CodePipeline은 전체 과정을 모니터링하다가 CodeDeploy 단계가 성공으로 끝나면 파이프라인을 완료하고 배포 성공으로 표시합니다.

    [buildspec.yml] 추가사항

    ...
    artifacts:
    files:
    # 1. 빌드된 JAR 파일 (target 폴더  내의  모든 .jar 파일)
     - target/*.jar
    # 2. appspec.yml 파일 (루트  디렉토리에  위치)
     - appspec.yml
    # 3. scripts 폴더  내의  모든  스크립트  파일들
     - scripts/**/* # scripts 폴더와  그  안의  모든  파일을  포함
    discard-paths:
    no # 중요! 이  옵션을 'no'로  설정해야  합니다.
    # 'yes'로  설정하면 target/, appspec.yml, scripts/ 등의  디렉토리  구조가  무시되고 # 모든  파일이  아티팩트 zip의  루트에  평탄하게  배치됩니다.
    # CodeDeploy의 appspec.yml에서  경로를 'target/' 또는 'scripts/'로  참조하므로, # 이  구조가  유지되어야  합니다.

     Gitub repository 생성 및 Local VSCode 폴더 복사 후 .git 삭제 후 git itit으로 신규 repository remote  Gitub repository 생성 및 Local VSCode 폴더 복사 후 .git 삭제 후 git itit으로 신규 repository remote
    Gitub repository 생성 및 Local VSCode 폴더 복사 후 .git 삭제 후 git itit으로 신규 repository remote

    echo "# modern-spring-demo-codedeploy" >> README.md 
    git init 
    git add README.md 
    git commit -m "first commit" 
    git branch -M main 
    git remote add origin https://github.com/xxxxxxx/modern-spring-demo-codedeploy.git git push -u origin main

    [CI/CD] Pipeline Flow

    GitHub (소스 코드 저장소)
     └── CodePipeline (CI/CD 파이프라인)
         ├── Source 단계 – GitHub에서 코드 가져오기 (커밋 트리거)  
         ├── Build 단계 – CodeBuild로 Spring Boot 애플리케이션 빌드 및 테스트  
         └── Deploy 단계 – CodeDeploy로 Blue/Green 배포 시작  
             ├── Blue 환경: 현재 가동 중인 EC2 (Auto Scaling Group - 기존 버전)  
             ├── Green 환경: 신규로 복제된 EC2 (Auto Scaling Group - 새 버전)  
             ├── ALB: Blue 대상 그룹 → Green 대상 그룹으로 트래픽 스위칭  
             └── 배포 완료: 새 버전 서비스 개시, 일정 시간 후 Blue 인스턴스 종료

     

    그림 설명: GitHub 커밋 → CodePipeline 소스 수집 → 빌드 → CodeDeploy 배포. CodeDeploy는 Blue 환경을 복제하여 Green 환경 생성 및 배포 후, ALB의 트래픽을 Blue에서 Green으로 전환한다. 최종적으로 Green이 서비스하고 Blue는 종료된다.

     

    위 다이어그램과 같이 파이프라인이 구성되면, 개발자가 GitHub에 코드를 푸시하는 것만으로 배포 자동화가 이뤄집니다. CodePipeline이 소스부터 배포까지 엔드 투 엔드로 관리하고, Blue/Green 전략 덕분에 서비스 중단 없는 우아한 배포가 가능합니다. 이제 세부 구성 요소별로 설정해야 할 것들을 살펴보겠습니다.

    appspec.yml과 배포 스크립트 구성

    AWS CodeDeploy를 통해 EC2에 배포하려면, 애플리케이션 패키지에 appspec.yml 파일이 포함되어 있어야 합니다. appspec.yml은 CodeDeploy에게 "어떤 파일을 어디에 놓고, 어떤 스크립트를 어떤 순서(event)에 실행할지" 알려주는 배포 명세서입니다. 간단히 말해 EC2에서 배포 작업의 각 단계(예: 애플리케이션 중지, 파일 복사, 애플리케이션 시작 등)를 정의하는 스크립트들의 목차라고 볼 수 있습니다.

    예를 들어, Spring Boot Jar 배포를 위한 appspec.yml의 구조는 다음과 같을 수 있습니다:

    version: 0.0
    os: linux # 배포  대상 EC2 인스턴스의  운영체제 (Amazon Linux이므로 linux)
    files:
     - source: target/ # CodeBuild 아티팩트의  루트  디렉토리 (JAR 파일과  스크립트들이  이  안에 destination: /opt/codedeploy-app # EC2 인스턴스  내에서  애플리케이션이  배포될  경로
    permissions: # 배포된  파일들의  권한  설정
     - object: /opt/codedeploy-app # 대상  디렉토리
    pattern: "**" # 모든  파일  및  하위  디렉토리
    owner: ec2-user # 애플리케이션을  실행할  사용자 (Amazon Linux 기본  사용자)
    group: ec2-user
    type:
     - directory
     - file
    hooks: # CodeDeploy 라이프사이클  훅 (각  배포  단계별로  실행될  스크립트  정의)
    # BeforeInstall: 새로운  버전이  설치되기  전에  실행. 기존  파일  정리  등.
    BeforeInstall:
     - location: scripts/before_install.sh
    timeout: 300 # 스크립트  최대  실행  시간 (초)
    runas: root # 스크립트  실행  사용자 (루트  권한으로  실행)
    # AfterInstall: 새로운  버전이 EC2에  복사된  후  실행. 파일  권한  부여, 환경  설정  등. AfterInstall:
     - location: scripts/after_install.sh
    timeout: 300
    runas: root
    # ApplicationStart: 애플리케이션  서비스를  시작. Spring Boot JAR 실행  등. ApplicationStart:
     - location: scripts/application_start.sh
    timeout: 600 # 애플리케이션  시작에  시간이  걸릴  수  있으므로  넉넉하게  설정
    runas: root
    # ApplicationStop: 이전  버전의  애플리케이션  서비스를  중지. (Blue/Green 배포에서는  주로 ApplicationStop:
     - location: scripts/application_stop.sh
    timeout: 300
    runas: root
    # ValidateService: 애플리케이션이  성공적으로  시작되었는지  검증. 헬스  체크  엔드포인트  호 ValidateService:
     - location: scripts/validate_service.sh timeout: 300
    runas: root

     

    위의 예에서, files 섹션은 빌드 산출물이 배포될 경로를 지정합니다. 예를 들면, CodeBuild에서 패키징 한 Jar 파일과 스크립트들이 /home/ec2-user/app 폴더로 복사됩니다. 이어서 hooks 섹션에서는 각 배포 단계별 실행할 스크립트를 지정합니다:

    • ApplicationStop: 기존 애플리케이션을 중지하는 단계입니다. stop_app.sh에서는 현재 실행 중인 Spring Boot 프로세스를 찾아 종료하는 명령을 포함합니다 (예: pkill -f myapp.jar 또는 systemd 서비스로 구동 중이라면 service myapp stop 등을 수행). 인플레이스 배포의 경우 이 훅이 가장 먼저 실행되어야 하고, Blue/Green 배포의 경우 새 인스턴스에는 중지할 앱이 없으므로 이 스크립트가 아무 작업 없이 성공하도록 작성해 두면 됩니다.
    #!/bin/bash 
    # 실행 중인 Spring Boot 애플리케이션을 중지합니다. 
    PID_FILE="/var/run/codedeploy-app.pid" 
    echo "Stopping application..." 
    if [ -f "$PID_FILE" ]; then 
     PID=$(cat "$PID_FILE") 
     if ps -p $PID > /dev/null; then 
     kill -15 "$PID" # Graceful shutdown (SIGTERM) 
     # 프로세스가 종료될 때까지 대기
     for i in $(seq 1 10); do 
     if ! ps -p $PID > /dev/null; then 
     echo "Application (PID: $PID) stopped successfully." 
     rm "$PID_FILE" 
     exit 0 
     fi 
     sleep 1 
     done 
     echo "Application (PID: $PID) did not stop gracefully. Force killing..." 
     kill -9 "$PID" # 강제 종료 (SIGKILL) 
     rm "$PID_FILE" 
     else 
     echo "Application not running (PID file exists but process not found)." 
     rm "$PID_FILE" # PID 파일이 유효하지 않으면 삭제
     fi 
    else 
     echo "PID file not found. Application may not be running." 
    fi 
    echo "ApplicationStop script finished."
    • BeforeInstall: 새 버전을 설치하기 직전 단계로, 주로 오래된 파일 정리나 디렉터리 생성 등을 수행합니다. clear_before_install.sh 스크립트에서 이전 배포 아티팩트를 지우거나 (rm -rf /home/ec2-user/app/*), 필요한 폴더를 만드는 작업 등을 합니다.
    #!/bin/bash 
    echo "Removing old application files if any..." rm -rf /opt/codedeploy-app/* 
    echo "BeforeInstall script finished."
    • AfterInstall: 새 버전 파일이 지정된 경로에 복사된 후 실행됩니다. fix_permission.sh 등에서 파일 권한을 조정하거나, 환경 설정 파일을 덮어쓰는 등의 작업을 합니다. 예를 들어 Jar 파일에 실행 권한(chmod +x)을 주어 이후 단계에서 문제 없도록 할 수 있습니다.
    #!/bin/bash 
    # CodeBuild에서 target/*.jar로 아티팩트를 만들었으므로, 
    # /opt/codedeploy-app/target/ 디렉토리 안에 JAR 파일이 있을 것입니다. 
    # 정확한 JAR 파일 이름을 알 수 없으므로, 와일드카드를 사용하여 찾습니다. 
    echo "Granting execute permission to the JAR file..." 
    JAR_FILE=$(find /opt/codedeploy-app -name "*.jar" | head -n 1) # 첫 번째 JAR 파일 찾기 if [ -z "$JAR_FILE" ]; then 
     echo "ERROR: JAR file not found in /opt/codedeploy-app."  exit 1 
    fi 
    chmod +x "$JAR_FILE" 
    echo "AfterInstall script finished. JAR: $JAR_FILE"
    • ApplicationStart: 애플리케이션을 새로 시작하는 단계입니다. start_app.sh에서는 Spring Boot Jar를 백그라운드 실행하는 명령을 실행합니다. 예를 들어 nohup java -jar /home/ec2-user/app/myapp.jar --spring.profiles.active=prod > /home/ec2-user/app/nohup.out 2>&1 & 같이 nohup으로 앱을 백그라운드 구동시키거나, 시스템 데몬으로 등록된 경우 service start를 호출합니다. 이때 데이터베이스 접속 정보 등의 환경 변수 세팅도 이 스크립트에서 할 수 있습니다 (다음 섹션에서 자세히 다룹니다). CodeDeploy는 ApplicationStart 스크립트가 지정 시간(timeout) 내에 종료되지 않고 계속 백그라운드에서 실행되더라도 일단 명령을 트리거하고 다음 단계로 넘어갑니다.
    #!/bin/bash
    # Spring Boot 애플리케이션을  시작합니다.
    # RDS 연결  정보는 EC2 환경  변수를  통해  주입됩니다. (추후 Secrets Manager 연동  고려)
    # !!! 중요: 이  환경  변수들은 EC2 User Data 또는 CodeDeploy 배포  그룹  환경  변수,
    # 또는 AWS Systems Manager Parameter Store/Secrets Manager를  통해  설정되어야  합니다. # 여기서는  스크립트  테스트를  위해  예시  값으로  선언했지만, 프로덕션에서는  이  방식은  권장되지 # 배포  그룹의  환경  변수  설정  섹션에서  실제  값을  주입할  것입니다.
    # RDS 환경  변수 (기존 RDS를  바라봅니다.)
    # export RDS_HOSTNAME="your-rds-endpoint.ap-northeast-2.rds.amazonaws.com" # 실제 RDS # export RDS_DB_NAME="your_db_name" # 실제  데이터베이스  이름
    # export RDS_USERNAME="your_db_username" # 실제  사용자  이름
    # export RDS_PASSWORD="your_db_password" # 실제  비밀번호
    export RDS_HOSTNAME="postgre-17-5.cluster-1234.ap-northeast-2.rds.amazonaws.c export RDS_DB_NAME="blog_db" # 실제  데이터베이스  이름
    export RDS_USERNAME="blog_user" # 실제  사용자  이름
    export RDS_PASSWORD="1234" # 실제  비밀번호
    # Redis 환경  변수 (Redis는  아직  생성  전이므로, 일단  빈  값  또는  테스트  값으로  설정해둡니다. # 추후 Redis 생성  후  실제  값으로  변경해야  합니다.)
    export REDIS_HOST="" # ElastiCache Redis 엔드포인트 (생성  후  업데이트)
    export REDIS_PORT="6379"
    export REDIS_PASSWORD="" # Redis 비밀번호가  있다면 (생성  후  업데이트)
    JAR_FILE=$(find /opt/codedeploy-app/target -name "*.jar" | head -n 1) # target 폴더
    # 애플리케이션  로그  디렉토리  생성  및 JAR 실행
    echo "Starting Spring Boot application..."
    LOG_DIR="/var/log/codedeploy-app"
    mkdir -p "$LOG_DIR"
    chown ec2-user:ec2-user "$LOG_DIR" # ec2-user가  로그를  쓸  수  있도록  권한  부여
    # nohup을  사용하여  백그라운드에서  실행하고, PID를  파일에  저장
    nohup java -jar "$JAR_FILE" \
    --spring.datasource.url="jdbc:postgresql://${RDS_HOSTNAME}:5432/${RDS_DB_NAME}" \ --spring.datasource.username="${RDS_USERNAME}" \
    --spring.datasource.password="${RDS_PASSWORD}" \
    --spring.redis.host="${REDIS_HOST}" \
    --spring.redis.port="${REDIS_PORT}" \
    --spring.redis.password="${REDIS_PASSWORD}" \
    > "$LOG_DIR/application.log" 2>&1 &
    echo $! > /var/run/codedeploy-app.pid
    echo "Application started with PID $(cat /var/run/codedeploy-app.pid)." echo "Application log: $LOG_DIR/application.log"
    echo "ApplicationStart script finished."
    • ValidateService: 애플리케이션이 정상적으로 가동되었는지 검증하는 단계입니다. 예를 들어 health_check.sh 스크립트에서 애플리케이션의 헬스 체크 API (/actuator/health 등)를 curl로 호출해 200 OK를 받는지 확인할 수 있습니다. 해당 검증에 실패하면 CodeDeploy 배포를 실패로 간주하고 롤백하거나 중단합니다. (Blue/Green의 경우 ValidateService 대신 로드 밸런서 헬스 체크가 자동 검증해 주므로, 별도의 스크립트가 Optional일 수도 있습니다.)
    #!/bin/bash 
    # 애플리케이션 헬스 체크 엔드포인트를 호출하여 서비스가 정상적으로 시작되었는지 확인합니다. 
    APP_HEALTH_URL="http://localhost:8080/actuator/health" # Spring Boot Actuator 기본 헬스 체크 MAX_RETRIES=15 
    RETRY_INTERVAL=10 # seconds 
    echo "Validating service at $APP_HEALTH_URL..." 
    for i in $(seq 1 $MAX_RETRIES); do 
     STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$APP_HEALTH_URL") 
     if [ "$STATUS_CODE" -eq 200 ]; then 
     echo "Health check successful (Status: $STATUS_CODE)." 
     exit 0 
     else 
     echo "Health check failed (Status: $STATUS_CODE). Retrying in $RETRY_INTERVAL seconds..."  sleep $RETRY_INTERVAL 
     fi 
    done 
    echo "Service validation failed after $MAX_RETRIES retries. Deployment will fail." exit 1

     

    이런 스크립트들은 배포 패키지(.zip) 내의 scripts/ 폴더 등에 포함되어 있으며, CodeDeploy 에이전트가 각 이벤트 때마다 실행해줍니다. runas로 지정된 계정 권한으로 실행되므로, 필요한 권한(root 또는 ec2-user 등)에 맞게 설정합니다. 예를 들어 앱 구동은 ec2-user로 하지만 포트 바인드나 시스템 변경 작업은 root 권한이 필요할 수 있습니다.

    Tip: Blue/Green 배포에서는 새로운 인스턴스가 깨끗한 상태로 시작하기 때문에, ApplicationStop 단계의 스크립트는 "이전 프로세스가 있으면 종료" 정도로만 가볍게 작성해 두고, 이전에 프로세스가 없더라도 오류 없이 지나가도록 해야 합니다. 또한 ValidateService 단계는 ALB 헬스 체크로 대체되지만, 데이터베이스 마이그레이션 여부 등 추가 커스텀 검증이 필요하다면 활용할 수 있습니다.

    정리하면, appspec.yml과 스크립트들은 인스턴스 상에서 이루어지는 세부 배포 작업을 자동화하는 핵심 요소입니다. 이를 잘 구성해두면 배포 시 사람이 일일이 수작업할 필요 없이 일관된 배포 절차가 실행됩니다. 다음으로, 배포에 필요한 환경 변수나 시크릿 값을 안전하게 다루는 방법을 살펴보겠습니다.

    CodePipeline 구성 

    - Name : MyGitHubPipeline_CD
    - IAM Role : AWSCodePipelineServiceRole-ap-northeast-2-MyGitHubPipeline_CD
    - github Repository : xxxxxxx/modern-spring-demo-codedeploy
    - Default branch : main
    - Output artifact format :  Full clone
    - Create build project : Role name : codebuild-Build-Basic-Pipeline-CodeDeploy-Demo-service-role

    Code Pipeline 구성
    Code Pipeline 구성

     

    Code Pipline 화면Code Pipline 화면
    Code Pipline 화면

     

    사전에 Resource는 모두 구성했다고 가정

    1) Redis 구성 화면

    Redis 구성화면
    Redis 구성화면

     

    2) ALB 생성 및 Target Group Mapping

     

    - ALB 생성 및 TargetGroup 생성 (생략)
    = ALB Name : MyCodePipelineDemo-ALB = TG Name : MyCodePipelineDemo-TG = healthcheck URI : /actuator/health = Listen Port 80 -> Target Port 8080

    ALB 구성 화면
    ALB 구성 화면

     

    3) AutoScaling Group 생성 (Launch Template 포함)

    - AutoScaling Group 생성 및 Lunch Template 생성 생략
    - EC2 콘솔 > Auto Scaling > Auto Scaling 그룹 > Auto Scaling 그룹 생성
    - Launch Template Name : MyCodePipelineDemo-LT (lt-0452e92c8144ac946)
    - userdata (scripts/application_start.sh 가공)

    #!/bin/bash 
    # --- CodeDeploy Agent 설치 --- 
    APP_DIR="/opt/codedeploy-app" 
    LOG_DIR="/var/log/codedeploy-app" 
    # 디렉토리 생성 및 권한 설정 (AMI에 없다면) 
    mkdir -p "$APP_DIR" 
    mkdir -p "$LOG_DIR" 
    chown ec2-user:ec2-user "$APP_DIR" "$LOG_DIR" 
    echo "Attempting to start Spring Boot application using application_start.sh..." 
    # application_start.sh 스크립트 실행
    # nohup을 사용하여 백그라운드에서 실행하고, 모든 출력을 로그 파일로 리다이렉션
    # 중요한 것은, 이 스크립트 자체가 백그라운드로 실행되어 User Data 스크립트가 종료되도록 해야 합 니다. 
    # 그렇지 않으면 인스턴스 부팅이 완료되지 않을 수 있습니다. 
    nohup /bin/bash "$APP_DIR/scripts/application_start.sh" > "$LOG_DIR/user_data_start.log" 2>&1 & 
    echo "application_start.sh triggered in background." echo "User Data script finished."

    Redis, RDS 환경 변수 보안 처리 (Secrets Manager / Parameter Store)

    실제 운영 환경에서는 데이터베이스 접속 정보, Redis 호스트/비밀번호, API 키 등 민감한 설정 값을 애플리케이션이 필요로 합니다. 이러한 환경 변수를 다루는 방법도 배포 전략의 중요한 부분입니다. 잘못하면 깃허브 등의 소스 코드나 설정 파일에 암호가 노출되어 보안 사고로 이어질 수 있습니다. 또한 배포 시마다 수동으로 값을 입력하거나 바꾸는 것은 번거롭고 오류를 낳기 쉽죠.

    AWS에서는 이를 해결하기 위해 AWS Systems Manager Parameter StoreAWS Secrets Manager라는 서비스를 제공합니다. 두 서비스 모두 민감한 설정 값을 안전하게 저장하고 애플리케이션이나 스크립트가 이를 프로그램을 불러쓸 수 있도록 해줍니다. 특히 Parameter Store는 EC2, CodeDeploy와의 통합이 용이하여 자주 쓰입니다.

    🔑 왜 Parameter Store인가? 수동으로 설정값을 관리하면 다음과 같은 문제점이 있습니다:

    • 설정값을 소스 코드나 설정 파일에 평문으로 하드코딩하게 되는데, 이는 보안상 위험할 뿐 아니라 관리도 어렵습니다 (여러 서버에 일일이 수정 배포 필요).
    • 팀원이나 애플리케이션별로 접근 권한 제어를 세밀하게 하기 어렵습니다. 운영 DB 비밀번호 같은 것은 일부 관리자만 알아야 하는데, 코드에 섞여 있다면 범위 제어가 불가능해집니다.
    • 설정값을 사람 손으로 옮기고 배포할 때 오타나 실수가 발생할 수 있으며, 암호 노출 위험도 있습니다.

    Parameter Store는 이러한 문제를 해소해 줍니다. Parameter Store에 값을 저장해 두면, 코드나 배포 패키지에 비밀번호를 넣지 않아도 되고 IAM 권한으로 접근 통제가 가능합니다. 무엇보다 CodeDeploy 배포 과정에서 Parameter Store를 참조하면 사람이 개입하지 않아도 자동으로 안전한 설정 주입이 가능합니다. Secrets Manager도 유사한 역할을 하지만 주로 주기적 비밀 rotation이 필요한 DB 자격증명 등에 쓰고, 일반 구성값은 Parameter Store를 활용하는 패턴이 많습니다.

    ✅ 적용 방법: 예를 들어 RDS 데이터베이스의 비밀번호를 Parameter Store에 저장하고 배포 시 불러오는 과정을 생각해봅시다:

    1. Parameter Store에 값 저장: AWS Systems Manager > Parameter Store에서 새 Parameter를 생성합니다. 이름은 예를 들어 /myapp/prod/DB_PASSWORD 식으로 경로를 계층적으로 짓고, 유형은 SecureString으로 선택합니다. 값으로 실제 DB 비밀번호를 입력하고, AWS KMS 키로 암호화 저장합니다.
    2. EC2 IAM 역할 권한 부여: CodeDeploy로 배포될 EC2 인스턴스 (Blue/Green 모두)는 Parameter Store 값을 읽을 수 있는 IAM Role을 가져야 합니다. EC2 인스턴스 프로파일에 AmazonSSMReadOnlyAccess 정책이나 해당 Parameter에 대한 ssm:GetParameter 권한을 부여합니다. 이렇게 해야 EC2에서 AWS CLI로 Parameter Store 값을 조회할 수 있습니다.
    3. 배포 스크립트에서 조회: 예를 들어 애플리케이션 시작 스크립트(start_app.sh)에서 다음과 같이 Parameter Store 값을 읽어 환경 변수로 주입합니다:
    # start_app.sh 예시
    DB_PASS=$(aws ssm get-parameter --name "/myapp/prod/DB_PASSWORD" --with-decryption --query "Parameter.Value" --output text)
    export DB_PASS
    nohup java -jar /home/ec2-user/app/myapp.jar --spring.profiles.active=prod &

     

     

    1. 위 스크립트는 AWS CLI를 통해 Parameter Store의 값을 복호화하여 가져온 후, 쉘 환경변수 DB_PASS로 설정하고 앱을 실행합니다. 이렇게 하면 애플리케이션 코드에서 System.getenv("DB_PASS") 혹은 Spring 설정에서 ${DB_PASS}로 해당 값을 참조할 수 있습니다. Spring Boot의 경우 별도 설정 없이도 SPRING_DATASOURCE_PASSWORD 같은 표준 변수명을 사용하면 자동 연결되지만, 여기서는 예시로 간단히 환경 변수만 사용했습니다.
    2. 애플리케이션에서 사용: 애플리케이션은 평소처럼 데이터베이스 비밀번호를 환경 변수 또는 Spring Config로부터 읽도록 구현하면 됩니다. 예컨대 application-prod.properties에서 spring.datasource.password=${DB_PASS}로 지정해 두면, 위에서 주입한 환경변수를 사용하게 됩니다.
    3. Secrets Manager 대안: AWS Secrets Manager를 사용한다면 Parameter Store 대신 Secret에 값을 저장하고, 마찬가지로 AWS CLI의 aws secretsmanager get-secret-value를 사용해 값을 가져와 환경 변수로 세팅할 수 있습니다. Secrets Manager는 버전관리와 자동 로테이션 기능이 있지만, 호출 방식은 유사합니다. 다만 Secrets Manager 사용 시에는 해당 IAM 권한 (e.g., secretsmanager:GetSecretValue)이 필요합니다.

    위 방법을 통해 코드베이스에는 민감 정보가 일절 포함되지 않게 됩니다. 또한 운영 환경의 실 비밀번호가 노출되지 않은 채로도 배포 자동화를 구현할 수 있습니다. Parameter Store와 CodeDeploy의 연계는 AWS 블로그에서도 잘 설명하고 있는데, 이를 활용하면 보안과 배포 편의성 두 마리 토끼를 잡을 수 있습니다.

    참고: Parameter Store/Secrets Manager를 사용하면 설정 변경도 유연해집니다. 예를 들어 DB 비밀번호를 변경해야 할 때, Parameter Store의 값을 업데이트하고 새로운 배포를 수행하면 애플리케이션이 새로운 값으로 구동됩니다. 코드 수정 없이 설정 교체가 가능하므로 운영 관리성이 향상됩니다. 또한 IAM으로 접근을 통제하므로 특정 환경(개발/스테이징/프로덕션) 별로 다른 권한과 값을 사용할 수도 있습니다.

    마지막으로, 이렇게 배포한 후 정상적으로 애플리케이션이 잘 구동되었는지 확인하고, 지속적으로 모니터링하는 방법에 대해 알아보겠습니다.

    성공화면
    성공화면

     

    배포 결과 검증 및 모니터링 방법

    성공적인 배포를 위해서는 배포 후 결과 검증과 모니터링이 필수입니다. Blue/Green 배포는 무중단으로 진행되지만, 새 버전이 제대로 동작하는지 확인하고 이상 발생 시 재빠르게 대응할 수 있어야 하죠. 다음은 배포 완료 후 점검해야 할 요소들과 AWS에서 활용할 수 있는 모니터링 도구들입니다:

    • 배포 상태 확인: 우선 AWS CodePipeline 콘솔이나 CodeDeploy 콘솔에서 배포 결과 상태를 확인합니다. CodePipeline이 성공(green)으로 끝났다면 일단 기본 배포 프로세스는 완료된 것입니다. 혹시 실패(red) 상태라면 CodeDeploy 단계에서 오류가 난 것이므로, CodeDeploy 콘솔의 배포 이벤트 로그를 살펴봐야 합니다. 어떤 Lifecycle 이벤트(AppStop, BeforeInstall 등)에서 오류가 발생했는지 상세 로그를 확인할 수 있습니다. 스크립트 에러, 권한 문제 등이 흔한 원인이니 로그를 잘 검토하세요. 특히 Blue/Green의 경우 AllowTraffic 단계 이전에 오류가 나면 트래픽 전환이 수행되지 않으므로, 서비스 영향은 없지만 배포가 롤백되었다고 봐야 합니다.
    • 애플리케이션 기능 점검: 배포가 성공으로 표시되었다면, 실제 서비스가 정상 동작하는지 최종 확인이 필요합니다. Application Load Balancer의 DNS 주소나 도메인으로 접속하여 주요 페이지나 API를 호출해 봅니다. 예를 들어 애플리케이션에 /health 혹은 버전 정보를 출력하는 엔드포인트를 마련해두었다면, 해당 URL을 열어 새 버전이 응답하는지 확인합니다. Blue/Green 배포에서는 ALB 헬스 체크를 통과한 시점에 전환이 이뤄지므로 대개 문제 없지만, 혹시 모를 논리 오류나 기능 이상을 확인하는 차원입니다. 실제 예로 한 사용자는 배포 후 ALB의 DNS로 접속해 새 버전의 응답을 확인함으로써 정상 배포를 검증했습니다. 작은 테스트 시나리오를 사전에 정해 배포 후 수행하면 안심할 수 있습니다.
    • 모니터링 및 자동 롤백: 배포 직후뿐 아니라 일정 시간 동안 새로운 Green 환경의 상태를 모니터링해야 합니다. AWS CloudWatch Alarms을 활용하면 이를 자동화할 수 있습니다. 예를 들어 오류 로그 수치(CloudWatch Logs의 메트릭 필터)나 HTTP 5xx 비율, CPU 사용률 등의 지표에 대한 CloudWatch 경보를 생성해 두고, CodeDeploy Deployment Group에 해당 경보를 연계할 수 있습니다. 이렇게 하면 배포 후 일정 시간 내 그 알람이 발생할 경우 CodeDeploy가 자동으로 롤백을 수행하게 설정할 수 있습니다. Blue/Green의 롤백은 트래픽을 다시 Blue로 돌리고 Green 인스턴스를 종료하는 것으로 간단히 이루어집니다. 별도의 재배포 없이도 자동 복구되므로, 배포로 인한 장애를 최소화할 수 있습니다. (물론 롤백이 일어나면 해당 배포는 실패로 표기되고 후속 조치가 필요하겠지만, 사용자 영향은 줄일 수 있습니다.)
    • 로그와 세부 지표 모니터링: 새로운 버전이 배포된 이후에도 지속적인 모니터링이 중요합니다. AWS CloudWatch Logs에 애플리케이션 로그를 수집해두었다면 배포 시각 이후 에러 로그가 급증하지는 않는지 확인합니다. 또한 CodeDeploy 에이전트 로그(/var/log/codedeploy-agent)나 각 배포 단계의 출력 로그도 확인하여 경고나 문제를 탐지합니다. AWS CloudTrail을 통해 누가 어느 시각에 배포를 트리거했는지 등의 배포 이력도 추적 가능합니다. 필요하다면 AWS SNS 알림을 설정해 CodePipeline 또는 CodeDeploy 결과를 팀원들에게 전파하는 것도 좋습니다. 예를 들어 배포 성공/실패시 SNS 토픽으로 알림을 보내 Slack이나 이메일로 받도록 하면, 실시간으로 배포 상황을 파악할 수 있습니다.
    • 실패 사례 팁: Blue/Green 배포를 진행하다 보면 간혹 새 환경이 정상 구동되지 않아 AllowTraffic 단계에서 실패하는 경우가 있습니다. 예를 들어 새 인스턴스의 보안 그룹 설정이 잘못되어 있어 애플리케이션 포트가 로드 밸런서로부터 접근 불가하면, 헬스 체크에 계속 실패하여 배포가 자동 중단됩니다. 실제로 “보안 그룹에 포트 8080을 열지 않아 CodeDeploy가 AllowTraffic 단계에서 실패했다”는 사례도 있었죠. 이러한 문제를 막으려면 사전에 보안 그룹, 서브넷, 라우팅 설정을 점검하고, 헬스 체크 경로가 올바른지 확인해야 합니다. 그래도 사람이 실수할 수 있으니 "실수해도 괜찮아요, AWS도 가끔 실수하니까요! 😂" 라는 마음가짐으로, 문제 발생 시 침착하게 로그와 설정을 재검토하면 됩니다. 배포 자동화에도 사람이 신경 쓸 부분이 완전히 사라지는 것은 아니지만, 자동화 수준이 높을수록 실수로 인한 영향은 줄어들고 복구는 빨라집니다.

    마지막으로, 많은 분들이 궁금해하시는 몇 가지 사항을 FAQ 형태로 정리하며 글을 마무리하겠습니다.

    FAQ

    Q1. CodePipeline Blue Green 배포로 전환하려면 기존 CodeDeploy 설정을 모두 새로 만들어야 하나요?
    A1. 아닙니다. 기존 CodeDeploy 애플리케이션은 재사용하고, 배포 그룹만 Blue/Green 방식으로 새로 만들어주면 됩니다. 예를 들어 기존에 인플레이스로 사용하던 배포 그룹이 있다면, 동일한 EC2 태그나 Auto Scaling Group을 대상으로 Deployment type을 Blue/Green으로 설정한 새로운 배포 그룹을 생성합니다. 그리고 CodePipeline의 Deploy 단계에서 새 배포 그룹을 가리키도록 업데이트하면 됩니다. CodeDeploy 설정에서 ALB 대상 그룹 등 추가 설정(예: 트래픽 전환 방식, 원본 종료 대기시간)만 해주면 되므로, AWS 배포 자동화 파이프라인 전체를 다시 만드는 건 아닙니다. 기존 인스턴스들에도 CodeDeploy 에이전트가 깔려 있다면 그대로 활용 가능합니다.

    Q2. Blue/Green 배포가 AWS 배포 자동화에 왜 유리한가요? 수동 배포와 비교해서 얻는 이점은?
    A2. AWS 배포 자동화의 목표는 일관되고 신속한 배포입니다. Blue/Green은 여기에 무중단성과 안정성을 더해줍니다. 수동으로 배포하면 사람마다 단계가 달라 실수가 생길 수 있지만, 자동화 파이프라인은 항상 동일하게 동작하죠. Blue/Green을 사용하면 배포 자동화 중에도 서비스 가용성을 유지할 수 있고, 문제 발생 시 자동 롤백 등 자기 치유적 대응도 가능합니다. 요약하면, 인간의 실수를 줄이고 서비스 연속성을 보장하는 측면에서 Blue/Green 배포는 자동화 파이프라인의 완성도를 한층 높여줍니다. 다만 초기 설정이 조금 복잡할 뿐, 일단 구축해 놓으면 이후 배포 부담이 크게 줄어듭니다.

    Q3. Spring Boot EC2 배포 환경에서 Blue/Green을 도입하면 비용이 두 배로 드는 것 아닌가요?
    A3. 일시적으로 배포 순간에만 두 환경을 동시에 운영하므로, 약간의 추가 비용이 발생하는 것은 사실입니다. 예를 들어 EC2 인스턴스 2대를 Blue, 2대를 Green으로 총 4대를 배포 중에 띄우게 됩니다. 하지만 Green 배포 완료 후 짧은 대기시간을 거치고 나면 Blue 인스턴스들은 종료되므로, 상시 두 배 비용이 드는 것은 아닙니다. 비용 절감을 원한다면 Auto Scaling 그룹의 최소 인스턴스 수를 일시적으로 줄여 Blue/Green 합쳐도 기존 규모 정도로 운영하는 방법도 있고, 배포 빈도를 적절히 조정할 수도 있습니다. 무엇보다 무중단 배포로 인한 유저 만족도 향상과 장애 예방의 가치를 고려하면, 그 정도 비용은 충분히 투자할 만합니다. 또한 필요한 경우 Green 환경에 스팟 인스턴스를 활용하여 비용을 낮출 수도 있습니다. AWS 또한 비용 최적화 옵션들을 제공하니, Spring Boot EC2 무중단 배포를 위한 투자로 보면 될 것입니다.

    Q4. Blue/Green으로 전환할 때 주의해야 할 다른 점이 있을까요? (예: 세션 관리나 캐시 등)
    A4. 네, 세션 데이터와 캐시에 대한 고려가 필요합니다. Blue/Green 전환 시 사용자의 세션이 한쪽(Blue)에만 저장돼 있다면, Green으로 트래픽 이동 후 세션 유실이 발생할 수 있습니다. 이를 해결하려면 세션 스토리지를 외부 공용 저장소로 사용해야 합니다 (예: ElastiCache Redis로 세션 공유 설정). Spring Boot의 경우 세션 클러스터링 또는 DB 세션 저장 등을 활용할 수 있습니다. 캐시도 마찬가지로, 애플리케이션 내 메모리캐시가 있다면 Green에서는 초기화 상태이므로 캐시 미스율이 일시적으로 높아질 수 있습니다. 가능한 한 Redis 같은 공용 캐시 계층을 사용하면 Blue/Green 간 캐시를 공유하게 되어 전환이 매끄럽습니다. 마지막으로 파일 업로드 등을 EC2 로컬 디스크에 저장하고 있었다면, 새 인스턴스에는 그 내용이 없으므로 공유 스토리지(S3 등)로 마이그레이션하는 것이 좋습니다. 이런 상태 관리 이슈들만 해결해두면, Blue/Green 전환은 기술적으로 큰 어려움 없이 이뤄질 것입니다.

     

    ※ 다음글

    2025.08.06 - [IT 트렌드/AWS & 클라우드 쉬운 활용법] - 애플리케이션 세션 클러스터링 구현 (Blue/Green CodeDeploy 활용)

     

    애플리케이션 세션 클러스터링 구현 (Blue/Green CodeDeploy 활용)

    목차분산 환경에서의 세션 관리 전략현대 웹 애플리케이션을 분산된 서버 환경에서 운영할 때는 세션 관리 방법이 매우 중요합니다. 단일 서버에서는 세션을 메모리에 저장하면 간단하지만, 서

    kberry.tistory.com

     


    이처럼 CodePipeline Blue/Green 배포를 도입하면 Spring Boot 애플리케이션을 AWS EC2에 무중단 배포하는 것이 가능해집니다. 처음엔 생소할 수 있지만 한 번 구축해 두면 배포 안정성과 개발 생산성이 크게 향상될 거예요. 배포 자동화로 스트레스는 줄이고, 여유로운 마음으로 서비스를 발전시켜 보세요! 🚀👍