스프링 프로젝트 Github action으로 CI 자동화하기

CI(Continuous Integration, 지속적인 통합)란, 개발자가 코드 변경 사항을 커밋할 때마다 자동으로 빌드, 테스트 등을 실행하여 코드의 안정성과 통합성을 검증하는 단계 이다.

main 브랜치에서 push 및 main 브랜치로 pr후 개발자가 직접 테스트를 해주어야 하지만, Github action을 사용하면 자동으로 CI를 해줄 수 있다. 실수로 테스트를 놓치거나 할 가능성이 낮아져서 좋다.

이런 이유로 좀 더 테스트를 잘 작성하는 게 중요한 것 같다.

.github/workflow/ci-test.yml

git action에서 CI 자동화를 하려면, 워크플로우를 작성해주어야 한다. 마법처럼 github가 테스트를 해주지는 않고, 적절한 설정이 필요한 것이다. 현재 내 프로젝트 환경에 맞춰서 yml을 작성해준다.

# 워크플로우 이름을 정의합니다.
name: Java CI with Gradle

# 이 워크플로우가 실행될 조건(이벤트)을 설정합니다.
on:
  # main 브랜치에 코드가 푸시(push)될 때 실행됩니다.
  push:
    branches: [ main ]
  # main 브랜치를 대상으로 하는 pull request가 생성되거나 업데이트될 때 실행됩니다.
  pull_request:
    branches: [ main ]

# 실행할 작업(jobs)을 정의합니다.
jobs:
  # 'build'라는 이름의 작업(job)을 정의합니다.
  build:
    # 이 작업은 최신 Ubuntu 환경에서 실행됩니다.
    runs-on: ubuntu-latest

    # 작업 내에서 순차적으로 실행될 단계(steps)를 나열합니다.
    steps:
      # 리포지토리를 체크아웃(다운로드)하는 단계입니다.
      - name: Checkout repository
        uses: actions/checkout@v3  # GitHub에서 제공하는 checkout 액션을 사용해 소스 코드를 가져옵니다.

      # JDK 17을 설치하고 설정하는 단계입니다.
      - name: Set up JDK 17
        uses: actions/setup-java@v3  # GitHub의 setup-java 액션을 사용해 JDK를 설치합니다.
        with:
          java-version: '17'       # 설치할 자바 버전을 17로 지정합니다.
          distribution: 'temurin'  # Temurin 배포판을 사용하여 JDK를 설치합니다.

      # gradlew 스크립트에 실행 권한을 부여하는 단계입니다.
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew   # gradlew 파일에 실행 권한을 추가합니다.

      # Gradle 명령어를 실행하여 프로젝트를 빌드하고 테스트를 수행하는 단계입니다.
      - name: Build and run tests
        run: ./gradlew clean test  # gradlew를 통해 클린 빌드 후, 테스트를 실행합니다.

로컬 파일 저장 이슈

빌드에 실패했다. 테스트시 중요한 것은, 임베디드 메모리 DB를 사용하고, 무언가에 의존하지 않는 것이 중요하다. 현재 내가 의존하고 있는 게 뭘까 생각해보니, 파일을 저장하는 서비스에서 로컬에 저장하도록 의존하고 있었다.

appication.properties 파일에 저장해둔 file.dir을 가져다가 서비스 계층에서 사용중이다.

file.dir=/Users/kimcheoljun/weblibrary/file/
public class LocalFileStore implements FileStore {

    @Value("${file.dir}")
    private String fileDir;

   ...

    @Override
    public UploadFile storeFile(MultipartFile multipartFile) {
        if (multipartFile.isEmpty()) {
            return null;
        }

        String originalFilename = multipartFile.getOriginalFilename();

        String storeFileName = FileStore.createStoreFileName(originalFilename);

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                try {
                    multipartFile.transferTo(new File(getFullPath(storeFileName)));
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            }
        });

        return new UploadFile(originalFilename, storeFileName);
    }

    ...

}

test/application.properties에서는 다음과 같이 file.dir을 넣어주었다. 이렇게 넣어 주면 빌드가 성공한다.

file.dir=/tmp/test-storage

댓글

개발자  김철준

백엔드 개발자 김철준의 블로그입니다.

주요 프로젝트