들어가며
기존에는 로컬 환경에서만 Spring Boot 프로젝트를 실행하고 있었지만, 실제 배포 환경을 경험해보기 위해 AWS EC2와 RDS를 이용한 배포를 진행하였다.
이번 과정에서는 단순히 서버를 띄우는 것보다,
- EC2 생성 및 SSH 접속
- Java / Git / Redis 설치
- Spring Boot jar 빌드 및 실행
- RDS(MySQL) 생성 및 연결
- Flyway 설정 충돌 해결
- 환경변수 및 Scheduler placeholder 문제 해결
등 실제 배포 환경에서 발생하는 다양한 문제들을 직접 경험하게 되었다.
이번 글에서는 EC2 + RDS 기반 Spring Boot 배포 과정과, 실제로 발생했던 에러 및 해결 과정을 정리해보려고 한다.
전체 배포 흐름
이번 배포는 다음과 같은 흐름으로 진행하였다.
IntelliJ
→ GitHub Push
→ EC2 접속
→ 프로젝트 clone
→ jar build
→ RDS 연결
→ Spring Boot 실행
1. EC2 생성
AWS 콘솔에서 EC2 인스턴스를 생성하였다.
사용 환경
- Amazon Linux 2023
- t2.micro
- Java 17
- Spring Boot
생성 이후 .pem 키 파일을 이용해 SSH 접속을 진행하였다.

2. EC2 SSH 접속
chmod 400 key.pem
ssh -i key.pem ec2-user@EC2_PUBLIC_IP
정상적으로 접속되면 다음과 같은 형태로 표시된다.
[ec2-user@ip-10-0-12-8 ~]$
3. Java / Git 설치
Amazon Linux 환경이기 때문에 apt가 아니라 dnf를 사용해야 했다.
Java 17 설치
sudo dnf update -y
sudo dnf install java-17-amazon-corretto-devel -y
Git 설치
sudo dnf install git -y
Java 버전 확인
java -version
4. 프로젝트 clone
GitHub에 push 되어있는 프로젝트를 EC2에 clone 하였다.
git clone https://github.com/계정명/프로젝트명.git
cd 프로젝트명
5. Spring Boot jar 빌드
초기에는 다음 명령어로 build를 시도하였다.
./gradlew clean build -x test
하지만 REST Docs asciidoctor 관련 에러가 발생하였다.
문제 상황
Task :asciidoctor FAILED
build/generated-snippets doesn't exist
원인 분석
Spring REST Docs + Asciidoctor 설정이 포함되어 있었고, 테스트를 실행하지 않은 상태에서 문서 생성 task가 실행되면서 snippets 디렉토리가 존재하지 않아 발생한 문제였다.
해결
배포용 jar만 필요했기 때문에 asciidoctor task를 제외하였다.
./gradlew clean bootJar -x test -x asciidoctor
정상적으로 build가 완료되면 다음 위치에 jar가 생성된다.
build/libs/
6. Redis 설치
애플리케이션 실행 중 Redis 연결 오류가 발생하였다.
문제 상황
Unable to connect to Redis server: localhost:6379
Connection refused
원인 분석
Redis 설치 및 실행
sudo dnf install redis6 -y
sudo systemctl start redis6
sudo systemctl enable redis6
Redis 실행 여부 확인
sudo systemctl status redis6

7. RDS(MySQL) 생성
Spring Boot 실행 중 DB 연결 관련 에러가 발생하였다.
문제 상황
jdbcUrl is required with driverClassName
원인 분석
MySQL datasource 정보가 존재하지 않았다.
즉,
- DB_URL
- DB_USERNAME
- DB_PASSWORD
환경변수가 설정되지 않은 상태였다.
해결
AWS RDS(MySQL)를 생성하였다.
생성 옵션
- Engine : MySQL
- Template : Free Tier
- 퍼블릭 액세스 : 아니요
- EC2와 동일 VPC 사용
생성 이후 Endpoint를 확인하였다.
fivefy-db.xxxxxx.ap-northeast-2.rds.amazonaws.com

8. RDS Database 생성
초기에는 다음과 같이 mysql 시스템 DB에 연결하였다.
jdbc:mysql://RDS주소:3306/mysql
하지만 Flyway 실행 중 권한 오류가 발생하였다.
문제 상황
Access denied for user 'admin'@'%' to database 'mysql'
원인 분석
AWS RDS에서는 시스템 DB(mysql)에 대한 권한 제한이 존재한다.
즉, 실제 서비스용 database를 별도로 생성해야 했다.
해결
MySQL CLI를 이용해 직접 database를 생성하였다.
mysql -h RDS주소 -u admin -p
CREATE DATABASE fivefy;
이후 datasource를 다음과 같이 변경하였다.
jdbc:mysql://RDS주소:3306/fivefy

9. Flyway(PostgreSQL) 충돌 문제
프로젝트에는 MySQL + PostgreSQL(vector DB) 두 개의 datasource가 존재하고 있었다.
하지만 실제 배포에서는 PostgreSQL vector DB를 사용하지 않는 상태였다.
문제 상황
postgresFlywayBean
jdbcUrl is required with driverClassName
원인 분석
커스텀 FlywayConfig 내부에서 PostgreSQL Flyway Bean이 생성되고 있었고, vector datasource 정보가 없어서 애플리케이션이 종료되고 있었다.
@Bean(name = "postgresFlywayBean")
@ConditionalOnProperty(name = "custom.flyway.postgre.enabled", havingValue = "true")
해결
실행 시 PostgreSQL Flyway를 비활성화하였다.
--custom.flyway.postgre.enabled=false
반면 MySQL Flyway는 유지하였다.
--custom.flyway.mysql.enabled=true
10. Scheduler Placeholder 문제
애플리케이션 실행 이후 Scheduler 관련 placeholder 오류가 발생하였다.
문제 상황
Could not resolve placeholder 'CHARGE_CRON'
이후 추가적으로 아래와 같은 오류도 발생하였다.
Could not resolve placeholder 'SUBSCRIPTION_CRON'
원인 분석
@Scheduled에서 사용하는 cron 표현식이 환경변수 기반으로 작성되어 있었지만, EC2 환경에 값이 존재하지 않았다.
scheduler:
charge-cron: ${CHARGE_CRON}
해결
실행 시 cron 값을 직접 전달하였다.
--CHARGE_CRON="0 0 0 * * *"
--SUBSCRIPTION_CRON="0 0 1 * * *"
11. 최종 실행 명령어
최종적으로 다음 명령어로 Spring Boot 애플리케이션을 실행하였다.
pkill -f java; rm -f app.log; nohup java -jar build/libs/*.jar \
--spring.profiles.active=prod \
--spring.datasource.primary.url="jdbc:mysql://RDS주소:3306/fivefy?serverTimezone=Asia/Seoul&characterEncoding=UTF-8" \
--spring.datasource.primary.username="admin" \
--spring.datasource.primary.password="비밀번호" \
--spring.datasource.primary.jdbc-url="jdbc:mysql://RDS주소:3306/fivefy?serverTimezone=Asia/Seoul&characterEncoding=UTF-8" \
--spring.data.redis.host=localhost \
--custom.flyway.mysql.enabled=true \
--custom.flyway.postgre.enabled=false \
--CHARGE_CRON="0 0 0 * * *" \
--SUBSCRIPTION_CRON="0 0 1 * * *" \
> app.log 2>&1 &
로그 확인
tail -f app.log


정리
이번 배포 과정에서는 단순히 Spring Boot jar를 실행하는 수준이 아니라, 실제 운영 환경에서 필요한 다양한 설정과 문제들을 경험할 수 있었다.
특히 다음과 같은 부분들을 직접 확인할 수 있었다.
- EC2 Linux 환경 이해
- Java / Redis / MySQL 설치 및 연결
- RDS 네트워크 및 권한 구조
- 환경변수 기반 설정 관리
- Flyway 다중 datasource 구성
- Scheduler placeholder 관리
- 운영 환경에서의 실행 명령 구성
처음에는 단순히 “jar 실행” 정도로 생각했지만, 실제로는 인프라와 애플리케이션 설정이 모두 연결되어 있다는 점을 체감할 수 있었다. 또한 이번 과정을 통해, 로컬에서는 잘 동작하던 애플리케이션도 운영 환경에서는 환경변수 / datasource / scheduler / migration 등 다양한 요소에 의해 실행이 실패할 수 있다는 점을 경험할 수 있었다. 앞으로는 단순 기능 구현뿐 아니라, 배포 및 운영 환경까지 고려하는 방향으로 프로젝트를 계속 개선해보려고 한다.
'Fivefy 프로젝트 > 트러블슈팅' 카테고리의 다른 글
| AWS CLI 기반 S3 인증 구조 개선 (0) | 2026.05.13 |
|---|---|
| PlaylistTrack reorder 동시성 테스트 검증 기준 개선 (0) | 2026.05.11 |
| Top N 제한을 DB로 이동하며 조회 성능 개선한 경험 (0) | 2026.04.28 |
| 인기 차트 생성 로직 리팩토링과 조회 흐름 정리 (0) | 2026.04.28 |
| PlaylistTrack 순서 변경 최적화 전체 재정렬을 부분 재정렬로 개선 (0) | 2026.04.23 |