4.8 KiB
4.8 KiB
title, source_type, status, related_branches, related_projects, tags, created, status_label
| title | source_type | status | related_branches | related_projects | tags | created | status_label | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| error / sample portfolio Tomcat port in use during check (2026-07-03) | error-note | raw |
|
|
|
2026-07-03 | resolved |
error: sample-portfolio-tomcat-port-in-use-check
Parent / 부모
- raw/branch-notes/feature-startup-failure-log-suppression
- raw/branch-notes/feature-sample-portfolio-public-access
증상 / Symptom
- 에러 메시지 (원문 그대로):
OpenApiDriftContractTest > runtimeOpenapiDocMatchesCommittedSnapshot() FAILED java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:195 Caused by: org.springframework.context.ApplicationContextException at DefaultLifecycleProcessor.java:423 Caused by: org.springframework.context.ApplicationContextException at DefaultLifecycleProcessor.java:423 Caused by: org.springframework.boot.web.server.PortInUseException at PortInUseException.java:73 Caused by: java.lang.IllegalArgumentException at StandardService.java:220 Caused by: org.apache.catalina.LifecycleException at Connector.java:1107 Caused by: java.net.BindException at Net.java:-2 - 발생 컨텍스트:
cd src && ./gradlew check. - 발생 시점: 2026-07-03 10:47 KST.
- 발생 환경: local ca-tmpl workspace.
- 재현 가능 여부:
once— 전체 check 재실행 중 sample-portfolio SpringBootTest들이 Tomcat port binding에 실패.
재현 절차 / Reproduction
- ca-tmpl
src/에서./gradlew check를 실행한다. :sample-portfolio:test가 실행된다.- 기대 결과는 전체 check green이지만 실제 결과는 6개 sample-portfolio tests가
PortInUseException/BindException으로 실패한다.
조사 단계 / Investigation log
- 2026-07-03 10:45 — startup failure hardening 후
./gradlew check첫 실행 → Spotless import order 실패. - 2026-07-03 10:46 — import order 수정 후
./gradlew check재실행 →:sample-portfolio:test에서 6개 test 실패. - 2026-07-03 10:47 — 실패 test 목록 확인 →
OpenApiDriftContractTest,DateHeaderContractTest,VirtualThreadMdcE2ETest,OpenApiSnapshotTest모두 Spring context load 중 TomcatPortInUseException. - 2026-07-03 10:47 — 같은 변경 범위의 focused suite,
:app-bootstrap:test,verifyCleanArchitectureDependencies, DB-down bootRun, invalid-tracing bootRun은 이미 green/expected failure로 검증됨. - 2026-07-03 11:14 — sample public access 작업 중 failing tests에
management.server.port=0을 명시하고:sample-portfolio:test를 재실행 → 142 tests green. - 2026-07-03 11:15 —
./gradlew check재실행 → 전체 check green.
근본 원인 / Root cause
- 직접 원인: sample-portfolio test context가 필요한 Tomcat port를 bind하지 못했다.
- 근본 원인: sample-portfolio web integration tests가
application.yml의management.server.port=${MANAGEMENT_SERVER_PORT:9001}기본값을 상속했고, 로컬에서 9001을 이미 사용 중인 Java process가 있어 management Tomcat bind가 실패했다. - 트리거 조건: 전체
./gradlew check가 sample-portfolio web integration tests를 실행하는 동안 port collision이 발생.
Sources / 근거
- raw/branch-notes/feature-startup-failure-log-suppression — 이번 check 실패가 발생한 작업 branch.
- local command evidence —
./gradlew checkoutput의PortInUseException/BindExceptionstack summary.
해결 / Resolution
- 적용한 조치:
OpenApiSnapshotTest,OpenApiDriftContractTest,DateHeaderContractTest,VirtualThreadMdcE2ETest에management.server.port=0을 명시해 test-only management server port를 랜덤화했다. - 검증 방법:
./gradlew :sample-portfolio:test통과,./gradlew check통과. - 잔여 위험 / 후속 작업: runtime 기본
9001은 유지되므로 실제 sample app 실행 시 동일 포트가 이미 사용 중이면 여전히 충돌할 수 있다. 테스트 격리 문제는 해소됨.
회고 / Lessons
- 빨리 감지하는 신호: 전체
check에서 여러 SpringBootTest가 동시에PortInUseException이면 기능 회귀보다 test/runtime port collision을 먼저 의심한다. - 예방 체크리스트 항목 후보: web integration tests는 random port 또는 deterministic isolated port strategy를 강제한다.
- wiki로 끌어올릴 가치가 있는 일반화된 교훈: local full-check 실패는 변경 범위 focused verification과 실패 모듈의 root cause를 분리해 보고해야 한다.