React Server Components 도입 검토 중 마주친 번들 사이즈 이슈
문제 상황
Next.js 13.4의 app directory를 실험적으로 도입했다. 기존 pages 디렉토리 대비 Server Components의 이점을 활용하려 했으나, 배포 후 초기 JS 번들이 오히려 120KB 증가했다.
원인 분석
번들 분석 결과, 서버 컴포넌트 내부에서 사용한 라이브러리들이 클라이언트 번들에 포함되고 있었다. 특히 date-fns와 lodash가 문제였다.
// layout.tsx (Server Component)
import { format } from 'date-fns';
import ClientWrapper from './ClientWrapper';
export default function Layout({ children }) {
const timestamp = format(new Date(), 'yyyy-MM-dd');
return <ClientWrapper timestamp={timestamp}>{children}</ClientWrapper>;
}
ClientWrapper에 'use client' 지시어가 있어도, 부모에서 import된 라이브러리가 번들에 포함되는 현상이 있었다.
해결 방법
- Server-only 패키지 활용: 서버 전용 로직을 명시적으로 분리했다.
import 'server-only';
import { format } from 'date-fns';
export async function getFormattedDate() {
return format(new Date(), 'yyyy-MM-dd');
}
-
Client Component 경계 재설정: 실제로 인터랙션이 필요한 최소 단위만 클라이언트 컴포넌트로 분리했다.
-
Dynamic import 활용: 조건부로 필요한 무거운 컴포넌트는 지연 로딩 적용했다.
const HeavyChart = dynamic(() => import('./HeavyChart'), {
ssr: false,
loading: () => <Skeleton />
});
결과
초기 번들 사이즈가 기존 대비 85KB 감소했다. Lighthouse 점수도 개선됐다. Server Components는 강력하지만, 클라이언트/서버 경계를 신중하게 설계해야 한다는 것을 배웠다.
app directory는 아직 안정화 단계이므로, 프로덕션 적용 시 번들 분석을 필수로 진행하는 게 좋겠다.