설정 주입 경로 - fresh-market/fm-backend GitHub Wiki

설정 주입 경로

같은 application.yml 을 읽어도 실행 방법마다 값의 출처가 다르다. 스프링 서버 실행과 통합 테스트, 두 경로에서 각 값이 실제로 어디서 오는지 정리했다.

로그와 테스트 결과는 2026-08-20 에 로컬 Docker 로 직접 돌려 확인한 것이다.

출처는 셋이다

출처 뜻
저장소 git 에 올라가는 파일. 클론하면 누구나 같은 값을 갖는다
저장소 밖 git 에 없다. 각자 만들거나 배포가 넣어준다. 비밀값이 여기 있다
런타임 주입 파일이 아니라 실행 중에 만들어진다. 컨테이너가 뜬 뒤 그 접속 정보를 읽어 넣는다

덮는 순서

같은 키를 여러 곳이 말하면 위쪽이 이긴다.

순위 출처
1 런타임 주입. Testcontainers @ServiceConnection, docker-compose 감지 가장 셈
2 명령행 인자. --spring.datasource.url=...
3 시스템 프로퍼티. Gradle systemProperty
4 OS 환경변수. DB_URL, SPRING_PROFILES_ACTIVE
5 프로필 파일. application-{프로필}.yml
6 기본 파일. application.yml 가장 약함

환경변수는 이 우선순위의 한 칸일 뿐이고, 실제로는 그보다 위 칸이 자주 값을 가로챈다.

그리고 .env 는 이 우선순위에 아예 없다. Docker Compose 만 읽어서 컨테이너를 어떻게 띄울지 정할 뿐, Spring 에는 닿지 않는다. .env 에 DB_URL 을 적어도 스프링 서버는 못 본다.

스프링 서버 실행: ./gradlew bootRun

프로필을 아무것도 주지 않는다. application.yml 의 기본값이 local 을 켠다.

1. 프로필 결정      application.yml                     [저장소]
   |                  profiles.default: local
   |
2. 기본값          application.yml                     [저장소]
   |                  DB 접속 정보. compose 구성에 맞는 기본값
   |
3. 로컬 값         application-local.yml               [저장소 밖]
   |                  카카오 키, JWT 서명 키. .gitignore 가 막는다
   |
4. DB 를 덮는다     spring-boot-docker-compose          [런타임 주입]
   |                  compose.yaml 의 MySQL 을 띄우고
   |                  그 컨테이너에서 읽은 접속 정보로 덮는다
   |
5. 기동            Flyway 마이그레이션 -> Hibernate validate -> Tomcat

확인한 로그다.

No active profile set, falling back to 1 default profile: "local"

application.yml 의 url, username, password 는 bootRun 에서는 실제로 안 쓰인다. 컨테이너에서 읽은 값이 이기기 때문이다.

그 셋이 쓰이는 때는 compose 없이 붙을 때다. 대표적으로 IntelliJ 에서 main() 을 직접 실행할 때인데, 그 경로는 Gradle 을 안 거쳐서 docker-compose 지원이 붙지 않는다. DB 를 미리 띄워둬야 한다.

통합 테스트: ./gradlew integrationTest

여기서는 환경변수가 한 칸도 안 쓰인다. 프로필은 시스템 프로퍼티로, DB 는 Testcontainers 로 들어온다.

1. 프로필 결정      build.gradle                        [저장소]
   |                  systemProperty 'spring.profiles.active', 'integrationTest'
   |                  IDE 직접 실행 대비로 테스트 클래스에 @ActiveProfiles 도 붙였다
   |
2. 기본값          application.yml                     [저장소]
   |                  공통만. local 이 안 켜지므로 application-local.yml 은 안 읽힌다
   |
3. 비밀값          src/integrationTest/resources/      [저장소]
   |                  application-integrationTest.yml
   |                  가짜 값이라 커밋한다. 이게 없으면 컨텍스트가 안 뜬다
   |
4. DB              @ServiceConnection MySQLContainer   [런타임 주입]
   |                  테스트마다 컨테이너를 띄우고 그 접속 정보를 넣는다
   |                  파일에 DB 설정이 없어도 된다
   |
5. 결과            22건 통과 (Product 11, Category 8, Placement 3)

확인한 로그다.

The following 1 profile is active: "integrationTest"

application-integrationTest.yml 이 생긴 이유

CI 는 PR 에서 브랜치 머리가 아니라 병합 커밋을 체크아웃한다.

그래서 비밀값 키를 추가한 브랜치가 통합 테스트를 하나도 안 건드렸어도, develop 쪽 통합 테스트가 그 브랜치의 application.yml 위에서 함께 돌아 빌드가 깨진다.

같은 커밋에서 이 파일만 빼면 11건이 전부 PlaceholderResolutionException 으로 실패한다.

값별로 보면

같은 키가 경로마다 다른 곳에서 온다.

키 bootRun 통합 테스트 운영
spring.profiles.active application.yml 기본값 Gradle systemProperty SPRING_PROFILES_ACTIVE
spring.datasource.url compose 컨테이너 Testcontainers DB_URL
spring.datasource.username compose 컨테이너 Testcontainers DB_USERNAME
jwt.secret application-local.yml application-integrationTest.yml JWT_SECRET
...kakao.client-id application-local.yml application-integrationTest.yml KAKAO_CLIENT_ID
kakao.admin-key application-local.yml application-integrationTest.yml KAKAO_ADMIN_KEY
hibernate.format_sql application.yml (true) application.yml (true) application-prod.yml (false)
MYSQL_PORT .env -> Compose 해당 없음 해당 없음

마지막 줄을 보라. MYSQL_PORT 만 .env 에서 오고, 그것도 Spring 이 아니라 Compose 가 읽는다. .env 가 스프링 서버 설정에 관여하는 칸은 이 표에 하나도 없다.

운영은 아직 배선 전이다

파일은 이름만 갖고 있고 값을 넣어줄 쪽이 아직 없다. infra 문서가 정한 경로는 이렇다.

SSM Parameter Store (SecureString)        [저장소 밖]
   |   서명 키와 DB 자격증명
   |
배포 스크립트                              아직 없다
   |   컨테이너 교체보다 먼저 값을 갱신해야 한다 (INF-7-03)
   |
컨테이너 환경변수                          [저장소 밖]
   |   서버 위 .env 를 거칠 수도 있다. 어느 쪽이든 저장소에는 없다
   |
application-prod.yml                      [저장소]
       ${DB_URL} 처럼 이름만 적혀 있다
       기본값이 없어 값이 빠지면 기동이 막힌다

없는 것이 셋이다.

없는 것 상태
Dockerfile 스프링 서버 컨테이너 이미지를 만들 방법이 아직 없다
배포 워크플로 .github/workflows 에 pr-gate, registry-check, wiki-sync 뿐이다
SSM 파라미터 문서에 정해져 있고 실제로 만들어진 것은 없다

함께 볼 것

설정 파일 각각의 역할과 로컬에서 무엇을 고치는지는 저장소의 docs/project/configuration.md 에 있다.