MODDO - Dockerfile 환경에서 Testcontainers 테스트 실패 원인 정리

원지윤·2025년 6월 10일
0

MODDO 프로젝트

목록 보기
4/4
post-thumbnail

🐹 MODDO란?

'모또’는 모임 정산 과정에서 발생하는 정산 지연등의 여러 문제에 대한 총무의 부담을 줄이기 위해 게이미피케이션 요소를 더하여 모임원들의 적극적인 정산 참여를 유도하는 서비스입니다.

✨ 주요 기능

👥 모임을 생성하고 모임에 참여했던 인원을 등록해요!

  • 모임의 이름과 참여자를 입력하면 더 간편하게 지출 내역을 입력할 수 있습니다.
  • 모임 구성원을 한눈에 확인하고 관리할 수 있습니다.

💵 모임에서 사용했던 지출내역을 간편하게 정리해요!

  • 사용했던 지출 내역을 각 차수(위치)별로 구분하여 쉽게 입력할 수 있습니다. - 지출 내역 입력 시 참여자를 자유롭게 추가/제외할 수 있고, 참여자별 사용 금액을 1/N로 구분할 수 있습니다.

🔗 모임의 지출내역을 공유하고 확인해요!

  • 작성한 정산 내역을 링크와 QR코드로 모임 참여자들에게 편리하게 공유할 수 있습니다.
  • 공유된 페이지에서는 참여자별, 차수(위치)별 지출내역을 한눈에 확인할 수 있어 투명한 정산이 가능합니다.
  • 입금 마감 시간과 입금 현황을 프로그레스바로 표시하여 모임의 정산 진행 상태를 쉽게 파악할 수 있습니다.

🚨 문제 상황

Spring REST Docs와 Redis 기반 캐시를 도입한 뒤 서버 배포 과정에서 테스트 실패로 인해 배포가 중단되는 문제가 발생했습니다.

🔎 원인 분석 과정

처음에는 "왜 Redis 테스트에서만 실패하지?"라는 의문이 들었습니다. 새로 추가된 부분과 Spring REST Docs 설정을 살펴봤지만 설정 자체에는 특별한 문제가 없어 보였습니다. 혹시 Redis를 테스트하기 위해 도입한 Testcontainers 쪽 이슈가 아닌지 의심하며 여러 가능성을 테스트했습니다.

이 과정에서 Dockerfile로 배포할 때 ./gradlew bootJar를 실행하면 테스트가 실패한다는 사실을 알게 됐습니다. 그래서 혹시 명시적으로 테스트를 실행하면 다를까 싶어 Dockerfile에 ./gradlew test를 추가해봤지만 역시 동일하게 실패했습니다.

🧩 핵심 원인 파악

여기서 "왜 로컬이나 CI에서는 통과하던 테스트가 Dockerfile 빌드 환경에서는 실패하지?"라는 의문이 들었고 원인을 추적하다가 Docker 컨테이너 내부에서 Testcontainers가 Redis 컨테이너를 띄우려고 할 때 호스트의 Docker 데몬에 접근할 수 없다는 사실을 알게 되었습니다.

GitHub Actions와 같은 CI 환경에서는 호스트의 Docker 데몬에 접근할 수 있어서 Testcontainers 기반 테스트가 정상적으로 동작합니다.
하지만 Dockerfile에서 ./gradlew bootJar를 실행할 때는 Docker 컨테이너 내부에서 다시 Docker 컨테이너(Testcontainers로 띄우는 Redis 등)를 실행해야 하는 상황이 됩니다.
이런 구조를 "Docker in Docker"라고 하는데 일반적인 Docker 빌드 환경에서는 도커 내부에 도커가 설치되어 있지 않기 때문에 Testcontainers가 동작하지 않고 이로 인해 테스트가 실패하게 되는 것입니다.


🛠️ 해결 방법

이 문제를 해결하기 위해 기존에는 Dockerfile에서 빌드와 테스트 실행 환경을 모두 처리했지만 아래와 같이 워크플로우를 분리했습니다.


기존 Dockerfile (문제 발생)

# 1단계: 빌드 환경 (Gradle 빌드)
FROM gradle:7.4.2-jdk17 AS builder


WORKDIR /app
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .

RUN chmod +x ./gradlew
RUN ./gradlew dependencies

COPY src src
RUN ./gradlew bootJar --no-daemon

# 2단계: 실행 환경 (최종 실행 이미지만 남김)
FROM openjdk:17-jdk-slim

WORKDIR /app
COPY --from=builder /app/build/libs/*.jar /app/moddo.jar
ENTRYPOINT ["java", "-Dspring.profiles.active=prod", "-jar", "moddo.jar"]

이 방식에서는 빌드 단계에서 테스트가 실행되어야 하는데 Docker 컨테이너 내부에서 Testcontainers가 동작하지 않아 실패합니다.


개선된 CI/CD 워크플로우

...
- name: Run tests (Testcontainers, Spring REST Docs)
	run: ./gradlew test --no-daemon

- name: Build JAR
	run: ./gradlew bootJar -x test
...

개선된 Dockerfile

# 실행 환경 (최종 실행 이미지만 남김)
FROM openjdk:17-jdk-slim

WORKDIR /app
COPY build/libs/*.jar /app/moddo.jar
ENTRYPOINT ["java", "-Dspring.profiles.active=prod", "-jar", "moddo.jar"]

이렇게 빌드와 테스트는 CI(GitHub Actions)에서 미리 수행하고 Dockerfile에서는 빌드된 JAR 파일만 복사해서 실행 환경만 구성하도록 분리했습니다. 이로써 Docker 빌드 단계에서 Testcontainers가 동작하지 않아 발생하던 테스트 실패 문제를 해결할 수 있었습니다.

0개의 댓글