티스토리 뷰
✏️ 발단
어느 날 GitHub Actions 워크플로우 로그를 들여다보다가 뭔가 이상하다는 걸 느꼈다. 빌드가 매번 2분씩 걸리는데, 체감상 너무 느렸다. 로그를 한 줄씩 따라가다 보니 원인이 눈에 들어왔다. Gradle 빌드가 두 번 실행되고 있었다.
✏️ 원인 분석
당시 CI/CD 파이프라인은 이런 흐름이었다.
deploy.yml에서 JAR를 만들고, 이어서 docker build를 실행하면 Dockerfile 내부에서 Gradle이 다시 처음부터 빌드를 한다. 앞서 만든 JAR는 쓰이지 않는다. 여기에 clean까지 매번 붙어 있어서 Gradle 캐시가 존재해도 전부 날리고 재빌드하는 구조였다. 빌드가 느릴 수밖에 없었다.
멀티스테이지 Dockerfile은 아마 "로컬에서도 docker build 한 방으로 실행되게 하겠다"는 의도로 작성된 것 같다. 하지만 CI/CD 환경에서는 이미 빌드 도구가 갖춰져 있으므로 Docker가 굳이 다시 빌드할 필요가 없다.
# GitHub Actions (deploy.yml)
./gradlew clean build -x test ← JAR 생성
# Dockerfile (Docker 빌드 내부)
FROM gradle:7.5.1-jdk17 AS builder
COPY . .
RUN ./gradlew clean build --no-daemon ← 또 JAR 생성
✏️ 해결 방법
핵심은 간단하다. 빌드는 GitHub Actions에서 한 번만 하고, Docker는 JAR를 복사하기만 한다.
1. Dockerfile 수정
멀티스테이지 빌드를 제거하고 GitHub Actions에서 만든 JAR를 그대로 복사한다. JDK → JRE로 변경한 것도 포인트다. 런타임에는 컴파일러가 필요 없으므로 JRE만으로 충분하고, 덕분에 이미지 크기도 약 200MB 줄었다.
# 변경 전
FROM --platform=linux/amd64 gradle:7.5.1-jdk17 AS builder
WORKDIR /home/gradle/project
COPY --chown=gradle:gradle . .
RUN chmod +x gradlew
RUN ./gradlew clean build --no-daemon
FROM --platform=linux/amd64 eclipse-temurin:17-jdk-alpine
WORKDIR /app
COPY --from=builder /home/gradle/project/build/libs/*.jar app.jar
EXPOSE 9000
ENTRYPOINT ["java", "-jar", "app.jar"]
# 변경 후
FROM --platform=linux/amd64 eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY build/libs/eat-ssu.jar app.jar
EXPOSE 9000
ENTRYPOINT ["java", "-jar", "app.jar"]
2. deploy.yml 수정
clean을 제거해서 Gradle 증분 빌드가 동작하도록 했다. 빌드 산출물 확인 스텝도 추가했는데, 뒤에서 Docker 빌드가 실패할 경우 원인을 빠르게 좁힐 수 있다.# 변경 전
- name: Gradle로 빌드
run: ./gradlew build -x test --no-daemon
# 변경 후
- name: 빌드 산출물 확인
run: ls -lh build/libs/*.jar
3. .dockerignore 수정
Docker 빌드 컨텍스트에 JAR만 포함되도록 설정해야 한다. build/ 전체를 컨텍스트에 올리면 불필요한 파일까지 전송되므로, 필요한 것만 골라낸다. build/ 하위 전체를 제외하되, build/libs/ 디렉토리와 그 안의 JAR 파일만 다시 포함시킨다.
build/*
!build/libs/
!build/libs/*.jar
4. build.gradle 수정
Spring Boot는 기본적으로 실행 가능한 JAR(eat-ssu.jar)와 plain JAR(eat-ssu-plain.jar) 두 개를 생성한다. COPY build/libs/*.jar app.jar처럼 와일드카드로 복사하면 두 파일이 매칭돼 오류가 난다. jar { enabled = false }로 plain JAR 생성을 꺼두면 깔끔하게 해결된다.
jar {
enabled = false
}
✏️ 결과
Github Actions 빌드 시간과, docker의 image 크기가 줄어든 것을 확인할 수 있다.


✏️ 마무리
돌아보면 문제의 원인은 단순했다. CI/CD 환경에 맞지 않는 Dockerfile이 그대로 사용되고 있었던 것이다. 로컬 개발 편의를 위한 멀티스테이지 빌드가 CI에서는 오히려 불필요한 중복 작업을 만들어냈다. 작은 설정 하나가 빌드 시간을 절반으로 줄였다. 비슷한 구조로 되어 있다면 한 번 점검해보길 추천한다.
https://github.com/EAT-SSU/Server/pull/366
fix: GitHub Actions Gradle 중복 빌드 제거 by pooreumjung · Pull Request #366 · EAT-SSU/Server
#️⃣ Issue Number resolved fix: GitHub Actions에서 Gradle 빌드 중복 실행 제거 #365 📝 요약(Summary) Dockerfile에서 Gradle 빌드 단계를 제거하고 GitHub Actions에서 생성된 JAR를 복사하는 방식으로 변경하여 Gradle
github.com
'Back-End > 잇슈' 카테고리의 다른 글
| [EAT-SSU / 잇슈] OAuth 토큰 로그 노출 방지 작업 정리 (0) | 2026.06.23 |
|---|---|
| [EAT-SSU / 잇슈] Docker 배포 스크립트 개선 - 전체 컨테이너 삭제 방지 (0) | 2026.06.23 |
| [EAT-SSU / 잇슈] RDS 데이터 다른 AWS 계정으로 이전하기 (0) | 2026.05.03 |
| [EAT-SSU / 잇슈] DNS 설정 실수로 인한 서버 장애 트러블슈팅 (0) | 2026.04.30 |
| [EAT-SSU / 잇슈] Flyway에서 특정 체크섬을 제거하는 방법 (0) | 2026.01.18 |
- Total
- Today
- Yesterday
- 세그먼트 트리
- 자료구조
- js
- DFS
- 알고리즘 공부
- C++
- java
- C++ Stack
- HTML5
- 유니온 파인드
- CSS
- 백준
- 백준 풀이
- html
- 스택
- 스프링 부트 crud 게시판 구현
- Do it!
- 투 포인터
- 자바
- 알고리즘
- 반복문
- 이분 매칭
- 자바스크립트
- DP
- 카운팅 정렬
- 유클리드 호제법
- BFS
- 우선순위 큐
- 에라토스테네스의 체
- c++ string
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |