기록은 가장 쉬운 명상입니다.
Memodian

지표관리 화면의 초기 조회 성능 개선

9 min read · 2025년 11월 25일

API 병목 해소를 위해 캐싱 가능한 도메인 경계를 정의하고 무효화 규칙 설계

1. 문제발생


'지표관리' 화면은 최초 진입 시 지표 목록·상세·임계치·변경이력 등 여러 조회 API가 동시에 호출되는 구조였어요.

이 중 초기 조건 지표 목록 조회는 항상 동일 조건임에도 불구하고 매 요청마다 DB를 재조회해야했고, 이는 전체 지연의 주요 병목으로 작용했어요.

특히 캐시 대상이 아닌 지표 기본정보 상세 API 또한 초기 진입 시 333ms까지 지연되는 등 전체 초기 로딩 성능이 심각하게 저하되는 문제가 발생했어요.


2. 해결과정


캐시 적용이 단순하지 않은 도메인 구조

지표는 결재·버전·부서 관리가 얽혀 있어 전체를 무작정 캐싱하면
금융 도메인 특성상 데이터 일관성 사고로 이어질 수 있는 상황이었어요.

따라서
“무엇을 캐싱할 수 있고, 무엇을 캐싱하면 안 되는지”
도메인 관점에서 경계를 직접 정의해야 했어요.


2-1. 도메인 관점에서 ‘캐시 가능한 경계’를 직접 정의

지표 상세·임계치·이력·버전 상태 등은 결재 흐름과 밀접하게 연결되어 있어 캐싱 불가.
반면, 검색 초기 조건은 변경 이벤트가 극히 드물고 반복 호출되는 영역이었어요.
현업 분들께서도 해당 업무 시, '검색 초기화' 버튼을 가장 많이 사용한다고 알려주셨어요.

따라서 캐싱 가능한 범위를 다음처럼 명확히 설정했다.

“오직 초기 조건 검색만 캐싱한다”


2-2. 도메인 이벤트 기반 캐시 무효화(Evict) 규칙 설계

지표 목록은 다음 이벤트가 발생할 때만 변경되므로
해당 시점마다 캐시를 무효화해야 했어요.

즉, 캐시 무효화는 단순 CRUD가 아니라
결재 흐름과 버전 생성이라는 도메인 이벤트를 기준으로 설계해야 했어요.

이벤트 기반 Evict를 통해 캐시와 실제 비즈니스 상태의 정합성을 확보했어요.


2-3. 운영환경에서 발생한 Redis Serialization 장애 해결

로컬에서는 ConcurrentMapCacheManager로 정상 작동했지만
운영(UAT/PRD)은 RedisCacheManager가 자동 활성화되어
NotSerializableException이 발생했어요.

해결

이로써 캐싱이 운영 환경에서도 안정적으로 동작하도록 문제를 해결했어요.


2-4. 캐싱이 비즈니스 일관성을 깨지 않도록 idempotent 구조 설계

지표는 결재 상태 및 버전 관리가 핵심이기 때문에
조회가 잘못되면 금융사에서는 “사고”가 될 수 있어요.

그래서 아래 원칙을 설계했어요.


3. 결과

3-1. 성능 개선

3-2. 도메인 일관성 유지

3-3. 운영환경까지 포함한 전 구간 안정화


+ 문제 원인 분석

캐시 적용 후 캐시 대상이 아닌 API까지 응답시간이 단축된 점을 보면,
당시 요청 타이밍에서 DB 커넥션 풀 경쟁이나 WAS 스레드 대기 같은 공통 병목이 완화된 것으로 해석할 수 있어요.
이는 대규모 시스템에서 특정 API의 부하 제거가 전체 리소스 경합 감소로 이어지는 전형적인 간접 성능 개선 패턴이에요.


4. 운영 리스크 분석

문제: 고객사 담당자가 DB에 직접 insert/update하는 경우 캐시 무효화가 불가능
해결 방향:

  1. 기술적 관점의 ‘완화(Mitigation)’ 전략
  1. 운영 정책 관점의 ‘방지(Prevention)’ 전략