Fivefy 프로젝트/트러블슈팅

AWS EC2 + RDS 환경에서 Spring Boot 배포

sudaruuu 2026. 5. 8. 20:46

들어가며

기존에는 로컬 환경에서만 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 등 다양한 요소에 의해 실행이 실패할 수 있다는 점을 경험할 수 있었다. 앞으로는 단순 기능 구현뿐 아니라, 배포 및 운영 환경까지 고려하는 방향으로 프로젝트를 계속 개선해보려고 한다.