[Diary][Spring]GitHub Actions로 단위 테스트 환경 구성하기 (Github Service Container)
본문 바로가기

Development/Diary

[Diary][Spring]GitHub Actions로 단위 테스트 환경 구성하기 (Github Service Container)

CI가 필요한 이유

MSA 프로젝트에서 테스트는 특히 외부 의존성을 많이 사용하게 될 경우 복잡해집니다. Redis, DB, Kafka 등 외부 리소스가 있다면, Mocking이나 다수의 서버 및 컨테이너 구동이 필수적이라, 테스트를 생략하고 PR을 진행하는 경우도 빈번하게 발생합니다. 이 글에서는 GitHub Actions를 통해 실제 개발 환경을 자동으로 구성하여 테스트를 자동화하는 방법을 소개합니다.

문제 상황: gradle build -x test

초기 CI 구성 시에는 gradle build -x test 명령어로 테스트를 건너뛰었다. 외부 Redis, DB, Kafka 등의 의존성이 테스트 중 연결되어야 하는데, 이로 인해 테스트 시 에러가 발생하기 때문이다. 그러나 이렇게 테스트를 생략하면, 서버 실행 후 발생할 수 있는 예외를 미리 확인할 수 없다.

문제 해결: Github actions의 서비스 컨테이너 구성하기

GitHub Actions의 서비스 컨테이너는 워크플로우 내에서 Docker 컨테이너를 이용해 애플리케이션이 필요한 서비스를 호스팅 할 수 있는 기능이다. 이를 통해 Redis, 데이터베이스 등 외부 리소스를 필요로 하는 테스트를 쉽게 설정할 수 있다.

각 워크플로우 단계에 필요한 서비스 컨테이너를 설정하면 실제 개발 및 배포 환경에 맞춘 테스트 환경이 자동으로 구성된다.

GitHub은 워크플로의 각 서비스에 대해 새로운 Docker 컨테이너를 생성하고, 작업이 완료되면 자동으로 삭제하여 리소스를 효율적으로 관리할 수 있다.

 

아래는 mongo, postgreSQL의 서비스 컨테이너를 구성하는 CI 예시이다.

name: Integrated Services Test

on:
  push:
    branches: [ "develop" ]
  pull_request:
    branches: [ "develop" ]

jobs:
  build:

    runs-on: ubuntu-latest
    services:
    
      delivery_db:
        image: mongo:latest
        env:
          MONGO_INITDB_DATABASE: delivery_db
          MONGO_INITDB_ROOT_USERNAME: delivery_db
          MONGO_INITDB_ROOT_PASSWORD: delivery
        ports:
          - 5435:27017

      commerce_db:
        image: postgres:latest
        env:
          POSTGRES_DB: commerce_db
          POSTGRES_USER: commerce_db
          POSTGRES_PASSWORD: commerce
        ports:
          - 5433:5432
        options: >-
          --health-cmd "pg_isready -U commerce_db"
          --health-interval 10s --health-timeout 5s --health-retries 5

    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4
      
      - name: Grant execute permission for Gradle Wrapper in root directory
        run: chmod +x ./gradlew
      
      - name: Build Gradle Project
        run: ./gradlew build -Dspring.profiles.active=dev

 

직접 docker-compose를 사용할 수도 있다.

name: Integrated Docker Services Test

on:
  push:
    branches: [ "develop" ]
  pull_request:
    branches: [ "develop" ]

jobs:
  build:

    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Docker Compose로 서비스 실행
        run: |
          docker compose -f docker/docker-compose.dev.yml up -d
      
      - name: Sleep for 30 seconds
        uses: jakejarvis/wait-action@master
        with:
          time: '30s'
      
      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4
      
      - name: Grant execute permission for Gradle Wrapper in root directory
        run: chmod +x ./gradlew
      
      - name: Build Gradle Project
        run: ./gradlew build -Dspring.profiles.active=dev

위 워크플로우 예시에는 repo에 있는 docker 경로의 docker compose를 실행하는 과정이 포함되어 있다. 이를 통해 쉽게 내 repo에 있는 docker 컨테이너 환경을 구성할 수도 있다.

다만, docker compose를 설치하고 docker 이미지를 다운로드하여 실행하기 때문에 바로 build로 넘어가면 안 될 것 같아 필자는 약 30초 정도의 텀을 주었다.

spring cloud eureka가 먼저 실행되어야 하는 경우?

Eureka의 연결이 필요한 경우, 아래 코드를 추가하여 우선적으로 eureka을 build 하고 실행시켜 줬다.

 - name: Build and Start Eureka Server
        run: |
          cd eureka-server
          chmod +x ./gradlew # Grant execute permission within the eureka-server directory
          ./gradlew bootJar
          nohup java -jar build/libs/eureka-server-0.0.1-SNAPSHOT.jar &
          cd ..
        env:
          SPRING_PROFILES_ACTIVE: dev

(그러면 마지막 단계에서./gradlew build 시 또 한 번 이 eureka를 build 하게 되는데.. 이 부분은 각 build 작업을 서비스 별로 분리해서 진행하는 리팩토링을..)

마치며

서비스 컨테이너 수가 많아질수록 워크플로우는 생각보다 시간이 걸린다. 한 3분 정도 걸리는데, 더 빠르게 단축시킬 수 있는 방법이 없을까 고민하는 중이다.

 

완성된 CI 워크플로우는 아래 링크에서 볼 수 있다.

https://github.com/pickple-ecommerce/backend/tree/develop/.github/workflows

 

backend/.github/workflows at develop · pickple-ecommerce/backend

Contribute to pickple-ecommerce/backend development by creating an account on GitHub.

github.com

 

참조