npm run dev
로 서버를 띄운 후, 첫 페이지 진입 시 찍히는 로그창을 보니
특히 쿼리문을 보니 불필요한 데이터까지 모두 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")
이건 아래와 같은 순서로 정렬할떄 최적화된다.
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 | 변경 전 | 변경 후 | 감소량 | 개선율 |
---|---|---|---|---|
/study | 2436ms | 2198ms | -238ms | 약 10% |
/api/studies | 1366ms | 1040ms | -326ms | 약 24% |
실행할때마다 수치가 다르긴 하지만, DB쿼리 개선후에 속도가 빨라진 건 느껴졌다.
API 속도가 느리면 일단 백엔드 쿼리를 먼저 확인해보는 게 기본이라는 것을 느꼈다. 특히 Supabase 덕분에 터미널에 쿼리문이 잘 찍혀서 디버깅하기 훨씬 좋았던 것 같다.
select
해오기index
걸기