Monew 프로젝트: 뉴스기사 목록 조회 인덱스 없이 구조 개선으로 약 30배 성능 개선

2026. 5. 17. 21:26·트러블 슈팅

문제상황

Monew 프로젝트 메인 화면에서는 뉴스기사 목록을 조회한다.

 

이 화면은 사용자가 자주 접근할 가능성이 높은 진입 지점이라고 생각했고, 목록 조회 성능이 전체 사용자 경험에 직접적인 영향을 줄 수 있다고 판단했다.

 

메일화면의 기본 조회조건은 화면에서 볼 수 있듯이 다음과 같다.

정렬기준: published_at

정렬 방향: DESC

출처: NAVER

조회 개수: 10개 + hasNext 확인용 1개

WHERE na.is_deleted = false
  AND na.source = 'NAVER'
ORDER BY
  na.published_at DESC,
  na.created_at DESC
FETCH FIRST 11 ROWS ONLY

기존 조회 구조

LEFT JOIN article_interests ai
       ON ai.news_article_id = na.id

LEFT JOIN comments c
       ON c.article_id = na.id
      AND c.is_deleted = false

LEFT JOIN article_views av
       ON av.news_article_id = na.id
      AND av.user_id = ...

기존 뉴스 기사 목록 조회는 기사 정보, 댓글 수, 사용자 조회 여부를 한번의 쿼리에서 모두 처리하고 있었다.

이후 댓글 수 집계를 위해 COUNT(DISTINCT c.id)와 GROUP BY를 수행했다.

 

문제는 메인 화면에서는 관심사 필터가 없음에도 article_interests 조인이 항상 수행된다는 점이었다.

즉, 최종적으로 필요한 데이터는 11개뿐인데 DB에서는 수만건의 조인과 집계, 정렬을 먼저 수행하고 있었다.


실행 계획 분석

실행 계획을 확인해보니 다음과 같은 문제가 있었다.

  • NAVER 기사 약 45,700 rows 조회
  • article_interests 약 79,000 rows 조인
  • 중간 결과 약 72,000 rows 생성
  • 이후 GROUP BY, COUNT(DISTINCT id), ORDER BY 수행

특히 정렬 단계에서는 external merge가 발생했다.

Sort Method: external merge
temp read/write 발생

정렬 대상 데이터가 메모리에 모두 올라가지 못해 디스크 기반 정렬이 발생했다는 의미 ..

결국 최종 결과는 11개 뿐인데도 DB는 그 11개를 얻기위해 수만건의 중간 결과를 처리하고 있던것이다.


개선 방향

문제의 핵심은 11개의 row를 뽑기위해 너무 많은 작업을 수행한다는 점.

 

1. news_articles에서 기사 11개를 먼저 조회

2. 조회된 기사 ID에 대해서만 댓글 수 조회

3. 조회된 기사 ID에 대해서만 사용자 조회 여부 조회

4. java에서 DTO 조립

 

먼저 JOIN과 GROUP BY, ORDER BY로 준비를 해놓고 조회하는방식이 아닌 11개를 조회하고 JOIN을 하는 식으로 변경했다.

 


개선 후 구조

 

SELECT
    na.id,
    na.source,
    na.original_link,
    na.title,
    na.published_at,
    na.summary,
    na.view_count,
    na.created_at
FROM news_articles na
WHERE na.is_deleted = false
  AND na.source = 'NAVER'
ORDER BY
    na.published_at DESC,
    na.created_at DESC
FETCH FIRST 11 ROWS ONLY;

먼저 11개를 조회한 후, 댓글 수 와 조회 여부는 현제 페이지의 기사 ID만 대상으로 별도 조회하는식으로 변경한것이다.

 


성능 비교

 

NAVER 뉴스기사 약 45000건 기준

 

기존 JOIN/GROUP BY 구조: 평균 실행시간은 614.825 ms

개선 구조는 20.215 ms

 

기사 목록조회: 20.067 ms

댓글 수 집계: 0.111ms

사용자 조회 여부 조회: 0.038ms

 

개선 후 전체 DB 실행 시간 기준 약 30배 수준의 성능 개선을 확인할 수 있었다.

 


 

'트러블 슈팅' 카테고리의 다른 글

Monew 프로젝트: 뉴스기사 목록조회 PostgreSQL 복합 인덱스로 뉴스 목록 조회 성능 개선  (0) 2026.05.17
'트러블 슈팅' 카테고리의 다른 글
  • Monew 프로젝트: 뉴스기사 목록조회 PostgreSQL 복합 인덱스로 뉴스 목록 조회 성능 개선
과컴
과컴
벡엔드 개발자 최소기준 맞추겠습니다.
  • 과컴
    곽의 프로그램
    과컴
  • 전체
    오늘
    어제
    • 분류 전체보기 (76)
      • 위클리페이퍼 (6)
      • 파이썬 (4)
      • 코드잇 스프린트 (48)
        • Spring 이론 (7)
        • Java이론 (11)
        • 실습 (23)
      • 백엔드 개발자 최소기준 (1)
      • 코딩테스트 (5)
        • 알고리즘 (0)
        • SQL (1)
      • Git (5)
      • 스프링부트 핵심가이드 (1)
      • 트러블 슈팅 (2)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백준브론즈
    파이썬
    백준1152
    파이썬입문
    파이썬기초
    백준2576
    백준1075번
    혼공파
    문자열
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
과컴
Monew 프로젝트: 뉴스기사 목록 조회 인덱스 없이 구조 개선으로 약 30배 성능 개선
상단으로

티스토리툴바