들어가며

실서비스에 React Server Components(이하 RSC)를 도입한 지 1년이 지났습니다. 첫 도입 결정을 했을 때는 환상이 컸지만, 막상 운영해 보니 트레이드오프가 분명했습니다.

이 글에서는 1년간 운영하며 알게 된 것들을 정리합니다. 잘 작동한 패턴후회한 패턴, 그리고 다시 도입한다면 어떻게 할지를 솔직하게 적어 봅니다.

전제 조건 Next.js 14 App Router 기반, 일 평균 트래픽 240만 PV의 미디어 서비스에서 진행된 경험입니다. SPA에서 마이그레이션 했으며, 팀은 풀스택 7명입니다.

잘 작동한 패턴 4가지

1. 데이터 페칭의 단순화

가장 큰 변화는 데이터 페칭 코드가 절반 이하로 줄었다는 점입니다. useEffect + 로딩 상태 + 에러 상태의 무한 반복에서 벗어났습니다.

// app/posts/[slug]/page.tsx
// ✅ Server-side data loading, no client bundle export default async function PostPage({ params }: { params: { slug: string } }) { const post = await getPost(params.slug) const related = await getRelated(post.id) return ( <article> <PostHeader post={post} /> <PostBody mdx={post.body} /> {/* Client component only where needed */} <CommentForm postId={post.id} /> <RelatedPosts items={related} /> </article> ) }

전에는 같은 페이지에서 useSWR, useState, 로딩 스피너, 에러 폴백 등 60줄짜리 보일러플레이트가 필요했습니다. 이제 14줄. 그리고 더 빠릅니다.

2. 번들 크기 축소

RSC로 옮기면서 JavaScript 번들이 38% 줄었습니다. Markdown 파서, 날짜 포맷터, syntax highlighter — 이런 것들이 모두 서버에서만 실행되도록 옮겨졌기 때문입니다.

💡
실측 데이터 같은 페이지를 모바일 4G로 측정한 결과입니다. TTI(Time to Interactive) 1.1초 단축은 사용자 체감 변화가 큰 수치예요.

3. SEO 메타데이터

App Router의 generateMetadata는 정말 잘 만들어진 API입니다. 동적 메타데이터를 SSR로 처리할 수 있어서, 소셜 공유 카드 처리가 굉장히 단순해졌습니다.

후회한 패턴 3가지

"Server / Client 경계는 처음 생각보다 훨씬 복잡합니다.
이 경계를 잘못 그으면, RSC의 이점을 모두 잃습니다."

가장 큰 실수는 Server / Client 경계를 너무 늦게 정한 것이었습니다. 초기에는 "필요할 때 'use client' 붙이면 되겠지"라고 생각했는데, 점점 쌓이면서 client component 트리가 비대해졌습니다.

// fig 01 — Server / Client 경계 시각화 (Vercel speed insights)

두 번째 실수는 third-party 라이브러리의 호환성을 과소평가한 것입니다. 익숙한 라이브러리들이 client component를 강제하거나, 아예 SSR을 지원하지 않는 경우가 의외로 많았습니다.

주의해야 할 라이브러리 react-beautiful-dnd, 일부 chart.js 래퍼, 그리고 localStorage에 직접 접근하는 모든 라이브러리는 client-only로 wrap이 필요합니다.

다시 시작한다면

지금이라면 처음부터 다음 3가지를 명확히 하고 시작할 것입니다.

  1. Server / Client 경계 사전 설계. 어느 컴포넌트가 어디 속하는지를 도입 전에 트리로 그려보기.
  2. 라이브러리 호환성 사전 조사. 사용 중인 모든 의존성을 점검하고, 대안을 미리 준비.
  3. 점진적 마이그레이션 전략. 한 번에 다 바꾸지 말고, 새 페이지부터 시작해서 천천히 확장.

마치며

RSC는 분명 강력한 도구이지만, 모든 프로젝트에 답은 아닙니다. 트래픽이 크지 않고 인터랙티브가 중요한 앱이라면, 굳이 도입할 필요가 없을 수도 있어요.

다음 글에서는 RSC를 도입하지 않은 케이스 — 이걸 했더라면 더 좋았을 결정들에 대해 적어볼 예정입니다. 의견이나 질문은 아래 댓글이나 Twitter/X로 남겨주세요.

— Doyun