1. 문제: SonarQube 분석 과정에서 테스트 실패

테스트 Spring Boot 프로젝트에 SonarQube 분석을 적용하던 중 GitHub Actions에서 빌드가 실패했다.
워크플로는 다음 명령어로 빌드와 분석을 실행하고 있었다.
./gradlew build sonar --info
실패한 부분은 SonarQube의 코드 분석 자체가 아니라, build에 포함된 테스트 실행 단계였다.
contextLoads() 테스트가 Spring 애플리케이션을 시작하는 과정에서 다음 오류가 발생했다.
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'entityManagerFactory'
Unable to create requested service
[org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
Caused by: org.hibernate.HibernateException:
Unable to determine Dialect without JDBC metadata
(please set 'jakarta.persistence.jdbc.url' for common cases
or 'hibernate.dialect' when a custom Dialect implementation
must be provided)
처음에는 오류 메시지에 등장한 Dialect 설정이 빠진 것처럼 보였다. 하지만 실제로 확인해야 할 부분은 DB 연결 환경이었다.
2. 원인: 로컬과 CI에서 localhost는 서로 다른 곳이다
애플리케이션의 DB 설정은 다음과 같았다.
spring:
datasource:
url: jdbc:postgresql://localhost:5432/zelotest
username: postgres
password: postgres1234
driver-class-name: org.postgresql.Driver
이 설정에서 localhost는 항상 개발자의 컴퓨터를 의미하지 않는다. 프로그램이 실행되는 환경 자신을 가리킨다.
| 실행 위치 | localhost가 가리키는 곳 |
| 개발자의 컴퓨터 | 개발자의 컴퓨터 |
| GitHub Actions runner | GitHub Actions의 작업 실행 머신 |
따라서 GitHub Actions에서 실행한 테스트는 내 컴퓨터의 PostgreSQL이 아니라, runner 자신의 5432 포트에 연결을 시도했다.
그런데 기존 워크플로에는 코드 체크아웃, JDK 설정, 캐시 설정, Gradle 실행만 있었고 PostgreSQL을 준비하는 단계가 없었다.
결국 애플리케이션이 기대하는 주소에 테스트용 DB가 준비되지 않은 상태였다.
DB 연결 문제가 왜 Dialect 오류로 나타났을까?
Dialect는 Hibernate가 PostgreSQL, MySQL 등 DB마다 다른 SQL 문법을 처리하기 위해 사용하는 설정이다.
Hibernate는 일반적으로 DB 연결을 통해 얻은 JDBC 메타데이터로 적절한 Dialect를 결정한다. 이번에는 DB에 연결하지 못해 메타데이터를 얻지 못했고, 그 결과 Dialect도 결정하지 못했다.
실패 흐름은 다음과 같다.
- 테스트에서 Spring 애플리케이션을 시작한다.
- JPA 초기화를 위해 DB 연결을 시도한다.
- CI 환경의 localhost:5432에 연결하지 못한다.
- JDBC 메타데이터를 읽지 못한다.
- Dialect를 결정하지 못해 entityManagerFactory 생성이 실패한다.
즉, Dialect 오류는 DB 연결 실패로 이어진 후속 오류였다. hibernate.dialect를 직접 지정하더라도 연결할 DB가 없는 문제까지 해결되는 것은 아니다.
3. 해결: GitHub Actions에 테스트용 PostgreSQL 추가
테스트가 실행되는 환경에도 DB가 필요하므로, 해당 job에 PostgreSQL 서비스 컨테이너를 추가했다.
아래 설정을 기존 build job의 runs-on 아래, steps와 같은 들여쓰기 수준에 배치했다.
jobs:
build:
name: Build and analyze
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_DB: zelotest
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres1234
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d zelotest"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
# 기존 checkout, JDK 설정, 캐시 설정 및 Gradle 실행 단계
postgres:16은 예시이며, 실제 프로젝트에서 사용하는 PostgreSQL 버전에 맞춰 설정한다.
위 계정 정보는 CI에서 생성하는 임시 테스트 DB용이다.
| 설정 | 역할 |
| image | 실행할 PostgreSQL 이미지 지정 |
| POSTGRES_DB | 초기 데이터베이스 생성 |
| POSTGRES_USER, POSTGRES_PASSWORD | 테스트 DB 계정 설정 |
| ports | runner의 5432 포트와 컨테이너의 5432 포트 연결 |
| pg_isready | PostgreSQL이 연결을 받을 준비가 됐는지 확인 |
현재 워크플로는 Gradle을 runner에서 직접 실행하므로, 포트를 연결하면 기존 주소인 localhost:5432를 사용할 수 있다.
또한 ddl-auto: update가 설정되어 있어도 연결 대상 데이터베이스 자체를 만들어주지는 않는다. 이번 구성에서는 POSTGRES_DB: zelotest로 빈 데이터베이스를 먼저 준비한다.
📍배운 점
이번 문제를 통해 CI에서는 애플리케이션 코드뿐 아니라 실행에 필요한 외부 의존성도 준비해야 한다는 것을 알게 되었다.
특히 localhost가 실행 환경에 따라 다른 대상을 가리킨다는 점이 중요했다.
개발자의 컴퓨터에 DB가 존재하더라도 GitHub Actions의 실행 머신에서 그대로 사용할 수는 없다.
오류 메시지에 나타난 설정을 곧바로 추가하기보다, 해당 오류가 발생하기까지의 연결 과정을 살펴봐야 한다. 이번에는 Dialect 설정 자체보다 CI 환경에 테스트용 PostgreSQL이 준비되어 있는지 확인하는 것이 해결의 핵심이었다.
'개발공부 > 인프라 · DevOps' 카테고리의 다른 글
| [Troubleshooting] OpenAI를 부르는 클래스의 테스트 커버리지가 0%였던 이유 (0) | 2026.10.20 |
|---|---|
| [Troubleshooting] SonarCloud 자동 분석과 GitHub Actions CI 분석 충돌 해결하기 (0) | 2026.10.18 |
| [궁금증] NAT 게이트웨이 - 프라이빗 ip주소로 변환한 다음에는..? + 느낀점 (0) | 2023.07.22 |
| [궁금증] S3에서 객체 업로드 시 비용이 발생하지 않도록 하려면 어떻게 해야하나? (0) | 2023.07.21 |
| [궁금증] EC2에서 왜 OS를 지정할까? (0) | 2023.07.20 |