
코드 한 줄 바꾸지 않고 프로덕션 미스터리를 명쾌하게 해결한 무신사 WMS팀의 실전 디버깅기
무신사 WMS팀이 간헐적인 Jenkins 배치 지연 현상을 해결하기 위해 Java Flight Recorder(JFR)를 실무에 전격 투입한 여정을 담은 아티클입니다. 단순 정황 증거와 부정확한 로그 분석에 의존해 엉뚱한 라이브러리를 고칠 뻔한 위기를 극복하고, 저오버헤드 진단 툴을 통해 팩트 기반의 분석을 수행한 과정을 보여줍니다. 결국 디바이드 앤 컨커 방식으로 진범인 N+1 쿼리를 찾아내고, 통합 쿼리 처리를 통해 인프라 부하를 8분의 1로 줄인 짜릿한 최적화 경험을 공유합니다.
안전성이 극도로 중요한 프로덕션 환경에서 원인 불명의 대기 상태나 병목을 마주해 곤경에 처한 자바/스프링 백엔드 시니어 개발자에게 강력히 권장합니다. 특히 상시 켜두어도 성능 저하가 없는 실시간 진단 도구를 통해 추측성 튜닝의 반복을 멈추고 고도로 효율적인 팩트 중심의 디버깅을 지향하는 엔지니어에게 훌륭한 실무 교과서가 될 것입니다.
Jenkins로 기동하는 Spring Batch 애플리케이션에서 Spring 기동 이후 첫 Step이 시작되기 전까지 간헐적으로 5분에서 12분 동안 일시 정지(Hang)되는 현상이 발생했습니다. 기존의 스레드 덤프나 힙 덤프 방식은 분석가가 행 발생 시점에 대기해야 하고 일회성 스냅샷만 제공하여 실시간 시간 흐름에 따른 병목 추적이 불가능했습니다.
운영 중인 코드의 수정 없이 JVM 기동 옵션만으로 동작하는 저오버헤드 프로파일러인 Java Flight Recorder(JFR)를 적용하여 빌드 종료 시 파일을 수집했습니다. 이후 JDK Mission Control(JMC)로 분석을 진행하여 기존 용의선상에 있던 AWS 로깅 라이브러리의 무죄를 입증하고, Aurora RO 복제본 DB에 파티션 단위로 루프를 돌며 조회를 수행하던 N+1 쿼리 병목을 식별하여 통합 그룹 쿼리 방식으로 수정했습니다.
N+1 조회를 제거하여 Aurora RO 복제본에 대한 소켓 read 횟수가 138회에서 32회로 급감했고, 대형 배치 기준 조회 성능이 최대 14.5배 향상되었습니다. 쿼리량 감소에 따라 동시 배치 실행 시 DB CPU 및 I/O 경합 부하가 8분의 1 수준으로 줄어들어 간헐적으로 발생하던 12분짜리 행 현상이 근본적으로 해결되었습니다.
Trade-off
개별 파티션 필터를 제거하고 대용량의 그룹 데이터를 한 번에 통합 조회하게 됨에 따라, 메모리 내부에서 그룹화 및 지그재그 정렬 처리를 수행하기 위한 Java CPU 연산과 메모리 사용량이 다소 증가했습니다. 또한 원본 DB의 일시적인 성능 한계로 인한 병목 현상은 단일 쿼리 최적화만으로는 근본적 해결이 불가능하여 중장기적으로 Temporal 워크플로우 엔진 이관을 통한 구조 개선이 요구됩니다.
OpenJDK 런타임에 내장되어 1~2% 수준의 매우 낮은 오버헤드로 JVM 내부에서 일어나는 광범위한 진단 정보(스레드, GC, 락, I/O 등)를 지속적으로 수집할 수 있는 고성능 프로파일러입니다.
JFR이 생성한 바이너리 데이터 분석 파일을 시각화하여 특정 시점의 상세 리소스 소비 현황과 코드 흐름을 프로파일링해 주는 인터랙티브 분석 도구입니다.
연관 데이터를 조회할 때 한 번의 상위 조회 쿼리 이후 루프 내에서 하위 엔티티들을 건건이 추가로 쿼리하여 원치 않는 대규모의 데이터베이스 요청 왕복(Round-Trip)이 수반되는 비효율적 패턴입니다.




