[DevOps]GitLab CI 트러블 슈팅 - Springboot contextLoads 예외

Inung_92·2025년 1월 23일
1

DevOps

목록 보기
5/5

개요

GitLab CI와 Springboot를 연동하여 테스트 및 SonarQube를 통한 코드 분석 자동화 파이프라인 구성 시 발생한 트러블 슈팅에 관련한 내용입니다.

해당 트러블 슈팅 기록은 Springboot와 GitLab에 한정하여 발생하는 트러블이므로 GitHub 및 기타 프로그래밍 언어, 프레임워크에 대한 해당사항은 없습니다.

GitLab CI와 Springboot 연동에 대한 정보가 없는 경우 이해가 힘들 수 있으니 여기를 먼저 확인해주시기 바랍니다.

배경

git push 이벤트가 발생하여 파이프라인이 동작하게되면 위 아키텍처에 따라 동작합니다. Springboot에서 단위 테스트를 할 경우 일반적으로 애플리케이션 설정 정보가 불필요하지만 DB 등 외부 인스턴스와 통신을 하게되면 통합 테스트로 작성하게 되어 애플리케이션 설정 정보가 필요하게됩니다.

이 상황에서 ubuntu에 구성된 GitLab Runner가 설정 정보인 application.yaml을 인식하지 못해 아래와 같은 에러가 발생하게 되었습니다.

DemoApplicationTest > contextLoads() FAILED
    java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:143
        Caused by: org.springframework.boot.context.config.ConfigDataResourceNotFoundException at ConfigDataResourceNotFoundException.java:97

원인 추측

application.yaml을 제대로 로드하지 못하는 경우는 여러가지가 있지만 GitLab CI 연동 시 발생할 수 있는 원인은 아래와 같습니다.

  • application.yaml을 포함한 설정 파일에 등록된 환경 변수가 GitLab CI 환경에는 존재하지 않는 경우
  • 소스 코드에 작성된 @Value(“${env.test}“) 형식의 환경 변수가 GItLab CI 환경에 존재하지 않는 경우
  • spring.profiles가 불일치하는 경우
  • DB 접속 정보가 불일치하는 경우
  • spring.server.port가 중복되는 경우

이런 원인들은 GitLab 뿐만 아니라 GitHub에서도 발생 할 수 있는 에러의 원인이기 때문에 반드시 확인을 해주셔야합니다.

이번 트러블 슈팅에는 위 원인과는 다른 GitLab 환경에서만 발생할 수 있는 원인인 환경변수에 설정된 application.yaml 파일이 정상적인 경로로 인식되지 않는 경우에 대해서 설명드리겠습니다.


해결 과정

상태

먼저 GitLab 환경이 어떤 상태여서 이런 에러가 발생했는지 설명드리겠습니다.

  • OS는 ubuntu이며, GitLab, SonarQube, other spring application 등이 구동 중
  • 테스트를 수행할 spring application의 application.yamlGitLab CI/CD > Variables 항목에 등록
  • other spring application은 개발 환경에서 .jar로 빌드를 완료하고, GitLab이 설치된 환경에서 환경 변수로 application.yaml을 로드하여 실행되도록 구성
  • etc/profile 내부에 SPRING_CONFIG_LOCATION=file://path/...와 같이 설정 위치에 대한 환경 변수 등록

위와 같은 상태가 GitLab Runner가 동작할 때 어떤 영향을 받는지 알아보겠습니다.

  • GitLab Runner는 기본적으로 시스템 환경 변수를 상속
  • SPRING_CONFIG_LOCATION이 상속된 환경 변수에 포함
  • GitLab CI/CD > Variables에 등록된 환경 변수를 무시하고, 시스템 환경 변수를 사용

결론적으로 시스템 환경 변수 상속으로 인해 실제 애플리케이션의 설정 파일이 아닌 별도 서비스로 등록된 애플리케이션의 설정 파일을 로드하는 문제가 발생했습니다.

해결 과정

원인 확인

해결에서 시간이 지체되었던 가장 큰 이유는 로그를 너무 늦게 확인했던 점입니다. GitLab CI가 반환하는 로그가 아닌 애플리케이션 실행 로그를 빠르게 확인했더라면 문제가 신속히 해결되었을겁니다.

# .gitlab-ci.yml
...생략
script:
  - ./gradlew test -i

./gradlew test -i 명령어를 사용하면 애플리케이션이 구동되는 동안 출력되는 로그를 GitLab Pipline에서 모두 확인할 수 있습니다.

시스템 환경 변수 명칭 변경

환경 변수의 명칭이 GitLab Runner가 인식할 수 있는 예약어를 사용하였기 때문에 이 부분을 애플리케이션 특성에 맞는 변수명으로 변경했습니다.

sudo vim /etc/profile


# 변경 전
export SPARING_CONFIG_LOCATION=...
# 변경 후
export [애플리케이션명]_CONFIG_LOCATION=...
:wq

# 적용
source /etc/profile

애플리케이션의 서비스 파일에서도 해당 내용을 수정해줍니다.

sudo vim /etc/systemd/system/[애플리케이션명].service

...생략
[Service]
User=...
Environment="[애플리케이션명]_CONFIG_LOCATION=..."
:wq

# 적용
sudo systemctl daemon-reload

GitLab CI/CD Variables 등록

시스템 환경 변수에 대한 설정을 모두 완료하였기 때문에 GitLab CI/CD > VariablesSPRING_APPLICATION_YML 등의 이름으로 설정 정보를 등록해줍니다.

.gitlab-ci.yml 수정

환경 변수로 등록한 설정 파일을 .gitlab-ci.yml 파일에 동적으로 생성되도록 스크립트를 수정합니다.

... 생략
  script:
    - echo "$SPRING_APPLICATION_YML" > src/main/resources/application.yaml
    - chmod +x ./gradlew
    - ./gradlew clean test jacocoTestReport sonar

IDE에서 인식하는 classpathGitLab Runner 환경에서 인식하는 classpath가 다를 수 있기에 위 방법으로도 해결되지 않는다면 classpath에 대한 정보를 확인하는 것이 필요합니다.

스크립트에 아래 명령을 추가하시면 됩니다.

- echo "Classpath debug:"
- ./gradlew printClasspath

기타 원인 해결 방법

application.yaml 혹은 설정 파일에 등록된 환경 변수 누락

.gitlab-ci.yml에 다음과 같이 해당 환경 변수 등록을 통해 GitLab Runner가 인식하도록 설정합니다.

# .gitlab-ci.yml
variables:
  [환경변수명]: []

또는 application.yaml에 환경 변수가 없는 경우에 대비한 기본값을 추가합니다. 이 방식은 SqEL(Spring Expression Language)와 환경 변수 대체 기능이 결합된 형식입니다.

# application.yaml
env:
  test: ${ENV_TEST:[기본값]}

소스 코드의 환경 변수가 GitLab CI 환경에서 누락

소스 코드에서 기본 값을 명시하고 방식은 위에서 설정한 방법과 동일하게 SqEL을 사용합니다.

@Value("${[환경변수명]:[기본값]}"")
private String envValue;

또는 GitLab CI/CD > Variables에 환경 변수를 미리 추가합니다.

spring.profiles 불일치

.gitlab-ci.yml 파일에 프로파일에 대한 정보를 명시적으로 설정합니다.

# .gitlab-ci.yml
variables:
  SPRING_PROFILES_ACTIVE: "test"

또는 gradle을 통해 실행할 때 프로파일 정보를 지정해줍니다.

./gradlew test -Dspring.profiles.active=test

그 외 DB 접속 정보 불일치포트 중복의 경우는 별도로 해결 방법을 작성하지 않겠습니다.


정리

이번 트러블 슈팅을 통해 얻은 교훈은 다음과 같습니다.

  • GitLab Runner구성된 환경과 동작 방식에 대한 이해가 부족했다.
  • 하나의 서버에서 복수 개의 애플리케이션이 실행될 때 설정 파일 관리 등에 대한 노하우가 부족했다.
  • 로그를 세심하게 확인했다면 문제의 원인을 좀 더 신속히 파악할 수 있었다.
  • 시스템 구성 및 환경 변수 관리를 다수의 인원이 할 경우 누락되는 정보가 발생할 수 있다.
profile
서핑하는 개발자🏄🏽

0개의 댓글