Next.js 성능 최적화기 ③ - DB 쿼리 튜닝으로 응답 속도 줄이기

혜연·2025년 6월 4일
0

Next.js

목록 보기
17/20
post-thumbnail

🐢 API 응답시간

npm run dev로 서버를 띄운 후, 첫 페이지 진입 시 찍히는 로그창을 보니

  • GET /study: 2436ms
  • GET /api/studies: 1366ms
    응답 속도가 꽤 느렸다.
    물론 실행할 때마다 수치는 조금씩 달라지긴 하지만, 느리다는 건 변한없었다.

특히 쿼리문을 보니 불필요한 데이터까지 모두 select해서 들고오고 있었다.
/study에서는 스터디 리스트를, /api/studies에서는 인기글 리스트를 select하고 있는 상황에서 두 쿼리문을 개선해 보았다.


✂️ 첫 번째 개선: 필요한 필드만 select

Prisma의 select옵션으로 필요한 필드만 지정해서 가져오도록 수정했다.

 const studies = await prisma.study.findMany({
      where,
      select: {
        id: true,
        title: true,
        category: true,
        startDate: true,
        createdAt: true,
        scrap: true,
        content: true,
        author: {
          select: {
            id: true,
            nickname: true,
            profileImage: true,
          },
        },
        _count: {
          select: {
            comments: true, // 댓글 개수만 필요하면 이렇게
          },
        },
      },
      orderBy: { createdAt: "desc" },
      ...(cursor && {
        cursor: { id: cursor },
        skip: 1, // cursor 제외
      }),
      take,
    });

결과

  • /study: 2436ms → 2105ms (약 331ms 감소, 14% 개선)
  • /api/studies: 1366ms → 1115ms (약 251ms 감소, 18% 개선)

🔍 두 번째 개선: 인덱스 추가

추가적으로 스크랩과 조회수 기준으로 인기글을 정렬할 때,
게시글별로 댓글을 가져올때, 더 빠르게 쿼리를 처리하기 위해 자주 조회되는 필드에 인덱스를 추가했다.

인덱스는 DB에서의 책 목차 같은 역할이다.
검색하거나 정렬할 필드에 인덱스를 걸어두면, 전체를 다 뒤짖 않고 필요한 데이터만 바로 찾아갈 수 있다.

// Study 테이블
 @@index([scrap(sort: Desc), views(sort: Desc), createdAt(sort: Desc)], name: "idx_study_performance")

이건 아래와 같은 순서로 정렬할떄 최적화된다.

  • "scrap 내림차순 → 그 안에서 views 내림차순 → 그 안에서 createdAt 내림차순"
    쿼리에서도 orderBy에 이 세 필드를 같은 순서로 명시해줘야 인덱스가 적용된다.
orderBy: [
  { scrap: "desc" },
  { views: "desc" },
  { createdAt: "desc" },
]
// Comment 테이블
 @@index([studyId], name: "idx_comment_study_id")

이건 댓글 테이블에서 특정 스터디에 달린 댓글 목록을 빠르게 조회할 때 사용된다. (WHERE studyId = 'xxx')

결과

  • /study: 2105ms → 2198ms (정렬 기준 적용 이후에도 속도 유지됨)
  • /api/studies: 1115ms → 1040ms (댓글 많은 글도 속도 차이 거의 없음)

전체 성능 변화 요약

API변경 전변경 후감소량개선율
/study2436ms2198ms-238ms약 10%
/api/studies1366ms1040ms-326ms약 24%

실행할때마다 수치가 다르긴 하지만, DB쿼리 개선후에 속도가 빨라진 건 느껴졌다.


😺 배운점

API 속도가 느리면 일단 백엔드 쿼리를 먼저 확인해보는 게 기본이라는 것을 느꼈다. 특히 Supabase 덕분에 터미널에 쿼리문이 잘 찍혀서 디버깅하기 훨씬 좋았던 것 같다.

  • 필요한 데이터만 select 해오기
  • 자주 조회되는 조건은 index 걸기
  • join이나 count연산 주의하기

0개의 댓글