이번에 팀원들과 프로젝트를 진행하면서 CI/CD, AWS, Docker 같은 기술을 처음 사용하게 되었어요. 사실 그동안은 개념만 조금 알고 있었지, 실제로 써본 적은 없었거든요. 게다가 인프라를 경험한 팀원도 없었고, 그래서 이번 기회에 배포를 직접 맡아서 한 번 정리해 보자고 결심했습니다.
목표
- EC2, ECR, GitHub Actions를 사용한 Spring Boot 배포
- Spring Boot + MySQL을 Docker Compose로 연동
- CI/CD 자동화 파이프라인 구축
1. EC2
먼저 EC2 인스턴스를 만들고, 퍼블릭 IP에 접속할 수 있게 탄력적 IP도 할당해줬습니다.
SSH 접속 잘 되는지 확인하고, 기본적인 docker, docker-compose 설치도 완료하였습니다.
2. EC2에 MySQL 설치
처음엔 그냥 `sudo apt install mysql-server` 해서 로컬에 MySQL을 깔고, Spring Boot랑 연결하려고 했습니다. 하지만 Docker 컨테이너에서 돌아가는 Spring Boot와 EC2 로컬에서 돌아가는 MySQL이 연결이 잘 안 되더라고요.
컨테이너는 격리된 환경이라 로컬 DB 접근이 어려움을 알게 되었고, 결국 MySQL도 컨테이너로 띄워서 내부에서 네트워크 연결하는 방식으로 변경했습니다.
3. 전체 구조

- GitHub에 push 하면
- GitHub Actions가 Docker Image를 만들고
- AWS ECR에 업로드한 다음
- EC2에 접속해서
- Docker Compose로 배포가 진행되는 구조
4. Dockerfile, docker-compose 구성
Dockerfile로 Spring Boot를 빌드해서 .jar로 만들어줬고,
# docker-compose.yml (일부 발췌)
services:
mysql:
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_DATABASE:test_db
MYSQL_USER: test_user
MYSQL_PASSWORD: 1234
app:
image: .../test-server:latest
env_file:
- .env
depends_on:
- mysql
ports:
- "8080:8080"
application.yml에서는 다음과 같이 환경 변수를 주입해서 DB 연결을 했습니다
spring:
datasource:
url: jdbc:mysql://${MYSQL_HOST}:3306/test_db
username: ${MYSQL_USER}
password: ${MYSQL_PASSWORD}
😱 삽질 모음
1. application.yml이 jar에 안 들어감
jar에 포함 안 되어 있어서 Spring Boot가 DB 설정을 못 읽음
→ GitHub Actions에서 echo "" > ./src/main/resources/application.yml 넣어서 해결!
2. MySQL이 자꾸 3310 포트로 열림
→ EC2에 로컬로 설치한 MySQL이 3306을 점유하고 있었음
→ sudo apt purge mysql*로 완전히 제거하고 해결!
3. EC2 인바운드 규칙
→ 8080, 3306 포트 안 열어놔서 외부에서 접속 안 됨
→ 보안 그룹에서 0.0.0.0/0 으로 열어줌
4. t2.micro 사양 부족
프리티어니까 t2.micro를 썼는데, 배포하면 앱이 자꾸 죽었어요
→ CPU 크레딧 or 메모리 부족 문제로 보입니다
→ 해결: t3.small로 올리니까 바로 정상 작동
5. Docker 환경 변수 안 들어감
Docker 컨테이너에서 환경변수가 안 들어가는 문제 발생
→ 해결: .env 파일 만들고 docker-compose.yml에 연결
최종 결과
- Spring Boot + MySQL 컨테이너 연동 성공
- GitHub Actions로 CI/CD 자동화 완성
- EC2 접속해서 직접 확인 완료
처음엔 리눅스 명령어를 하나도 몰라서 당황했지만 로그 찾는 법, 권한 부여하는 법 등 명령어를 알게 되니 문제 원인을 찾기 수월하더라고요. 결국 디버깅은 로그를 읽는 힘이라는 것을 다시 느꼈습니다.
'공부방' 카테고리의 다른 글
| 인덱스의 중요성, 성능 테스트로 증명하기 (2) | 2025.08.13 |
|---|---|
| CQRS 패턴의 진정한 가치: 부하 테스트로 증명하기 (2) | 2025.08.12 |
| EC2 + Docker + GitHub Actions + Nginx + Route 53 기반 프론트 배포 & HTTPS 적용기 (0) | 2025.04.12 |
| WebSockets vs SSE (0) | 2025.02.17 |
| JUnit5 & Mockito (0) | 2025.02.13 |