- Scala 2.13에서 Scala 3로의 코드베이스 마이그레이션 과정에서 예상치 못한 성능 저하가 발생
- 초기 테스트와 배포 환경에서는 모든 지표가 정상이었으나, 몇 시간 후 Kafka 지연(lag) 이 증가
- 부하 테스트 결과, 세분화된 메시지 처리 시 처리율 급감 현상이 확인
-
async-profiler 분석을 통해 Quicklens 라이브러리의 체인 평가 비효율 버그가 원인으로 드러남
- 라이브러리 업데이트 후 성능이 복구되었으며, Scala 버전 간 라이브러리 동작 차이에 대한 주의 필요성 강조
서비스 마이그레이션 과정
- 기존 서비스는 Scala 2.13에서 Scala 3.7.3으로 이전
- 매크로를 사용하지 않는 데이터 수집 중심 서비스였으며, 성능이 중요한 구성
- 의존성, 컴파일러 옵션, 타입 및 문법 변경을 적용 후 컴파일 성공
- 테스트 환경과 단계적 배포에서도 로그와 메트릭 모두 정상으로 나타남
- 인프라, JVM, 애플리케이션 수준의 지표 모두 건강한 상태로 확인
원인 불명의 성능 저하
- 배포 후 약 5~6시간 뒤 Kafka lag 증가 현상 발생
- 데이터 스파이크가 아닌 상황에서도 인스턴스당 처리율 감소
- 롤백 후 처리율이 즉시 복구되어 코드 변경이 원인임을 확인
성능 분석 및 원인 추적
- 부하 테스트에서는 초기에는 성능 회귀가 재현되지 않음
- 메시지의 세분화 및 이질적 페이로드에서만 처리율 급감이 발생
- 의존성 라이브러리(직렬화, DB SDK, Docker 이미지, 설정 라이브러리 등)를 하나씩 되돌려 테스트했으나 변화 없음
-
async-profiler로 CPU 프로파일링 수행 결과,
- Scala 3에서는 JIT 컴파일러와 디코딩 단계의 CPU 점유율 급증
- Flamegraph 상단에서 Quicklens 호출이 전체 CPU 시간의 절반 차지
- Scala 2.13에서는 동일 호출이 0.5% 수준에 불과
문제의 근본 원인
- Quicklens 라이브러리의 체인 평가 비효율 버그가 Scala 3에서 발생
교훈 및 권장 사항
-
라이브러리의 메타프로그래밍 의존성이 Scala 버전 간 성능 차이를 유발할 수 있음
- 마이그레이션이 정상적으로 완료되어도, 핫스팟과 병목 구간을 벤치마크해야 함
- 성능이 중요한 서비스에서는 “잘 동작한다”는 가정 대신, 실측 기반 검증이 필수
- 코드가 아닌 벤치마크가 병목을 드러내는 상황을 방지하기 위한 사전 점검 필요