시작하며
웹 성능 테스트 플랫폼(Webtest) 프로젝트가 운영 배포를 앞두고 있습니다.
이번 프로젝트에서는 전통적인 SSH 방식이 아닌 AWS Systems Manager(SSM) 기반으로
무중단 SSH 배포 자동화 파이프라인을 구성했습니다.
CI/CD 구현을 준비하면서 어떤 선행 작업이 필요했는지 어떻게 배포 아키텍처를 설계했는지 정리해두고자 합니다.
특히 팀원 누구나 손쉽게 운영 환경에 반영할 수 있도록 명확한 절차와 구조 그리고 실제 운영 중 겪을 수 있는 포인트까지 담았습니다.
1. CI/CD 구축을 위한 선행 세팅: 체크리스트 중심 정리
A. GitHub 레포지토리 & 브랜치 전략
- 레포: webtest
- 브랜치 운영 규칙:
- develop → 개발 작업 및 테스트
- main → 운영 배포 트리거용 브랜치
권장 흐름
- CI (빌드, 테스트, GHCR 이미지 푸시)
→ main, develop 모두에서 실행 - CD (배포 실행)
→ main push에만 실행
B. 컨테이너 이미지 저장소: GHCR 설정
- 이미지 네이밍 규칙:
ghcr.io/<owner>/<image>:<tag>- <owner>는 반드시 소문자로 설정
- 예: ghcr.io/eonseojiancasino/webtest-backend:latest
- GHCR Pull을 위한 토큰 발급 (EC2에서 docker login용)
- GitHub Settings → Developer Settings → Personal Access Token 생성
- 필수 권한: read:packages
- EC2 내부에 .env 또는 시크릿 파일로 저장
C. EC2 준비 (SSM 배포용)
- Ubuntu 22.04 기반 EC2 생성 (퍼블릭 IP 필요)
- 보안 그룹:
- 80, 443만 오픈
- 22(SSH)는 닫아도 됨 (SSM 사용 시 필요 없음)
- 전달받아야 할 값:
- EC2 Instance ID (SSM용)
- 퍼블릭 IP (도메인 연결 시 사용)
- EC2에 부착된 IAM Role 이름 (SSM Agent 등록용)
IAM Role (SSM Agent용) 설정
- 권한: AmazonSSMManagedInstanceCore
- EC2에 부착 → Systems Manager의 Managed Nodes에 등록되어야 정상
D. 배포용 IAM User (GitHub Actions → AWS 호출용)
- 필요한 값:
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_REGION
- SSM_INSTANCE_ID
- 최소 권한 정책:
- ssm:SendCommand, ssm:GetCommandInvocation
E. EC2 초기 세팅 (1회 수동 or SSM 명령)
- 디렉터리 구성: /home/ubuntu/webtest
- .env 파일 생성: 앱이 필요로 하는 시크릿 저장소
DB_USER=webtest_prod
DB_PASSWORD=...
GHCR_USER=...
GHCR_TOKEN=...
- 필수 패키지 설치
- docker, docker compose, certbot (HTTPS용)
2. CI/CD 전체 흐름 요약: git push → 운영 반영
A. 왜 EC2에서 직접 빌드하지 않는가?
- 빌드 환경 버전 차이를 CI 서버로 통일할 수 있음
- EC2는 가볍고 단순한 런타임 서버만 담당
- 배포 단위는 이미지(GHCR) → 불변 산출물 추적 가능
B. docker compose pull의 의미
- compose 파일에 정의된 이미지 태그를 기준으로
- GHCR에서 새 이미지를 내려받음
- 이후 up -d로 컨테이너 재기동
C. 운영에서 git pull이 필요한 경우
- 앱 코드만 변경: pull && up -d면 충분
- 아래 파일이 변경된 경우에는 git pull 필요:
- docker-compose*.yml
- nginx.conf, default.conf
- prometheus.yml
3. GitHub Actions에서 SSM으로 배포: deploy.yml 구성
name: Deploy to EC2 via SSM
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy to EC2 via SSM
run: |
aws ssm send-command \
--instance-ids "${{ secrets.SSM_INSTANCE_ID }}" \
--document-name "AWS-RunShellScript" \
--comment "webtest deploy" \
--parameters 'commands=[
"cd /home/ubuntu/webtest",
"set -a && source ./.env && set +a",
"echo $GHCR_TOKEN | docker login ghcr.io -u $GHCR_USER --password-stdin",
"docker compose -f docker-compose.prod.yml pull",
"docker compose -f docker-compose.prod.yml up -d",
"docker compose -f docker-compose.monitoring.yml up -d || true"
]'
- 핵심은 aws ssm send-command로 EC2에서 실제 배포 명령을 원격으로 실행하는 구조입니다.
- .env는 배포 시크릿이 아닌 런타임 시크릿이므로 EC2 내에서만 존재합니다.
4. 시크릿 관리: 운영 안정성을 위한 2계층 원칙
| 구분 | 내용 | 저장 위치 |
| 런타임 시크릿 | DB 계정, API 키 등 앱 실행에 필수 | EC2 내부 .env |
| 배포 시크릿 | AWS 키, SSM 인스턴스 ID 등 | GitHub Secrets |
이렇게 계층을 나누면, CI/CD 보안 사고와 앱 구동 오류를 명확히 분리할 수 있습니다.
5. 도메인 연결 & HTTPS 구성 핵심
A. A 레코드 연결 이유
- 도메인(example.com)을 EC2 퍼블릭 IP와 매핑하기 위해 필요
- DNS 요청 시 EC2 IP를 알려주고, 브라우저는 해당 IP로 접속
B. nginx의 역할
- 외부 포트(80, 443) 수신 → 내부 app:8080으로 리버스 프록시
- TLS 종료, HTTP → HTTPS 리다이렉트, 헤더 정책 관리
C. certbot의 역할
- Let’s Encrypt 인증서를 자동 발급/갱신
- 보통 cron 또는 systemd timer로 갱신 자동화
D. 인증서 파일을 nginx에 마운트하는 이유
- 인증서는 EC2 호스트의 /etc/letsencrypt에 저장
- nginx 컨테이너가 이를 참조하려면 호스트 디렉터리 → 컨테이너 디렉터리 마운트가 필요
6. 운영
운영 DB 전략
- 운영용 DB 계정은 .env로 관리, 로컬/개발용과 분리
- PostgreSQL은 컨테이너 기동 시 환경변수를 기준으로 DB 생성
- 이후 변경은 수동 SQL 실행이 필요
실수하기 쉬운 포인트
- GHCR 이미지 네이밍은 소문자만 허용
- 대문자 포함 시 Invalid image reference format 오류 발생
- 운영 DB는 외부 포트 제거
- db: ports 삭제로 보안 강화
- compose/nginx 변경은 이미지로 반영되지 않음
- Git pull 또는 파일 복사 배포 필요
- GHCR가 private일 경우 EC2에서 docker login 필수
- SSM 사용 시 필수 IAM 구성 정리
- EC2에 SSM Role
- GitHub에 최소 권한 IAM User
마치며
이번 웹 성능 테스트 프로젝트에서는 운영 서버에 접속하지 않고도 안전하게 배포할 수 있는 구조를 목표로 아키텍처를 설계했습니다.
CI 서버는 빌드와 이미지 푸시까지 담당하고 EC2는 단순히 이미지를 받아 실행하는 역할만 수행합니다.
덕분에 운영 서버의 복잡도는 줄고 팀원 누구나 명확한 절차에 따라 배포를 수행할 수 있게 되었습니다.
'프로젝트 > 웹 성능 테스트' 카테고리의 다른 글
| 싸피 백엔드 과정: Spring Security (0) | 2025.11.30 |
|---|---|
| 장애 대응을 위한 메트릭 모니터링 단 구축(1. Actuator + Micrometer) (0) | 2025.11.28 |
| 롱폴링 비동기 완료 (0) | 2025.11.27 |
| 비동기 통신 방식 비교와 A/B 테스트 설계 (0) | 2025.11.09 |
| Nginx 도입 2편: 적용 (0) | 2025.11.09 |