Skip to content

[PERF] 잔디 yearly/lessons 캐시, 직렬화 무게 때문에 캐시 없을 때보다 느림 #359

Description

@dlxodus02

[PERF] 잔디 캐시 직렬화 — EVERYTHING 타입 메타데이터로 큰 페이로드 캐시가 역효과

📊 개선 시급성 및 우선순위

  • P1 : 주요 API 응답 지연 및 사용자 경험(UX) 저하 현상 해결
  • P0 : 치명적인 성능 병목 (타임아웃 발생, 서버 리소스 고갈 등 긴급 조치 필요)
  • P2 : 사전 예방 차원의 쿼리 튜닝 및 리소스 사용 효율화

⚡ 성능 개선 개요 및 목표

  • 연관 이슈 번호 : #
  • 연관 도메인 : grass (전역 설정이라 다른 캐시 도메인에도 영향 가능 — 랭킹 등)
  • 현재 상태 (As-Is) : RedisConfig가 모든 캐시에 GenericJackson2JsonRedisSerializer + ObjectMapper.DefaultTyping.EVERYTHING을 전역 적용 중. 캐시에 들어가는 모든 객체·필드에 타입 메타데이터(@class)가 붙어서, 페이로드가 큰 캐시(grassYearly:v2, grassLessons:v2 — 365일치, 21KB+)는 역직렬화 비용이 캐시 이득을 상회함. 중간 강도 부하(10,000명, 30초 분산) 측정 결과 캐시를 켰는데 캐시 없을 때보다 더 느려짐:
    • /api/grass/yearly: 280ms(캐시 없음) → 1,809ms(캐시 있음, 현재 직렬화)
    • /api/grass/lessons: 766ms(캐시 없음) → 1,681ms(캐시 있음, 현재 직렬화)
  • 목표 상태 (To-Be) : 캐시 이름별로 타입을 고정한 가벼운 직렬화(Jackson2JsonRedisSerializer<구체타입>)로 교체. 로컬 실험 결과 yearly 1,809ms → 26ms(91%↓, 10.8배), lessons 1,681ms → 22ms(97%↓, 34.8배)로 정상화됨.

💻 상세 작업 내용 및 영향 계층

  • Model / Policy:
  • UseCase / Command:
  • Service:
  • Port / Adapter: RedisConfig.cacheManager()grassMonthly:v2/grassYearly:v2/grassView:v2/grassLessons:v2 4개 캐시에 한해 withInitialCacheConfigurations()로 타입 고정 직렬화 적용. 나머지 캐시(랭킹 등)는 기존 EVERYTHING 설정 유지(이번 PR 범위 밖, 별도 검토 필요).
  • Repository: (예: Fetch Join 적용, 인덱스 추가 등)
  • Controller:
  • response / request:

🚨 검증 및 사이드 이펙트 확인 (TestCode)

  • 최적화 전후 정량적 지표 측정 완료 및 성능 향상 확인 (로컬에서 1차 확인됨 — PR에서 재검증)
  • 캐시 직렬화/역직렬화 라운드트립 테스트 추가 (CacheSerializationRoundTripTest에 그대로 적용 — 타입 고정 직렬화도 record 역직렬화가 정상 동작하는지 확인)
  • 기존 비즈니스 로직 정상 동작 테스트 케이스 통과 확인
  • 예외(Exception) 처리 로직 유지 및 검증 통과 확인

📸 실행 계획(Explain) 및 지표 로그

측정 환경: 회원 10,000명, daily_study_stats 665만 행, k6 ramping-arrival-rate(10,000명이 30초에 걸쳐 분산 도착)

엔드포인트 캐시 없음 캐시 + 기존 직렬화 캐시 + 가벼운 직렬화(제안)
/api/grass (view) 19ms 27ms 18ms
/api/grass/yearly 280ms 1,809ms ⚠️ 26ms
/api/grass/lessons 766ms 1,681ms ⚠️ 22ms
/api/grass/monthly 18ms 27ms 17ms

⚠️ = 캐시를 켰는데 캐시 없을 때보다 더 느려진 구간

참고: 극단적으로 짧은 시간(10초)에 동시 요청이 몰리는 상황에서는 직렬화를 가볍게 바꿔도 개선이 제한적임(시스템 자체의 동시 처리 한계가 다른 병목으로 작용) — 이건 이번 PR 범위 밖, 별도 인프라/용량 검토 과제로 분리.

원본 비교/코드 예시: Notion 문서 참고

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions