Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 요약 (Walkthrough)프로덕션 환경을 위한 Spring Boot 설정 파일과 GitHub Actions CI/CD 워크플로우를 추가합니다. 프로덕션 프로필 설정, 개발/프로덕션 배포 파이프라인, 서브모듈 업데이트를 포함하여 멀티 환경 배포 인프라를 구성합니다. 변경 사항 (Changes)
예상 코드 리뷰 난이도 (Estimated code review effort)🎯 3 (보통) | ⏱️ ~20분
관련 PR (Possibly related PRs)
제안 레이블 (Suggested labels)
축하 시 (Poem)
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
.github/workflows/ci.yml (1)
29-63: 아티팩트 업로드 구성을 확인하세요.
build/libs/*.jar및Dockerfile이 업로드되고 있으나, CD 워크플로우가 이를 성공적으로 다운로드할 수 있도록download-artifact단계의 구성과 일치하는지 확인하십시오. 또한 아티팩트 보관 기간이 설정되지 않은 경우 저장소 용량 누적을 고려하여 명시적으로 설정하는 것이 좋습니다.아티팩트 구성을 명확히 하기 위해 다음을 추가하세요:
- name: Upload Build Artifacts uses: actions/upload-artifact@v4 with: name: build-libs + retention-days: 1 path: | build/libs/*.jar Dockerfile
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.github/workflows/cd.yml(2 hunks).github/workflows/ci.yml(2 hunks)src/main/resources/application-prod.yml(1 hunks)src/main/resources/application.yml(1 hunks)src/main/resources/security(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (5)
src/main/resources/security (1)
1-1: Based on my investigation, I've confirmed the key findings. The security submodule repository referenced in.gitmodules(https://github.com/Geumpumta/backend-security.git) is not accessible through public GitHub APIs or web access. The backend repository itself is public, so this suggests the security submodule is either private, doesn't exist, or the URL is incorrect.Here is the rewritten review comment:
Security submodule update cannot be verified — submodule repository is not accessible
The submodule pointer has been updated from
fd01d78390303b12d3459d9db53578fb16bc53cato24fc3c905e4cc5f26e4140bbc7d4da51ec14ea44, but the referenced repository (https://github.com/Geumpumta/backend-security.git) is not publicly accessible. Unable to verify:
- What changes were introduced in the submodule
- Compatibility with new production configuration (
application-prod.yml, production workflows)- Any breaking changes or security implications
- Alignment with production CI/CD objectives
Action required: Verify the submodule changes directly in the backend-security repository or provide documentation of what changed in this update.
.github/workflows/ci.yml (1)
1-7: 워크플로우 트리거 및 이름이 Prod 환경에 올바르게 정렬되어 있습니다.CI 워크플로우가
prod브랜치에서만 트리거되도록 변경되었으며, CD 워크플로우에서 이 워크플로우를 참조할 때 일관성이 유지됩니다 (cd.yml 라인 5).src/main/resources/application-prod.yml (1)
1-11: 프로필 그룹 및 임포트 구조가 명확합니다.보안 및 애플리케이션 설정 모듈을 프로필별로 분리하는 것이 좋습니다. 그러나 이러한 파일들(security/application-*.yml)이 존재하고 변수(
geumpumta.mysql.*,geumpumta.redis.*)가 배포 환경에서 설정되는지 확인하세요.다음을 확인하세요:
- 모든 임포트된 파일이 존재하는가
- 환경 변수
geumpumta.mysql.url,geumpumta.mysql.username,geumpumta.mysql.password,geumpumta.redis.host,geumpumta.redis.port,geumpumta.redis.password가 CD 파이프라인에서 설정되는가.github/workflows/cd.yml (2)
1-16: 프로덕션 CD 워크플로우 트리거 및 환경 설정이 올바르게 구성되어 있습니다.워크플로우가
prod브랜치의 성공적인 CI 완료 후에만 실행되도록 제한되며, GitHub Environment를 통해 프로덕션 환경 변수를 분리하여 관리합니다. 이는 환경 간 설정 분리 목표와 일치합니다.
62-78: Verify that database and Redis configuration variables are properly injected into the container.The CD workflow correctly uses
productionGitHub Environment withsecrets.WEB_PORTandvars.NETWORK_NAME(lines 91, 90). However, the docker run command (lines 88-94) only setsSPRING_PROFILES_ACTIVE=prodand does not explicitly inject the database and Redis connection variables that the application requires:
application-prod.ymlreferences${geumpumta.mysql.url},${geumpumta.mysql.username},${geumpumta.mysql.password},${geumpumta.redis.host},${geumpumta.redis.port}, and${geumpumta.redis.password}- These variables must be available at runtime either via environment variables, self-hosted runner configuration, or GitHub Secrets/Vars
Ensure one of the following:
- Add
-eflags to the docker run command to inject these variables (e.g.,-e GEUMPUMTA_MYSQL_URL=${{ secrets.GEUMPUMTA_MYSQL_URL }})- Or verify these variables are pre-configured on the self-hosted runner environment
- Or configure them in the
productionGitHub Environment if using that approach
.github/workflows/prod-cd.yml
Outdated
| - name: Clean up old container and image | ||
| run: | | ||
| docker rm -f ${{ vars.CONTAINER_NAME }} || true | ||
| docker images "ghcr.io/${{ github.repository }}" \ | ||
| --format "{{.Repository}}:{{.Tag}}" \ | ||
| | grep -v "${{ needs.build.outputs.image-tag }}" \ | ||
| | xargs -r docker rmi -f || true | ||
| docker image prune -f | ||
|
|
||
| # 새로운 이미지로 새로운 컨테이너 생성하여 실행 | ||
| - name: Run New Container | ||
| - name: Run New Container (Prod) | ||
| run: | | ||
| docker run -d \ | ||
| --name ${{ vars.CONTAINER_NAME }} \ | ||
| --network ${{ vars.NETWORK_NAME }} \ | ||
| -p ${{ secrets.DEV_WEB_PORT }}:8080 \ | ||
| -e SPRING_PROFILES_ACTIVE=dev \ | ||
| -p ${{ secrets.WEB_PORT }}:8080 \ | ||
| -e SPRING_PROFILES_ACTIVE=prod \ | ||
| -e TZ=Asia/Seoul \ | ||
| ${{ needs.build.outputs.image-tag }} | ||
| ${{ needs.build.outputs.image-tag }} |
There was a problem hiding this comment.
Docker 이미지 정리 및 컨테이너 배포 구성을 개선하세요.
현재 설정의 잠재적 문제:
-
이미지 정리 (라인 84):
docker image prune -f는 모든 미사용 이미지를 삭제합니다. 여러 애플리케이션이 같은 호스트에서 실행 중인 경우 의도치 않게 다른 애플리케이션의 이미지를 삭제할 수 있습니다. -
컨테이너 재시작 정책 부재: 컨테이너가 중단되었을 때 자동으로 다시 시작되도록 설정하지 않았습니다.
-
배포 실패 처리:
docker run실패 시 워크플로우가 계속 진행될 수 있습니다.
다음과 같이 개선하세요:
- name: Clean up old container and image
run: |
docker rm -f ${{ vars.CONTAINER_NAME }} || true
- docker image prune -f
+ docker image prune -f --filter "until=72h"
- name: Run New Container (Prod)
run: |
docker run -d \
--name ${{ vars.CONTAINER_NAME }} \
--network ${{ vars.NETWORK_NAME }} \
+ --restart unless-stopped \
-p ${{ secrets.WEB_PORT }}:8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-e TZ=Asia/Seoul \
${{ needs.build.outputs.image-tag }}
+ set -eCommittable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In .github/workflows/cd.yml around lines 81 to 94, tighten image cleanup and
make deployment safer: replace the broad `docker image prune -f` with a scoped
cleanup (e.g., prune only dangling images with `docker image prune -f --filter
"dangling=true"` or remove the previous release image by name/tag) so other
apps' images aren’t removed; add a restart policy to the docker run command
(`--restart unless-stopped`) so the container is automatically restarted on
failure; and ensure the run step fails the workflow on error by removing any `||
true` suppression and enabling exit-on-error at the top of the run script (e.g.,
`set -e`) so a failed `docker run` stops the job.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
.github/workflows/prod-cd.yml (1)
81-94: Docker 이미지 정리 및 컨테이너 배포 안전성을 개선하세요.현재 설정에 세 가지 중대한 문제가 있습니다:
광범위한 이미지 정리 (84줄):
docker image prune -f는 모든 미사용 이미지를 삭제합니다. 호스트에서 여러 애플리케이션이 실행 중이면 다른 앱의 이미지도 의도치 않게 삭제될 수 있습니다.컨테이너 재시작 정책 부재: 컨테이너가 중단되면 자동으로 다시 시작되지 않습니다.
에러 처리 부재:
docker run실패 시 워크플로우가 계속 진행될 수 있습니다.필터(--filter)를 사용하여 정확히 제어할 수 있습니다. 다음과 같이 개선하세요:
- name: Clean up old container and image run: | + set -e docker rm -f ${{ vars.CONTAINER_NAME }} || true - docker image prune -f + docker image prune -f --filter "until=72h" - name: Run New Container (Prod) run: | docker run -d \ --name ${{ vars.CONTAINER_NAME }} \ --network ${{ vars.NETWORK_NAME }} \ + --restart unless-stopped \ -p ${{ secrets.WEB_PORT }}:8080 \ -e SPRING_PROFILES_ACTIVE=prod \ -e TZ=Asia/Seoul \ ${{ needs.build.outputs.image-tag }}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.github/workflows/dev-cd.yml(1 hunks).github/workflows/dev-ci.yml(1 hunks).github/workflows/prod-cd.yml(2 hunks).github/workflows/prod-ci.yml(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (6)
.github/workflows/prod-ci.yml (2)
1-49: 프로덕션 CI 워크플로우가 잘 구성되었습니다.메인 브랜치로 트리거, 필요한 권한 설정, Redis 헬스 체크, 그리고 의존성 캐싱 등이 모두 적절히 구성되어 있습니다.
60-63: Dockerfile를 아티팩트에 포함한 점이 좋습니다.프로덕션 CD 워크플로우에서 이미지를 빌드하는 데 필요하므로 이 설정이 필수적입니다.
.github/workflows/prod-cd.yml (1)
1-20: GitHub Environment와 workflow_run 트리거가 올바르게 구성되었습니다.프로덕션 환경 변수 주입과 CI 성공 시에만 배포하는 조건이 적절합니다.
.github/workflows/dev-cd.yml (1)
13-33: 아티팩트 다운로드 및 이미지 태그 추출 패턴이 적절합니다.
workflow_run이벤트 간 데이터 전달을 위해 파일 기반 아티팩트를 사용하는 방식이 올바릅니다..github/workflows/dev-ci.yml (2)
1-60: 개발 CI 워크플로우의 기본 구조가 잘 설계되었습니다.JDK 21, Gradle 캐싱, Redis 헬스 체크, 권한 설정 등이 모두 적절합니다.
94-102: 이미지 태그를 파일로 내보내고 아티팩트로 전달하는 방식이 우수합니다.
workflow_run이벤트를 통한 워크플로우 간 통신에서 이 패턴은 표준적이고 신뢰할 수 있는 방식입니다.
.github/workflows/dev-cd.yml
Outdated
| - name: Clean up old container | ||
| run: | | ||
| docker rm -f ${{ vars.CONTAINER_NAME }} || true | ||
| docker image prune -f | ||
|
|
||
| - name: Run New Container (Dev) | ||
| run: | | ||
| docker run -d \ | ||
| --name ${{ vars.CONTAINER_NAME }} \ | ||
| --network ${{ vars.NETWORK_NAME }} \ | ||
| -p ${{ secrets.WEB_PORT }}:8080 \ | ||
| -e SPRING_PROFILES_ACTIVE=dev \ | ||
| -e TZ=Asia/Seoul \ | ||
| ${{ steps.get-tag.outputs.IMAGE_TAG }} No newline at end of file |
There was a problem hiding this comment.
Docker 이미지 정리 및 컨테이너 배포를 개선하세요.
개발 환경에서도 동일한 안전성 개선이 필요합니다:
- 광범위한 이미지 정리:
docker image prune -f가 다른 컨테이너 이미지를 삭제할 수 있습니다. - 컨테이너 재시작 정책 부재: 장애 발생 시 자동 복구 기능이 없습니다.
- 에러 처리 부재: 배포 실패가 워크플로우 실패로 이어지지 않습니다.
다음 diff를 적용하세요:
- name: Clean up old container
run: |
+ set -e
docker rm -f ${{ vars.CONTAINER_NAME }} || true
- docker image prune -f
+ docker image prune -f --filter "until=72h"
- name: Run New Container (Dev)
run: |
docker run -d \
--name ${{ vars.CONTAINER_NAME }} \
--network ${{ vars.NETWORK_NAME }} \
+ --restart unless-stopped \
-p ${{ secrets.WEB_PORT }}:8080 \
-e SPRING_PROFILES_ACTIVE=dev \
-e TZ=Asia/Seoul \
${{ steps.get-tag.outputs.IMAGE_TAG }}🤖 Prompt for AI Agents
.github/workflows/dev-cd.yml lines 45-58: the workflow currently runs a broad
docker image prune, lacks a container restart policy, and swallows errors which
prevents CI from failing on real deployment problems; change the image prune to
only remove dangling images (e.g. docker image prune -f --filter
"dangling=true"), add a restart policy to the docker run command (e.g. --restart
unless-stopped), and make error handling strict by removing the unconditional
silencing (replace the current docker rm -f ... || true with a check that only
skips removal when the container is absent, or run a conditional existence check
before removal) so genuine failures cause the workflow to fail.
🚀 1. 개요
📝 2. 주요 변경 사항
1. 🐳 Docker 인프라 분리 (Port & Volume 격리)
기존
docker-compose.yml을 용도에 따라 두 개로 분리하고, 포트와 데이터 경로를 격리하여 동시 실행이 가능하도록 했습니다.docker-compose.prod.yml3311, Redis:6379geumpumta-net-proddocker-compose.dev.yml3313(기존 3312 충돌 해결), Redis:6381geumpumta-net-dev./docker-infra/mysql-dev등 별도 경로 사용2. 🍃 Spring Boot 설정 분리
application.yml에서 프로필별로 바라보는 DB 주소를 분리하여, 로컬 개발 시 실수로 운영 DB에 접속하는 사고를 방지했습니다.local:localhost:3313(개발 서버의 Dev DB 포트 사용)dev: Docker 내부망mysql-geumpumta-devprod: Docker 내부망mysql-geumpumta-prod3. 🚀 CI/CD 파이프라인 고도화 (4-Tier 구조)
기존 단일 워크플로우를4개의 파일로 분리하고, GitHub Environments를 도입했습니다.
dev-ci.yml/prod-ci.yml: 빌드 및 테스트, Docker 이미지 생성 (Artifact로 태그 전달)dev-cd.yml/prod-cd.yml:workflow_run으로 CI 성공 시 트리거, 환경 변수 주입 및 배포upload/download-artifact로직 추가development,production)의WEB_PORT,NETWORK_NAME변수를 사용하여 스크립트 재사용성 증대docker image prune -f를 사용하여 롤백 가능성을 열어두고 안전하게 구버전 이미지 정리4. 🌐 Nginx 리버스 프록시 분리
외부 요청을 각 환경에 맞는 컨테이너로 연결하도록 Upstream 포트를 분리했습니다.
geumpumta.shop→ 32123 (Prod Container)dev.geumpumta.shop→ 32124 (Dev Container)Summary by CodeRabbit
릴리스 노트
새로운 기능
Chores
✏️ Tip: You can customize this high-level summary in your review settings.