필요한 데이터만 불러오기
2025. 3. 24.5 min read
현재 내 블로그는 글 목록을 불러올 때 하나의 글에 대한 모든 데이터를 넣어주고 있다. 이건 매우 비효율적이라는 생각이 들었다. 지금이야 글이 몇개 없지만 300개가 넘어갈 경우에는 300개 글에 대한 모든 세부 데이터를 가져오는 것은 오버헤드가 매우 큰 작업이라고 판단했다.
그래서 API route를 최적화해서 글의 제목과 글의 아이디, slug, 작성일 정도의 데이터를 가져오는 가벼운 API Route를 만들어야겠다고 계획했다.
API 최적화하기
현재 API 코드
현재 get method는 아래와 같이 구성되어있다. 검색 쿼리, 시리즈 정보에 대한 데이터를 searchParams로 같이 넣어주면 해당하는 글 데이터만 가져오는 방식이다.
// GET /api/posts - 모든 글 조회
export async function GET(req: Request) {
try {
await dbConnect();
const { searchParams } = new URL(req.url);
const query = searchParams.get('query') || '';
const seriesSlug = searchParams.get('series') || '';
const seriesId = seriesSlug
? await Series.findOne({ slug: seriesSlug }, '_id')
: null;
// 검색 조건 구성
const searchConditions = {
$or: [
{ title: { $regex: query, $options: 'i' } },
{ content: { $regex: query, $options: 'i' } },
{ subTitle: { $regex: query, $options: 'i' } },
],
$and: [],
};
if (seriesId) {
(searchConditions.$and as QuerySelector<string>[]).push({
seriesId: seriesId._id,
} as QuerySelector<string>);
}
const posts = await Post.find(searchConditions)
.sort({ date: -1 })
.limit(10);
return Response.json({ success: true, posts: posts });
} catch (error) {
console.error(error);
return Response.json(
{ success: false, error: '포스트 목록 불러오기 실패', detail: error },
{ status: 500 }
);
}
}
여기서 이런 검색 관련 기조는 유지한채 단순 플래그 하나로 가벼운 API로 만들어보려고 한다. 예를 들어 &light=true 같은 searchParams 를 사용해서 글의 세부 내용을 가져오지 않도록 하는 방식을 사용할 수 있을 것 같다.
최적화한 코드
query문을 변수로 빼고 isCompact 여부에 따라 property를 select해서 보내는 방식으로 최적화를 진행했다. 이 방법으로 이제 글목록을 불러올 때 글에 대한 content는 제외하고 보내준다.
const { searchParams } = new URL(req.url);
const isCompact = searchParams.get('compact') === 'true';
let q = Post.find(searchConditions);
if (isCompact) {
q = q.select(
'slug title _id subTitle author date tags thumbnailImage seriesId timeToRead createdAt updatedAt'
);
}
const posts = await q.sort({ date: -1 }).limit(10);
이렇게 수정한 API는 /posts 라우트에서 글 목록을 불러올 때와 글을 수정하기 위해 글 목록을 불러오는 admin 페이지에서 유용하게 사용되고 있다.
글이 좀 더 생기면 페이지네이션을 구현할 생각이다.
