♻️ Nginx 리버스 프록시를 제거 - #98
Conversation
|
""" Walkthrough이 변경사항은 프로덕션 및 개발 환경의 GitHub Actions 워크플로우와 Docker Compose 설정에서 Nginx를 제거하고, Spring Boot 서비스를 직접 80번 포트로 노출하도록 수정했습니다. 배포 워크플로우는 사전 테스트 단계를 제거하고, 배포 후 디버깅과 헬스체크를 대폭 강화했습니다. 개발 테스트 워크플로우는 효율성과 캐싱, 리포트 업로드, 환경설정 자동화가 개선되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Developer
participant GitHub Actions
participant RemoteServer
participant Docker
participant SpringBoot
Developer->>GitHub Actions: Push to master/feat/git-master or manual trigger
GitHub Actions->>RemoteServer: SSH 접속 및 배포 스크립트 실행 (동적 브랜치 체크아웃)
RemoteServer->>Docker: docker-compose down --remove-orphans, system prune, up (springboot on :80)
RemoteServer->>SpringBoot: 서비스 시작 및 컨테이너 상태 점검
RemoteServer->>RemoteServer: 배포 후 디버깅 정보 수집 및 컨테이너 내부 테스트 수행
RemoteServer->>RemoteServer: 외부 API 헬스체크 (여러 엔드포인트, 재시도 포함)
GitHub Actions->>GitHub Actions: 배포 결과 요약 및 보고
Possibly related PRs
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
.github/workflows/dev-test.yml (2)
36-43: Elasticsearch JVM 옵션 축소만으로는 CI 메모리 OOM 을 완전히 방지하지 못할 수 있습니다
-Xms256m -Xmx256m으로 조정했지만 GitHub Hosted 러너의 기본 메모리 제한(7 GB) 내에서 여전히vm.max_map_count커널 파라미터가 낮아 ES 기동 실패가 자주 발생합니다.
bootstrap.memory_lock=false,indices.memory.index_buffer_size=10%등을 추가하거나, 테스트용으로 Elastic 공식 lightweight 이미지elasticsearch:8.13.0-jdk-alpine사용을 고려해 주세요.
94-161: 대형application-test.properties인라인 생성은 유지보수성이 떨어집니다
워크플로마다 긴cat <<EOF블록을 복사-붙여넣기하면 값 변경 시 실수 확률이 높습니다.제안:
SpringBoot/src/test/resources/application-test.properties파일로 이동하여 Git 버전 관리 ↔ 워크플로우에서는cp만 수행- 또는
--from-env-file방식으로.env.test를 읽도록 Spring 설정 리팩터이를 통해 IDE-지원, 리뷰 diff, 재사용성이 개선됩니다.
.github/workflows/deploy-prod.yml (1)
98-111: 네트워크 이름 하드코딩으로 인한 실패 가능성
docker network inspect news-deliver_backend는docker-compose프로젝트명이 디렉터리 또는COMPOSE_PROJECT_NAME에 따라 달라질 때 실패합니다.
아래처럼 동적으로 가져오거나 무시해도 무방한 진단 단계로 변경하세요.NETWORK=$(docker network ls --format '{{.Name}}' | grep '_backend$' | head -n1) [ -n "$NETWORK" ] && docker network inspect "$NETWORK"
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.github/workflows/deploy-prod.yml(2 hunks).github/workflows/dev-test.yml(4 hunks)docker-compose.yml(1 hunks)nginx/nginx.conf(0 hunks)
💤 Files with no reviewable changes (1)
- nginx/nginx.conf
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/dev-test.yml
[error] 67-67: trailing spaces
(trailing-spaces)
[error] 73-73: trailing spaces
(trailing-spaces)
[error] 84-84: trailing spaces
(trailing-spaces)
[error] 89-89: trailing spaces
(trailing-spaces)
[error] 100-100: trailing spaces
(trailing-spaces)
[error] 106-106: trailing spaces
(trailing-spaces)
[error] 112-112: trailing spaces
(trailing-spaces)
[error] 120-120: trailing spaces
(trailing-spaces)
[error] 123-123: trailing spaces
(trailing-spaces)
[error] 128-128: trailing spaces
(trailing-spaces)
[error] 139-139: trailing spaces
(trailing-spaces)
[error] 143-143: trailing spaces
(trailing-spaces)
[error] 146-146: trailing spaces
(trailing-spaces)
[error] 149-149: trailing spaces
(trailing-spaces)
[error] 155-155: trailing spaces
(trailing-spaces)
[error] 158-158: trailing spaces
(trailing-spaces)
[error] 191-191: trailing spaces
(trailing-spaces)
.github/workflows/deploy-prod.yml
[error] 38-38: trailing spaces
(trailing-spaces)
[error] 44-44: trailing spaces
(trailing-spaces)
[error] 48-48: trailing spaces
(trailing-spaces)
[error] 51-51: trailing spaces
(trailing-spaces)
[error] 54-54: trailing spaces
(trailing-spaces)
[error] 63-63: trailing spaces
(trailing-spaces)
[error] 67-67: trailing spaces
(trailing-spaces)
[error] 70-70: trailing spaces
(trailing-spaces)
[error] 73-73: trailing spaces
(trailing-spaces)
[error] 76-76: trailing spaces
(trailing-spaces)
[error] 79-79: trailing spaces
(trailing-spaces)
[error] 82-82: trailing spaces
(trailing-spaces)
[error] 91-91: trailing spaces
(trailing-spaces)
[error] 97-97: trailing spaces
(trailing-spaces)
[error] 100-100: trailing spaces
(trailing-spaces)
[error] 103-103: trailing spaces
(trailing-spaces)
[error] 107-107: trailing spaces
(trailing-spaces)
[error] 111-111: trailing spaces
(trailing-spaces)
[error] 119-119: trailing spaces
(trailing-spaces)
[error] 128-128: trailing spaces
(trailing-spaces)
[error] 137-137: trailing spaces
(trailing-spaces)
[error] 146-146: trailing spaces
(trailing-spaces)
[error] 155-155: trailing spaces
(trailing-spaces)
[error] 161-161: trailing spaces
(trailing-spaces)
[error] 164-164: trailing spaces
(trailing-spaces)
[error] 170-170: trailing spaces
(trailing-spaces)
[error] 177-177: trailing spaces
(trailing-spaces)
[error] 179-179: trailing spaces
(trailing-spaces)
[error] 182-182: trailing spaces
(trailing-spaces)
[error] 185-185: trailing spaces
(trailing-spaces)
[error] 189-189: trailing spaces
(trailing-spaces)
[error] 193-193: trailing spaces
(trailing-spaces)
[error] 195-195: trailing spaces
(trailing-spaces)
[error] 206-206: trailing spaces
(trailing-spaces)
[error] 212-212: trailing spaces
(trailing-spaces)
[error] 239-239: no new line character at the end of file
(new-line-at-end-of-file)
🔇 Additional comments (2)
docker-compose.yml (1)
27-29: docker-compose.yml 27–29: 호스트 포트 80 매핑 권한·충돌 검토 요청
다음 사항을 확인해주세요:
- 동일 호스트에서 80번 포트를 이미 사용 중인 서비스(Nginx, Certbot 등)와의 충돌 가능성
- rootless Docker 또는 비-root 계정 환경에서 80번 이하 포트 바인딩 제한 여부
대안 예시:
- - "80:8080" + - "${HOST_HTTP_PORT:-8080}:8080" # 기본값 8080, 필요 시 .env로 재정의.github/workflows/deploy-prod.yml (1)
174-222:success플래그 논리 오류 가능성
초기화success=false이후 루프 내부에서success=true로 설정해도,
break 2로 빠져나오면 외부 for-loop만 탈출하고success가 문자열"true"여야 합니다.
그러나 Bash에서는 공백·따옴표 실수로"true"가 아닌true(명령) 로 평가되면[ "$success" = true ]비교가 실패할 수 있습니다. 안전하게 고정 문자열 사용을 권장합니다.-success=false +success="false" ... - success=true + success="true" ... -if [ "$success" = true ]; then +if [ "$success" = "true" ]; thenLikely an incorrect or invalid review comment.
| - name: 서비스 준비 대기 (최적화) | ||
| run: | | ||
| echo "⏳ Dev 테스트 환경 준비 중..." | ||
|
|
||
| # 병렬로 서비스 상태 확인 | ||
| wait_for_service() { | ||
| local service_name=$1 | ||
| local check_cmd=$2 | ||
| local max_attempts=$3 | ||
|
|
||
| for i in $(seq 1 $max_attempts); do | ||
| if eval "$check_cmd" >/dev/null 2>&1; then | ||
| echo "✅ $service_name 준비 완료" | ||
| return 0 | ||
| fi | ||
| sleep 1 | ||
| done | ||
| echo "❌ $service_name 준비 실패" | ||
| return 1 | ||
| } | ||
|
|
||
| # 병렬 서비스 체크 (시간 단축) | ||
| wait_for_service "MySQL" "mysqladmin ping -h127.0.0.1 -P3306 -uroot -ptestpass --silent" 10 & | ||
| wait_for_service "Redis" "redis-cli -h 127.0.0.1 -p 6379 ping | grep -q PONG" 8 & | ||
| wait_for_service "Elasticsearch" "curl -f http://localhost:9200/_cluster/health" 15 & | ||
|
|
||
| # 모든 백그라운드 작업 완료 대기 | ||
| wait | ||
| echo "✅ 모든 서비스 준비 완료" | ||
|
|
There was a problem hiding this comment.
wait 종료 코드를 덮어써 서비스 준비 실패가 숨겨집니다
wait 명령 이후 바로 echo 를 실행해버려 실패 시(비 0)에도 스텝이 성공으로 처리됩니다.
wait # 종료코드 보존 필요
echo "...완료" # 이 echo 로 exit code 0 으로 덮임아래처럼 종료코드를 확인하여 실패를 전파하도록 수정하세요.
- wait
- echo "✅ 모든 서비스 준비 완료"
+ wait
+ status=$?
+ if [ $status -ne 0 ]; then
+ echo "❌ 일부 서비스 준비 실패"
+ exit $status
+ fi
+ echo "✅ 모든 서비스 준비 완료"🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 67-67: trailing spaces
(trailing-spaces)
[error] 73-73: trailing spaces
(trailing-spaces)
[error] 84-84: trailing spaces
(trailing-spaces)
[error] 89-89: trailing spaces
(trailing-spaces)
🤖 Prompt for AI Agents
In .github/workflows/dev-test.yml around lines 64 to 93, the script uses 'wait'
to wait for background service checks but immediately echoes a success message
without checking the exit status of 'wait', causing failures to be hidden.
Modify the script to capture the exit code of 'wait' into a variable, then
conditionally echo the success message only if all services are ready, and exit
with the captured code to propagate any failure.
| # 기존 컨테이너 정리 | ||
| docker-compose down --remove-orphans --timeout 30 || true | ||
| docker system prune -f || true | ||
|
|
||
| # 새 컨테이너 시작 | ||
| docker-compose up -d --build --force-recreate | ||
|
|
||
| echo "⏳ 컨테이너 시작 대기 (90초)..." | ||
| sleep 90 | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
고정 sleep 90 대신 헬스체크 기반 대기 로직으로 교체 권장
컨테이너 부트 시간은 환경·네트워크에 따라 달라집니다. 90 초 하드코딩은
- 과도하게 길어 CI 시간을 낭비하거나
- 반대로 불충분하여 이후 단계가 실패할 수 있습니다.
dev-test 워크플로우에 구현한 wait_for_service 함수를 재사용해 Spring Boot /actuator/health 등을 폴링하도록 리팩터링하면 안정성과 속도를 모두 확보할 수 있습니다.
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 48-48: trailing spaces
(trailing-spaces)
[error] 51-51: trailing spaces
(trailing-spaces)
[error] 54-54: trailing spaces
(trailing-spaces)
🤖 Prompt for AI Agents
In .github/workflows/deploy-prod.yml around lines 45 to 54, replace the fixed
'sleep 90' wait with a health check polling mechanism like the
'wait_for_service' function used in the dev-test workflow. This involves
implementing a loop that repeatedly checks the Spring Boot /actuator/health
endpoint until it reports healthy or a timeout occurs, ensuring the container is
fully ready before proceeding. This change improves reliability and reduces
unnecessary wait time by dynamically waiting based on actual service readiness
instead of a fixed delay.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
docker-compose.yml (2)
30-32: 호스트 timezone 파일 마운트는 플랫폼 의존성이 높습니다
/etc/localtime,/etc/timezone를 읽기 전용으로 마운트하면 리눅스 배포판에서는 문제없지만 macOS Docker Desktop, Windows WSL2 등에서는 해당 경로가 존재하지 않아 Compose가 바로 실패합니다.
- 컨테이너 내부
ENV TZ=Asia/Seoul만으로도 대부분의 애플리케이션-레벨 시간대 처리가 충분합니다.- 멀티 플랫폼 배포가 예상된다면 마운트 제거를 고려하거나
condition: ${HOST_TZ_MOUNT:-false}같은 옵션화가 좋습니다.
160-160: EOF 개행 누락
YAML lint가 경고하듯 파일 끝에 개행이 없습니다. 일부 CI 툴이나 diff 툴에서 경미한 이슈를 일으킬 수 있으므로 한 줄 추가해 두는 편이 좋습니다.- driver: bridge + driver: bridge +
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
SpringBoot/Dockerfile(1 hunks)docker-compose.yml(6 hunks)
✅ Files skipped from review due to trivial changes (1)
- SpringBoot/Dockerfile
🧰 Additional context used
🪛 YAMLlint (1.37.1)
docker-compose.yml
[error] 160-160: no new line character at the end of file
(new-line-at-end-of-file)
🔇 Additional comments (2)
docker-compose.yml (2)
29-32: 호스트 포트 80 바인딩 시 권한·포트 충돌 및 헬스체크 누락 확인 필요
Nginx를 제거하면서springboot컨테이너를 곧바로80:8080으로 매핑했습니다.
- Docker Compose를 root가 아닌 계정으로 실행할 경우 호스트의 80 포트는 커널-레벨 권한이 필요해 실패할 수 있습니다.
- 동일 호스트에서 다른 서비스(예: 기존 웹 서버, Certbot)와 포트 충돌 가능성을 반드시 점검하세요.
- Nginx가 담당하던 TLS 종료 지점이 사라졌으므로, Load Balancer나 Spring Boot 내부에서 HTTPS 처리를 어떻게 할지 운영 관점에서 재설계가 필요합니다.
springboot서비스에는 healthcheck가 정의돼 있지 않아depends_on의condition: service_healthy체인이 끊깁니다. 최소한 Actuator 엔드포인트를 이용해 헬스체크를 추가하는 것을 권장합니다.+ healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] + interval: 10s + timeout: 5s + retries: 5
54-55: MySQL--default-time-zone=+09:00설정이 컨테이너 TZ와 불일치할 가능성
컨테이너에는TZ=Asia/Seoul(KST)이 설정돼 있지만 MySQL은+09:00오프셋을 직접 지정했습니다. 서머타임이 없어 현재로선 동일하지만, 명시적 지역 이름을 쓰면 가독성과 유지보수가 더 쉽습니다.- command: ["mysqld", "--default-time-zone=+09:00"] + command: ["mysqld", "--default-time-zone=Asia/Seoul"]변경 전·후 쿼리 결과(
SELECT @@global.time_zone;)가 기대와 일치하는지 한 번 더 확인해 주세요.
Nginx 리버스 프록시를 제거하고 Spring Boot 애플리케이션이 직접 80번 포트로 서비스되도록 아키텍처를 단순화했습니다.
🌐 Docker 컨테이너 한국 시간대 설정
📋 변경 사항
🔧 수정된 파일
SpringBoot/Dockerfile: 시간대 설정 추가docker-compose.yml: 모든 서비스에 TZ 환경변수 및 볼륨 마운트 추가Summary by CodeRabbit