마이페이지 저장된 로그 등 콘텐츠 로딩시간이 김

서버 데이터 패치 함수에서 시간 측정
export async function fetchBookmarkedLogs({ userId, currentPage = 1, pageSize = 12 }: logBookmarkListParmas): Promise<LogsReseponse> {
const start = Date.now(); // 측정 시작
try {
...
const duration = Date.now() - start;
console.log(fetchBookmarkedLogs 처리 시간: ${duration}ms);
return {
success: true,
data: filterBookmarkedLogs,
meta: {
...
httpStatus: 200,
},
};
} catch (_error) {
console.error(_error);
return {
success: false,
...
};
}
}

| 항목 | 전략 2번 (/api/logs/bookmark + CSR fetch) | 전략 3번 (dehydrate + HydrationBoundary) |
|---|---|---|
| 데이터 fetch 시점 | 클라이언트 진입 후 시작됨 | 서버에서 먼저 fetch 완료 후 렌더 |
| 초기 렌더 속도 | 느릴 수 있음 (로딩 스피너 필요) | 빠름 (로딩 없이 즉시 렌더) |
| SEO 노출 | 데이터 없이 HTML만 렌더됨 | 데이터 포함된 HTML 렌더 |
| 중복 fetch | 브라우저 새로고침마다 fetch 발생 | dehydrate로 SSR 캐시 재사용 |
| 사용자 경험 | 잠깐 깜빡이거나 스켈레톤 필요 | 거의 깜빡임 없음 |
export async function GET(req: NextRequest) {
const { searchParams } = req.nextUrl;
const userId = searchParams.get('userId');
const currentPage = parseInt(searchParams.get('currentPage') ?? '1', 10);
const pageSize = parseInt(searchParams.get('pageSize') ?? '12', 12);
if (!userId) {
return NextResponse.json(
{
success: false,
msg: ERROR_MESSAGES.COMMON.UNAUTHORIZED,
errorCode: ERROR_CODES.COMMON.UNAUTHORIZED,
},
{ status: 400 }
);
}
try {
// 서버 패치 함수로부터 데이터를 가져옴
const result = await getBookmarkedLogs({ userId, currentPage, pageSize });
if (!result.success) {
return NextResponse.json(result, {
status: 404,
});
}
return NextResponse.json(result, { status: result.meta?.httpStatus ?? 200 });
} catch (_error) {
console.error(_error);
return NextResponse.json(
{
success: false,
msg: ERROR_MESSAGES.COMMON.INTERNAL_SERVER_ERROR,
errorCode: ERROR_CODES.COMMON.INTERNAL_SERVER_ERROR,
},
{ status: 500 }
);
}
}
async function fetchUseLogsBookmark(params: BookmarkParams): Promise<LogsReseponse> {
const query = toQueryString(params);
const res = await fetch(`/api/logs/bookmark?${query}`);
const data = await res.json();
return data;
}
export default function useLogsBookmark({
userId,
currentPage = 1,
pageSize = 12,
}: BookmarkParams) {
const params = {
userId,
currentPage,
pageSize,
};
const tab = useProfileTabStore((state) => state.tab);
return useQuery({
queryKey: logKeys.bookmarkList(params),
queryFn: () => fetchUseLogsBookmark(params),
enabled: !!userId && tab === 'savedLog',
placeholderData: keepPreviousData,
});
}