Modu Square

인기글 트래픽 집중에 따른 응답 지연 개선

문제

  • 인기글 목록은 다른 기능보다 조회 트래픽이 집중되기 쉬움

Modu Square 인기글 전체 보기 화면

return hotArticleListRepository.readAll(dateStr).stream()
        .map(articleClient::read)
        .filter(Objects::nonNull)
        .map(HotArticleResponse::from)
        .toList();
  • Redis에는 인기글 ID와 점수만 있어 목록 요청마다 Article Service의 단건 조회 API를 10회 호출
  • 요청률을 높이자 75 req/s까지 20ms대였던 응답 시간이 100 req/s에서 1초 이상으로 급증

해결 전략

  • 당일 생성 게시글의 articleId, title, createdAt만 Hot Article Service 조회 모델에 저장
  • Sorted Set에서 Top 10 ID를 읽고 조회 모델을 MGET으로 일괄 조회
  • 인기글 조회 경로에서 Article Service 단건 API 호출 제거

기술 선택 이유

  • 단건 API 10회 병렬 호출 - 제외

    • 응답 대기 시간은 줄지만 요청 한 건이 내부 호출 10건으로 늘어나는 구조 유지
    • 인기글 트래픽 증가에 따라 Article Service의 커넥션과 스레드 사용량도 함께 증가
  • Article Service batch API - 제외

    • 내부 호출은 한 번으로 줄지만 Article Service의 지연과 장애가 인기글 API로 전파
    • 인기글 화면을 위해 Article Service에 별도 API 계약을 추가해야 하는 결합 발생
  • Redis 조회 모델 - 채택

    • 순위와 화면 데이터를 같은 Redis에서 읽어 서비스 간 호출 제거
    • Article Service에 지연이나 장애가 생겨도 인기글 조회 경로는 영향받지 않음

구현

List<Long> articleIds = hotArticleListRepository.readAll(dateStr);
Map<Long, HotArticleQueryModel> queryModels =
        hotArticleQueryModelRepository.readAll(articleIds);
  • 게시글이 늘어도 Top 10 고정이라 목록 요청당 Redis 왕복 2회 유지

검증

같은 로컬 환경에서 요청률을 단계적으로 높여 변경 전후 비교

항목설정
대상당일 생성 게시글 Top 10
요청률50 → 75 → 100 → 150 → 200 → 250 req/s
측정 시간단계별 45초

변경 전

변경 전 인기글 목록 응답 시간

  • 100 req/s부터 p95와 p99가 초 단위로 급증하며 병목 구간 확인

변경 후

조회 모델 적용 후 인기글 목록 응답 시간

  • 100 req/s에서 p95 1.75ms 확인
  • 같은 조건에서 250 req/s까지 높여도 오류 없이 처리
지표변경 전 100 req/s변경 후 100 req/s변경 후 250 req/s
p951.83s1.75ms1.21ms
Article Service 단건 조회최대 약 993 req/s0 req/s0 req/s

한계

  • 원본을 부르지 않으므로 제목을 수정해도 갱신 이벤트가 처리될 때까지 목록에는 이전 제목이 남음
  • 로컬 환경 측정이라 운영 규모의 네트워크 지연과 경합은 반영되지 않음