Conversation
pkill 패턴이 실제 프로세스를 한 번도 잡지 못했다. 컨테이너 안 cmdline 은
npm exec serve -s /workspace/app/dist -l 3000
node /root/.npm/_npx/<hash>/node_modules/.bin/serve -s /workspace/app/dist -l 3000
이라 리터럴 'npx serve' 가 없다. 대신 그 pkill 을 실행하는 sh -c 자신의 cmdline 에는
패턴 문자열이 들어 있어 스스로에게 SIGTERM 을 보냈다.
2026-08-25 컨테이너 실측(node:20-alpine, 운영과 같은 cap-drop/pids/memory):
pkill -f 'npx serve' → exec 종료코드 143, 살아남은 serve 2개
pkill -f '[s]erve -s' → exec 종료코드 0, 남은 serve 0개
옛 serve 가 포트 3000 을 쥐고 있으면 새 serve 는 EADDRINUSE 로 죽지 않고 랜덤 포트로
조용히 옮겨 붙는다("Accepting connections at http://localhost:46113"). 게이트웨이는
3000 만 프록시하므로 옛 serve 가, 즉 그 serve 가 붙들고 있는 옛 디렉터리가 계속
응답한다. 빌드 산출물 경로가 바뀌면 낡은 화면이 그대로 보인다 — 같은 디렉터리면
serve 가 요청마다 디스크를 읽어 최신이 나오므로, 이 증상은 경로가 바뀔 때만 터진다.
이미 들어가 있는 리스닝 확인이 오히려 이것을 가렸다. 옛 serve 가 3000 에서 응답하니
probe 가 통과해 "준비 완료"가 된다.
함께 고친 것 — exec 이 종료 코드를 읽지 않던 문제.
DockerContainerService.exec 은 stdout·stderr 만 모으고 종료 코드를 확인하지 않았다.
그래서 프리뷰 빌드의 set -o pipefail 이 아무 의미가 없었고, 빌드가 깨져도 호출자는
성공으로 알았다. 컨테이너를 재사용하는 프리뷰에서는 이전 빌드의 dist 가 남아 있어
detectBuildOutputDir 이 그것을 잡았고, 실패한 빌드가 옛 화면으로 성공처럼 보였다.
exec 의 의미는 바꾸지 않았다. 호출부가 48곳인데 상당수는 실패해도 되는 명령이라
(없는 파일 cat, 이미 있는 remote 를 git remote add, [ -d ... ] 존재 확인) 전부
예외로 바꾸면 멀쩡한 흐름이 깨진다. 종료 코드를 함께 돌려주는 execWithExitCode 를
따로 두고, 실패가 반드시 전달돼야 하는 빌드에서만 쓴다. 호출자는 이미 예외를 받아
세션을 FAILED 로 닫는다.
Closes #115
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(preview): 옛 serve 가 살아남아 낡은 빌드를 서빙하던 문제
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
develop → main. #170 하나뿐이고 마이그레이션 변경은 없다.
무엇을 고치나
프리뷰를 다시 띄울 때 옛
serve를 죽이는pkill이 실제 프로세스를 한 번도 잡지 못했다. 컨테이너 안 cmdline 에 리터럴npx serve가 없고, 대신 그 pkill 을 실행하는sh -c자신의 cmdline 에 패턴 문자열이 있어 스스로에게 SIGTERM 을 보냈다.컨테이너 실측(2026-08-25,
node:20-alpine, 운영과 같은 cap-drop/pids/memory):옛 serve 가 포트 3000 을 쥐고 있으면 새 serve 는 EADDRINUSE 로 죽지 않고 조용히 옮겨 붙는다. 게이트웨이는 3000 만 프록시하므로 옛 serve 가 붙들고 있는 옛 디렉터리가 계속 응답한다. 빌드 산출물 경로가 바뀔 때(
dist→build) 낡은 화면이 남는다 — 같은 경로면 serve 가 요청마다 디스크를 읽어 최신이 나오므로, 증상은 경로가 달라질 때만 발현된다.이미 들어가 있던 리스닝 확인이 오히려 이것을 가렸다. 옛 serve 가 3000 에서 응답하니 probe 가 통과해 "준비 완료"가 된다.
함께 고친 것 — 빌드 실패가 조용히 성공으로 넘어가던 문제
DockerContainerService.exec이 종료 코드를 읽지 않아 프리뷰 빌드의set -o pipefail이 무의미했다. 빌드가 깨져도 호출자는 성공으로 알았고, 컨테이너를 재사용하는 프리뷰에서는 이전 빌드의dist가 남아 있어 실패한 빌드가 옛 화면으로 성공처럼 보였다.exec의 의미는 바꾸지 않았다 — 호출부 48곳 중 상당수가 실패해도 되는 명령이라, 종료 코드를 함께 돌려주는execWithExitCode를 따로 두고 빌드에서만 쓴다.검증
./gradlew test전체 통과, CI 통과, dev 배포 성공(f83e762) 및 기동 확인(200)Closes #115
🤖 Generated with Claude Code