React 18 useDeferredValue 심화: 검색 자동완성에서 디바운싱을 제거하는 이유

React 18 useDeferredValue 심화: 검색 자동완성에서 디바운싱을 제거하는 이유

⚡ Next.js 14 App Router와 SWR의 궁합: 공존의 기술

서버 컴포넌트(RSC)가 다 해주는데, SWR이 아직 필요할까요?

Next.js 13, 14로 넘어오면서 App RouterReact Server Components(RSC)가 표준이 되었습니다.
이제 `fetch` API만으로도 서버에서 데이터를 가져올 수 있게 되었죠.
여기서 많은 개발자분들이 고민에 빠집니다.

"데이터 페칭은 이제 서버 컴포넌트가 다 하는데, SWR이나 React Query 같은 클라이언트 라이브러리는 버려야 하나요?"

결론부터 말씀드리면 "아니요, 오히려 둘의 시너지는 강력합니다"입니다.
오늘은 App Router 환경에서 SWR을 어떻게 배치하고 활용해야 최고의 성능을 낼 수 있는지, 그 황금 밸런스를 정리해 드립니다.



⚖️ 1. 서버 컴포넌트 vs SWR: 역할 확실히 나누기

App Router 시대에는 '언제', '어디서' 데이터를 가져올지가 가장 중요합니다.
모든 것을 SWR로 처리하던 Pages Router 시절의 습관은 버려야 합니다.
두 기술은 경쟁 관계가 아니라 상호 보완 관계입니다.

📌 기술별 최적 사용 시나리오

구분 서버 컴포넌트 (RSC) SWR (Client)
주목적 초기 로딩 속도 (FCP), SEO 최적화 실시간 데이터 갱신, 사용자 상호작용
데이터 성격 블로그 글, 제품 상세 정보 등 정적인 데이터 좋아요 수, 댓글, 알림, 주식 차트 등 동적인 데이터
실행 위치 서버 (브라우저 JS 번들 포함 X) 브라우저 (클라이언트)

즉, 뼈대와 핵심 콘텐츠는 서버 컴포넌트로 그리고, 살아서 움직여야 하는 부분만 SWR에게 맡기는 전략이 필요합니다.


🛠️ 2. App Router에서 SWR 제대로 구현하기

SWR은 Hooks 기반이므로 오직 클라이언트 컴포넌트(`'use client'`) 내부에서만 사용할 수 있습니다.
하지만 App Router의 기본은 서버 컴포넌트입니다. 여기서 충돌이 발생하죠.
이를 해결하기 위한 두 가지 핵심 패턴이 있습니다.

⚠️ 주의사항:
서버 컴포넌트 파일(`page.tsx`, `layout.tsx`)에 직접 `useSWR`을 작성하면 에러가 발생합니다.
반드시 별도의 클라이언트 컴포넌트로 분리하거나, `'use client'` 지시어를 상단에 명시해야 합니다.

Pattern A: 격리된 클라이언트 컴포넌트 (Recommended)

데이터 갱신이 필요한 부분만 작은 컴포넌트로 쪼개고, 그 안에서 SWR을 사용하는 방식입니다.
가장 Next.js스러운 방법입니다.

// Components/LiveUserCount.tsx
'use client';
import useSWR from 'swr';

export default function LiveUserCount() {
  const { data } = useSWR('/api/user', fetcher);
  if (!data) return <div>Loading...</div>;
  return <div>접속자: {data.count}</div>;
}

Pattern B: SWRConfig Provider 래핑

전역 설정(fetcher 등)을 공유하고 싶다면, `SWRConfig`를 제공하는 별도의 Provider 컴포넌트를 만들어 `layout.tsx`를 감싸야 합니다.


🚀 3. 궁극의 패턴: 서버 페칭 + SWR Hydration

이 글의 핵심입니다. 서버 컴포넌트의 SEO 장점과 SWR의 실시간성을 모두 잡는 방법입니다.
Next.js 공식 문서에서도 권장하는 '데이터 미리 채우기(Pre-fetching)' 전략입니다.


🎯 작동 원리 3단계

  1. Step 1 (Server): `page.tsx`(서버 컴포넌트)에서 `fetch`로 데이터를 미리 가져옵니다.
  2. Step 2 (Pass): 가져온 데이터를 클라이언트 컴포넌트의 props로 넘기거나, `SWRConfig`의 `fallback` 옵션에 주입합니다.
  3. Step 3 (Client): SWR은 초기값으로 전달받은 데이터를 즉시 화면에 보여주고(로딩 없음!), 백그라운드에서 최신 데이터를 다시 확인(Revalidation)합니다.

이 방식을 사용하면 사용자는 로딩 스피너를 볼 필요가 없으며, 검색 엔진은 완성된 HTML을 읽어갈 수 있습니다.
동시에 페이지에 머무르는 동안 데이터는 SWR에 의해 항상 최신 상태로 유지됩니다.


🎓 도구에 갇히지 마세요

App Router가 나왔다고 해서 기존의 훌륭한 라이브러리들이 쓸모없어지는 것은 아닙니다.
오히려 Next.js의 서버 능력과 SWR의 클라이언트 능력을 조합했을 때, 사용자 경험(UX)은 극대화됩니다.

✅ 오늘 배운 내용 실천 가이드
  • 정적 데이터: 과감하게 SWR을 제거하고 서버 컴포넌트(`fetch`)로 전환하세요.
  • 동적 데이터: 클라이언트 컴포넌트 내부에서 `useSWR`을 사용하세요.
  • 하이브리드: 초기 데이터는 서버에서, 갱신은 SWR로 처리하는 Fallback 패턴을 적용해보세요.

지금 바로 여러분의 프로젝트에서 'use client'가 남발된 곳은 없는지, 혹은 불필요하게 서버 부하를 주고 있는 곳은 없는지 점검해보시기 바랍니다.

댓글 쓰기