From c0da68e73d485112d120cfbbdffdfcfd8cc362cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=EB=AF=B8?= Date: Tue, 21 Jul 2026 21:54:06 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=EB=B0=B0=ED=8F=AC=20=ED=97=AC?= =?UTF-8?q?=EC=8A=A4=EC=B2=B4=ED=81=AC=EB=A5=BC=20=EA=B3=A0=EC=A0=95=20?= =?UTF-8?q?=ED=83=80=EC=9E=84=EC=95=84=EC=9B=83=20=EB=8C=80=EC=8B=A0=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EA=B8=B0=EB=B0=98=20=EC=99=84=EB=A3=8C=20?= =?UTF-8?q?=EC=8B=A0=ED=98=B8=20=EA=B0=90=EC=A7=80=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존 방식(15초 대기 + 10회x10초 폴링)은 OTel agent 계측으로 부팅 시간이 늘어나면서(3s→20~30s) 정상 배포도 실패로 오판하는 문제가 있었음. 이제 프로세스 생존 여부로 진짜 실패(크래시)를 즉시 감지하고, 살아있는 동안은 Spring Boot가 실제로 찍는 완료 로그("Started ServerApplication")를 기다림. 임의의 타임아웃 추측 대신 실제 이벤트 기반 판단이라 부팅 시간 변동에 안전하고, 5분 상한선은 진짜 행(hang) 상황에 대한 안전장치로만 남김. --- scripts/deploy.sh | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index d708747..f8a2524 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -30,28 +30,51 @@ else echo "> Grafana OTel agent 미설정, 모니터링 없이 실행" fi +LOG_FILE=/home/ec2-user/app/nohup.out +START_LINE=$(wc -l < "$LOG_FILE" 2>/dev/null || echo 0) + nohup java $JAVA_AGENT_OPTS -jar \ -Duser.timezone=Asia/Seoul \ $JAR_PATH \ - >> /home/ec2-user/app/nohup.out 2>&1 & + >> "$LOG_FILE" 2>&1 & +APP_PID=$! +echo "> 프로세스 시작됨 (PID: $APP_PID)" -echo "> 15초 후 헬스체크 시작" -sleep 15 +echo "> 앱 준비 신호 대기 중 (최대 300초, 프로세스 생존 여부로 실패 판단)" +MAX_WAIT=300 +ELAPSED=0 +READY=false -for i in {1..10}; do - RESPONSE=$(curl -s http://localhost:8080/actuator/health || true) - if echo "$RESPONSE" | grep -q '"status":"UP"'; then - echo "> 헬스체크 성공" - break - fi - echo "> 헬스체크 실패($i/10): $RESPONSE" - if [ $i -eq 10 ]; then +while [ $ELAPSED -lt $MAX_WAIT ]; do + if ! kill -0 $APP_PID 2>/dev/null; then + echo "> 프로세스가 예기치 않게 종료됨 (크래시)" + echo "> 최근 로그:" + tail -n 40 "$LOG_FILE" echo "> 배포 실패" exit 1 fi - sleep 10 + + if tail -n +"$((START_LINE + 1))" "$LOG_FILE" | grep -q "Started ServerApplication"; then + echo "> 앱 준비 완료 신호 감지 (${ELAPSED}초 소요)" + READY=true + break + fi + + sleep 2 + ELAPSED=$((ELAPSED + 2)) done +if [ "$READY" != "true" ]; then + echo "> ${MAX_WAIT}초 내에 준비 신호 없음 — 안전장치 발동" + echo "> 최근 로그:" + tail -n 40 "$LOG_FILE" + echo "> 배포 실패" + exit 1 +fi + +RESPONSE=$(curl -s http://localhost:8080/actuator/health || true) +echo "> 헬스체크 확인: $RESPONSE" + echo "> Nginx 시작" sudo systemctl start nginx || true sudo systemctl enable nginx || true From b2a2de2ba0c9885449fdf5e82371ed782730f4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=EB=AF=B8?= Date: Fri, 24 Jul 2026 21:26:14 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=ED=97=AC=EC=8A=A4=EC=B2=B4=ED=81=AC?= =?UTF-8?q?=20=ED=83=80=EC=9E=84=EC=95=84=EC=9B=83=20=EC=97=AC=EC=9C=A0=20?= =?UTF-8?q?=ED=99=95=EB=B3=B4=20+=20curl=20=ED=83=80=EC=9E=84=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MAX_WAIT을 appspec.yml의 AfterInstall 훅 타임아웃(300초)과 정확히 일치시키지 않고 240초로 낮춰서, CodeDeploy의 외부 강제종료가 스크립트 자체의 정상 종료 로직보다 먼저 발동하지 않도록 여유 확보 - 헬스체크 curl에 --max-time 10 추가, 포트가 아직 안 열려있을 때 무한 대기하지 않도록 방어 --- scripts/deploy.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index f8a2524..5fbbbe7 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -40,8 +40,8 @@ nohup java $JAVA_AGENT_OPTS -jar \ APP_PID=$! echo "> 프로세스 시작됨 (PID: $APP_PID)" -echo "> 앱 준비 신호 대기 중 (최대 300초, 프로세스 생존 여부로 실패 판단)" -MAX_WAIT=300 +echo "> 앱 준비 신호 대기 중 (최대 240초, 프로세스 생존 여부로 실패 판단)" +MAX_WAIT=240 ELAPSED=0 READY=false @@ -72,7 +72,7 @@ if [ "$READY" != "true" ]; then exit 1 fi -RESPONSE=$(curl -s http://localhost:8080/actuator/health || true) +RESPONSE=$(curl -s --max-time 10 http://localhost:8080/actuator/health || true) echo "> 헬스체크 확인: $RESPONSE" echo "> Nginx 시작"