로컬 환경(Local)에서 개발하던 스프링 부트 프로젝트를 실제 클라우드 환경(Cloudtype)에 배포하며 겪은 시행착오와 해결 과정을 정리합니다. 이번 경험을 통해 인프라 설정과 데이터베이스 연결의 핵심 원리를 깊이 이해하게 되었습니다.
1. 개요
- 프로젝트명: Pace
- 배포 환경: Cloudtype (Spring Boot, MariaDB)
- 주요 기술: Java 21, Spring Boot 3.x, Spring Data JPA, MySQL
2. 주요 트러블슈팅 (Troubleshooting)
2.1 환경 변수 주입 문제
- 문제:
java.lang.RuntimeException: Driver claims to not accept jdbcUrl, ${DATABASE_URL} - 원인: 로컬의
.env파일은 깃에 올리지 않으므로, 서버는${DATABASE_URL}이라는 변수의 실제 값을 찾지 못해 발생한 문제. - 해결: 클라우드타입 콘솔의 환경 변수(Environment Variables) 설정 메뉴에서
DATABASE_URL,DATABASE_USERNAME,DATABASE_PASSWORD를 직접 등록하여 해결. - 학습: 배포 환경에서는 민감한 정보를 외부 환경 변수를 통해 주입(Injection)받는 것이 정석임을 이해함.
2.2 MariaDB 호환성 및 접속 주소
- 문제: 클라우드타입 서비스 목록에 MySQL이 없어 MariaDB를 선택하며 발생한 혼란.
- 원인: MySQL과 MariaDB는 뿌리가 같아 호환되지만, 접속 주소 형식을 맞추는 작업이 필요했음.
- 해결: 주소 형식을
jdbc:mysql://로 유지하여 기존 MySQL 드라이버가 MariaDB와 대화할 수 있도록 설정.
2.3 URL 문법 오타
- 문제:
jdbc:mysql//...(콜론 누락) 에러 발생. - 원인: 주소를 수동 입력하는 과정에서 프로토콜 구분자인
:를 누락하여 드라이버가 주소를 인식하지 못함. - 해결:
jdbc:mysql://형식으로 정확히 수정. - 교훈: 인프라 설정 시 문자 하나가 시스템 전체의 실행 여부를 결정하므로 극도의 세밀함이 필요함.
2.4 하이버네이트 방언(Dialect) 에러
- 문제:
java.sql.SQLSyntaxErrorException: Unknown column 'RESERVED' in 'WHERE' - 원인: MySQL 드라이버가 MariaDB의 시스템 테이블 구조를 잘못 파악하여 발생한 문법 오류.
- 해결: 환경 변수에
SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT를 추가하고 값을org.hibernate.dialect.MariaDBDialect로 명시하여 해결. - 학습: JPA가 SQL을 번역할 때 사용하는 방언(Dialect)의 개념과 자동 판별이 실패할 경우의 수동 설정법을 익힘.
3. 결과 및 성과
다양한 네트워크 및 설정 에러를 해결한 끝에 다음과 같이 서버가 정상 구동됨을 확인하였다.
Tomcat started on port 8080 (http) with context path '/'
Started PaceApplication in 114.597 seconds
4. 향후 배포 고도화 계획
현재는 클라우드타입의 간단하게 UI 기반 배포를 사용했으나, 다음 단계로 CI/CD 파이프라인을 직접 구축할 계획이다.
- GitHub Actions: 코드 푸시 시 자동 빌드 및 JAR 생성.
- Docker Hub: 생성된 이미지를 가상화하여 보관.
- AWS EC2 & Docker Compose: 서버에서 이미지를 내려받아 앱과 DB를 컨테이너로 묶어 실행.
5. 마치며
"삽질은 배신하지 않는다"는 말을 체감한 하루였습니다. 단순히 코드를 짜는 것만큼이나 내가 짠 코드가 어떤 환경에서 어떻게 돌아가는지 이해하는 것이 백엔드 개발자의 핵심 역량임을 깨달았습니다..