판단

# 기준 설명
1 해당 API가 목표 p95를 넘었는가? 이미 넘었거나, 마진이 작아 VU 증가 시 초과 가능한가
2 그 API가 읽기 중심이고 반복 호출되는가? SELECT 쿼리, 높은 req/s
3 느린 이유가 DB 조회/정렬/집계/검색 때문인가? 인덱스 부재, Full Scan, JOIN+GROUP BY 등
4 데이터 최신성이 얼마나 중요하고, 변경 빈도는 낮은가? 캐싱 적합성 판단
5 인덱스/캐시 적용 후 같은 조건에서 p95, DB CPU, 쿼리 시간이 개선됐는가? 적용 후 동일 조건 재측정 필요 (Before/After)

요약

순위 API 적용 방법 핵심 근거
1 content-list 인덱싱 + 캐싱 Postgres CPU 86% (최고), 인덱스 0개, 읽기 127 req/s
2 playlist-detail 캐싱 p95 271ms (목표 300ms 근소), pending 28건, 4개 쿼리 연쇄
3 playlist-list 캐싱 (또는 반정규화) 커넥션 풀 포화, JOIN+GROUP BY 집계 매 요청 실행
4 review-list 인덱싱 목록 조회용 복합 인덱스 부재, 쿼리 패턴이 명확

1. content-list (콘텐츠 목록 조회) — 인덱싱 + 캐싱

테스트 결과

지표 비고
p95 215ms 목표 500ms 이내
Postgres CPU 86% 9개 API 중 최고
App CPU 135%
커넥션 풀 active 4/10, pending 0
처리량 127 req/s

기준별 판단

기준 판단 근거
p95 목표 초과? 아님 p95 215ms로 목표 이내이나, Postgres CPU 86%는 VU 증가 또는 데이터 증가 시 급격한 성능 저하 예고
읽기 중심 + 반복 호출? YES 127 req/s, 순수 SELECT, 목록 화면 진입마다 호출
느린 이유가 DB? YES contents 테이블에 인덱스가 하나도 없음. deleted_at IS NULL 필터 + watcher_count/average_rating/created_at 정렬을 Sequential Scan + Sort로 처리
데이터 최신성/변경 빈도? 캐싱 적합 콘텐츠 등록은 관리자 행위로 빈도 낮음. 30~60초 TTL 캐시 가능

현재 쿼리문

파일: ContentQdslRepositoryImpl.java - findContents()

WHERE deleted_at IS NULL
  AND type = ? (선택)
ORDER BY watcher_count DESC, id   (또는 average_rating, created_at)

최적화 방안

인덱싱: 정렬 기준별 Partial 복합 인덱스

-- 시청자 수 정렬 (기본)
CREATE INDEX idx_contents_active_watcher
  ON contents (watcher_count DESC, id)
  WHERE deleted_at IS NULL;

-- 평균 평점 정렬
CREATE INDEX idx_contents_active_rating
  ON contents (average_rating DESC, id)
  WHERE deleted_at IS NULL;

-- 최신순 정렬
CREATE INDEX idx_contents_active_created
  ON contents (created_at DESC, id)
  WHERE deleted_at IS NULL;