✍️ 필사 모드: RSC 이후의 프론트엔드 2025 완전 정복: React Server Components 철학, Next.js App Router·Remix/React Router 7·SvelteKit·SolidStart·Astro Islands·Qwik Resumability 비교, 서버·클라이언트 경계 설계, 실전 마이그레이션 — Season 6 Ep 1
한국어프롤로그 · 프론트엔드는 다시 서버로 돌아왔다
1990년대 서버 렌더링(PHP·JSP) → 2010년대 SPA(React·Vue·Angular) → 2020년대 다시 서버 중심. 역사는 반복한다. 그러나 이번엔 다르다. 도구와 사고 방식이 완전히 새로워졌다.
2024-2025년 프론트엔드의 중심 질문은 하나다.
"서버와 클라이언트의 경계를 어디에 둘 것인가?"
React Server Components(RSC) 이후, 이 질문은 더 이상 피할 수 없다.
- Next.js 15는 App Router가 완전히 정착
- Remix는 React Router 7로 통합
- SvelteKit 2는 Svelte 5 Runes와 함께 성숙
- SolidStart 1(stable), Astro 5, Qwik v2
- React 19은 Actions·
use()·Ref as prop·document metadata 정식화
Season 6 첫 편은 이 전체 지형을 관통한다.
1장 · RSC의 본질 — "네트워크 경계를 컴포넌트 모델로"
기존 React의 한계
SPA 시대 (2015-2022)
- 브라우저가 빈 HTML 받고, JS 번들 다운로드 후 렌더
- 문제: 큰 번들 → 느린 초기 로딩, 나쁜 SEO,
useEffect로 데이터 가져오기
SSR + Hydration (2016-2023)
- 서버가 초기 HTML 생성, 클라이언트가 hydrate
- 문제: 모든 JS를 여전히 전송, "useEffect 지옥"
- 동일 로직을 서버·클라이언트 양쪽에 작성
RSC (2023-)
- 컴포넌트를 Server Component / Client Component 로 분리
- 서버 컴포넌트는 서버에서만 실행, JS 전송 안 됨
- 클라이언트 컴포넌트만 hydrate
- 데이터 가져오기는 서버 컴포넌트에서
await fetch()자연스럽게
RSC의 3가지 혁신
- 번들 크기 절감: 라이브러리를 서버에서만 쓰면 클라이언트 번들에서 사라짐
- 데이터 Fetching 단순화: "어디서 데이터를 가져올까" 고민 종식, 컴포넌트에서 직접
- 네트워크 경계의 시각화:
'use client'지시어로 경계 명시
오해 vs 진실
오해 1: "RSC = SSR의 새 이름이다"
- 실제: 별개 개념. RSC는 SSR과 같이 쓰일 수도 있고, 없이 쓰일 수도 있음
오해 2: "모든 게 서버 컴포넌트여야 한다"
- 실제: 상호작용이 있는 UI(폼·버튼 상태·애니메이션)는 클라이언트가 맞음
오해 3: "RSC는 Next.js 전용"
- 실제: React의 공식 기능. Remix/React Router 7·Waku·다른 메타 프레임워크도 채택 중
오해 4: "성능이 무조건 좋아진다"
- 실제: 경계 설계를 잘못하면 워터폴(순차 fetch) 발생, 오히려 느려짐
2장 · Next.js 15 App Router — 성숙한 RSC 구현체
2024년 내내 버그·불안정성 논란이 있었으나, Next.js 15(2024 10월)에서 대폭 안정화.
주요 기능
(1) React 19 통합
- Actions,
useFormStatus,useOptimistic정식 use()hook으로 Promise·Context 언래핑
(2) Partial Pre-Rendering (PPR)
- 정적 셸 + 동적 홀 하이브리드 렌더
- 2025년 안정화 경로
- 가장 혁신적 성능 아이디어
(3) Turbopack 기본값
- Webpack 대체 러스트 번들러
- Dev 서버 빌드 속도 5-10배
(4) Caching 전면 재설계
- 이전의 "자동 캐싱"이 혼란 유발
- 2025년엔 명시적
cache·revalidate필요 use cache지시어 도입 (실험)
(5) Server Actions 성숙
- 폼 제출·뮤테이션을 서버 함수로
'use server'지시어
2025년 권장 구조
app/
layout.tsx # 전역 레이아웃 (RSC)
page.tsx # 홈 (RSC)
(marketing)/
about/page.tsx # 정적 마케팅
(app)/
dashboard/
page.tsx # 로그인 필요
loading.tsx # 로딩 UI
error.tsx # 에러 경계
_components/
ChartClient.tsx # 'use client'
api/
webhook/route.ts # Route Handler
일반 실수 Top 5
- 'use client'를 과하게 씀 — 트리 최상단에 붙이면 전부 클라이언트
- Fetch를 클라이언트에서 반복 — 서버에서 한 번이면 충분
- Caching 가정 — Next.js 15부턴 명시적 opt-in 필요
- Server Action에서 무거운 로직 — 별도 API·큐 필요
window접근을 서버 컴포넌트에서 — 빌드 오류
3장 · Remix → React Router 7 통합
2024년 말 중대한 변화. Remix가 React Router 7에 흡수됐다.
배경
- Remix는 항상 React Router 기반이었음
- 유지 둘로 분리 관리 vs 통합
- 2024년 5월 "Remix as React Router" 발표
- 2024년 후반 React Router 7 릴리스
React Router 7 핵심
(1) Framework Mode vs Library Mode
- Framework mode: 과거 Remix 방식 (파일 기반 라우팅·loaders·actions)
- Library mode: 순수 라우팅 라이브러리
- 양쪽 다 지원
(2) RSC 점진적 지원
- 2025년 상반기 실험 단계, 후반 stable 목표
- Remix 철학: "웹 플랫폼 표준 존중" 유지
(3) Vite 기본
- Remix 2부터 Vite. RR7에서 공식 표준
(4) loader/action
- 데이터 fetch·mutation 핸들러를 라우트별로
- 서버 실행, JSON 반환
2025년 선택 기준
- Next.js: SSG·ISR·PPR·전사 관리자 대시보드·마케팅 사이트까지 하나로
- React Router 7 (Remix): 웹 표준 선호·간결한 로더·SPA도 지원
- 두 가지를 한 조직에서 혼용하는 경우도 증가
4장 · SvelteKit 2 · Svelte 5 Runes
Svelte는 다른 철학으로 성장.
Svelte 5의 변화
Runes (2024-2025)
$state,$derived,$effect— 명시적 리액티비티- 이전의 마법적 문법 대체
- Vue 3 Composition API, Solid Signals와 비슷한 추상화
예시:
<script>
let count = $state(0);
let doubled = $derived(count * 2);
$effect(() => {
console.log('count changed', count);
});
</script>
SvelteKit 2 주요 기능
- Vite 기본
load함수 (서버·클라이언트)- Form Actions (Remix와 유사)
+page.server.ts서버 전용- Adapter로 Vercel·Netlify·Cloudflare·Node·정적
장점
- 번들 크기가 매우 작다 (React·Next.js 대비 1/3)
- 문법 가독성 높음
- 학습 곡선 완만
- 빌트인 transitions·animations
단점
- 생태계가 React 대비 작음
- 엔터프라이즈 채용 시장 제한
- 복잡한 상태관리 외부 의존
5장 · SolidStart 1 — 진정한 fine-grained reactivity
Solid는 React와 비슷한 JSX 문법, 전혀 다른 렌더링 모델.
핵심 철학
- 컴포넌트는 단 1회 실행
- Signals이 의존성 추적
- Virtual DOM 없음
- 극도의 성능 (공식 벤치마크 최상위)
SolidStart 1 (2024년 stable)
createSignal,createEffect,createResource- 파일 기반 라우팅
- SSR·SPA·Static 모두 지원
- Vinxi 빌드 툴 기반
적합한 경우
- 극한 성능이 필요한 앱
- React와 유사한 개발 경험 원하지만 번들·런타임 비용 싫은 경우
- 복잡한 인터랙티브 UI (대시보드, 에디터)
한계
- 생태계 소규모
- 엔터프라이즈 도입 아직 제한
- 일부 3rd party는 React/Vue에만 초점
6장 · Astro 5 — Islands Architecture의 성숙
"콘텐츠가 주인, 인터랙션은 섬(island)"
Astro 철학
- 기본 렌더: 정적 HTML (JS 제로)
- 필요한 컴포넌트만 섬(island) 으로 하이드레이트
- 프레임워크 혼용: React + Vue + Svelte + Solid 같은 페이지에 가능
- MDX·Markdown 네이티브 지원
Astro 5 (2024 말) 주요 기능
(1) Content Layer
- 정적 콘텐츠 소스를 TypeScript로 정의
- 블로그·문서 사이트 강력한 빌드 시간 처리
(2) Server Islands
- 정적 페이지 안에 서버에서 동적 생성되는 부분 삽입
- PPR과 유사한 개념
(3) View Transitions API
- SPA 느낌의 전환을 MPA에 적용
- 브라우저 네이티브 API 활용
적합한 경우
- 블로그·문서·마케팅 사이트
- SEO·성능이 절대적 중요
- 여러 프레임워크 혼용 희망
한계
- 복잡한 인터랙티브 앱(대시보드·에디터)에는 과부족
- 클라이언트 라우팅은 옵션이지만 Next.js·Remix만큼 성숙 X
7장 · Qwik v2 — Resumability의 도전
2024-2025년 가장 이단적 접근.
핵심 개념: Resumability
- Hydration 대신 Resumability
- 서버가 HTML과 serialize된 앱 상태를 함께 보냄
- 클라이언트는 필요한 순간에만 JS 로드·실행
- 초기 로드 시 거의 JS 실행 0
장단점
장점
- 초기 페이지 로드 극단적으로 빠름 (JS 거의 없음)
- 대규모 앱도 첫 페이지는 작게
단점
- 학습 곡선 높음
- 생태계 매우 작음
- 디버깅·툴링 아직 성숙 중
2025년 위치
- Nike·Salesforce 등 일부 대형 채택
- 일반 개발자 풀에선 여전히 니치
- Builder.io가 주도 (모기업)
8장 · 메타 프레임워크 종합 비교표 (2025 4월)
| 기준 | Next.js 15 | RR7 (Remix) | SvelteKit 2 | SolidStart 1 | Astro 5 | Qwik v2 |
|---|---|---|---|---|---|---|
| 렌더 모델 | RSC·SSR·SSG·PPR | SSR·SPA·RSC | SSR·SSG·SPA | SSR·SSG·SPA | Static+Islands | Resumable |
| 기본 언어 | React JSX | React JSX | Svelte | Solid JSX | Any | Qwik JSX |
| 번들 크기 | 중~대 | 중 | 작음 | 매우 작음 | 최소 | 최소 |
| 학습 곡선 | 중 | 중 | 낮 | 낮~중 | 낮 | 높 |
| 생태계 | 최대 | 크다 | 중간 | 작음 | 중간 | 작음 |
| 엔터프라이즈 | ★★★★★ | ★★★★ | ★★★ | ★★ | ★★★ | ★★ |
| 콘텐츠 사이트 | ★★★ | ★★★ | ★★★ | ★★ | ★★★★★ | ★★★ |
| 대시보드 앱 | ★★★★★ | ★★★★★ | ★★★★ | ★★★★ | ★★ | ★★★ |
| SEO | ★★★★★ | ★★★★★ | ★★★★ | ★★★★ | ★★★★★ | ★★★★★ |
| Edge/Serverless | ★★★★★ | ★★★★ | ★★★★ | ★★★★ | ★★★★ | ★★★★ |
2025년 현실적 선택 가이드
- 대규모 웹앱·엔터프라이즈: Next.js 15 (최대 생태계·안정성)
- 웹 표준 선호, 복잡도 낮추고 싶다: React Router 7
- 성능·번들이 생명: SvelteKit 2 or SolidStart 1
- 블로그·마케팅·문서: Astro 5
- 극단적 초기 로드 성능: Qwik v2
9장 · 서버·클라이언트 경계 설계 — 실전
원칙 5가지
(1) 기본은 서버 (Server-First)
- 상호작용 없으면 서버 컴포넌트 유지
'use client'없이 시작
(2) 가장 아래 leaf에서 Client
- "카운터 하나"를 위해 전체 페이지를 클라이언트로 만들지 마라
'use client'는 가능한 트리의 잎에
(3) 데이터는 서버에서 Fetch
await fetch()를 서버 컴포넌트에서 자유롭게- 클라이언트
useEffect fetch지양
(4) 경계를 명확히 이름 짓기
Foo.server.tsx,Foo.client.tsx네이밍 권장 (관례)- 읽는 사람이 바로 파악
(5) Client Boundary의 비용 인식
'use client'하나에 자식 전체 트리 클라이언트화- State·Effect·Browser API가 필요한 최소 단위로
자주 헷갈리는 케이스
케이스 1: 상태 없는 순수 UI 컴포넌트 → 서버. JS 전송 0.
케이스 2: 차트 라이브러리 래핑 → 클라이언트(시각화 라이브러리 대부분 brow서 API 사용).
케이스 3: 폼
→ Server Action + 'use client' 래퍼 조합. useFormStatus로 진행 상태.
케이스 4: 테마 토글 → 클라이언트. 최소 단위로.
케이스 5: Auth 체크 후 다른 UI 보여주기
→ 서버. await getServerSession() 후 분기.
10장 · Server Actions와 Forms — React 19의 혁신
기존 패턴
function Form() {
const [state, setState] = useState();
const handleSubmit = async (e) => {
e.preventDefault();
const res = await fetch('/api/submit', { method: 'POST', body: ... });
setState(await res.json());
};
return <form onSubmit={handleSubmit}>...</form>;
}
새 패턴 (React 19 + RSC)
async function submitAction(formData: FormData) {
'use server';
const result = await db.insert(formData.get('name'));
revalidatePath('/items');
}
export default function Page() {
return (
<form action={submitAction}>
<input name="name" />
<button type="submit">추가</button>
</form>
);
}
장점
- Progressive Enhancement: JS 꺼져도 동작
- 타입 안전: 같은 레포 서버·클라이언트 타입 공유
- 보일러플레이트 감소: API 라우트·JSON 직렬화 불필요
- 자동 revalidation:
revalidatePath,revalidateTag
주의 사항
- Public Internet 노출 엔드포인트임 → 인증·권한 체크 필수
- 민감한 비밀을 클라이언트 코드에서 참조 금지
- Error Handling과 Optimistic UI는 별도 설계
11장 · Streaming과 Partial Pre-Rendering (PPR)
Streaming
- HTML을 한 번에 보내지 않고 조각씩 전송
- 느린 부분은
<Suspense>로 감싸 로딩 상태 먼저 보여주기 - TTFB·LCP 개선
Partial Pre-Rendering (PPR)
- 2024-2025 Next.js 신기능
- 정적 셸을 빌드 시 생성
- 동적 홀은 요청 시 채움
- 최고의 초기 로드 + 개인화 공존
사용 예
export const experimental_ppr = true;
export default function Page() {
return (
<>
<StaticHeader /> {/* 빌드 시 */}
<Suspense fallback={<Skeleton/>}>
<PersonalizedGreeting /> {/* 런타임 */}
</Suspense>
<StaticFooter /> {/* 빌드 시 */}
</>
);
}
2025년 표준화 경로
- Next.js 15 후반 stable 목표
- React 팀과 협업하는 참조 구현
- 다른 메타 프레임워크도 유사 기능 검토
12장 · 실전 마이그레이션 — Pages Router → App Router
2024년에도 많은 프로젝트가 Pages Router에서 App Router로 이동 중.
단계별 전략
Phase 1: 공존
app/과pages/를 같이 운영 (Next.js 공식 지원)- 새 페이지만 App Router로
Phase 2: 컴포넌트 분리
- 기존 컴포넌트에
'use client'추가 → App Router에서도 동작 - 상태·Effect 있는 것 위주
Phase 3: 데이터 가져오기 전환
getServerSideProps/getStaticProps→ 서버 컴포넌트에서fetch- SWR·React Query 의존 감축
Phase 4: Layout·Loading·Error 재구성
- App Router의 특별 파일 활용
- 중첩 레이아웃 설계
Phase 5: API Routes → Server Actions
- 단순 mutation은 Server Action으로
- 외부 노출 API는 Route Handler 유지
흔한 함정
use client트리 최상단: 번들 폭발, 성능 저하- 데이터 가져오기 중복: 서버·클라이언트 양쪽에서
- 캐시 이해 부족: Next.js 15 캐시 정책 대폭 변경
- Edge Runtime 가정: Node API 쓰는 코드가 Edge에서 깨짐
- Hydration Mismatch: 서버·클라이언트 렌더 결과 다름 → 콘솔 에러
13장 · 다음 글 예고 — Season 6 Ep 2: "디자인 시스템과 토큰의 현재"
프레임워크 골격을 만들었다면 다음은 비주얼과 인터랙션. Ep 2는 디자인 시스템.
- Radix UI·shadcn/ui·Chakra·Tamagui·DaisyUI·Park UI·Ark UI 비교
- Headless vs Styled 철학
- Design Token 표준 (W3C Design Tokens)
- Figma ↔ Code 연동 (Tokens Studio, Figma Variables, Specify)
- 컴포넌트 API 설계 원칙
- Theming·Dark Mode·Color Mode
- 접근성(Accessibility) 기본값
- 모바일·데스크톱 크로스 디자인
- 대기업 디자인 시스템 사례 (토스·네이버·카카오·쿠팡)
- 팀 규모별 디자인 시스템 도입 전략
"디자인 시스템은 CSS가 아니다. 제품 팀의 공용 언어다."
다음 글에서 만나자.
에필로그 · 체크리스트 12
- 우리 프로젝트가 2025년 메타 프레임워크 중 적절한 것을 선택했는가?
- 서버·클라이언트 경계가 의식적으로 설계되어 있는가?
'use client'는 가장 아래 leaf에만 붙어 있는가?- Server Action으로 mutation이 처리되는가?
- Streaming·Suspense로 느린 부분이 격리되어 있는가?
- PPR 또는 동등한 정적+동적 하이브리드를 활용하는가?
- Core Web Vitals (LCP/CLS/INP) 를 측정하고 있는가?
- Hydration Mismatch가 없는가?
- 데이터 Fetching이 서버에서 한 곳으로 정리되어 있는가?
- Edge Runtime·Node Runtime이 의도적으로 선택되었는가?
- 번들 크기를 정기 모니터링(Bundle Analyzer)하고 있는가?
- Pages Router 잔재가 있다면 마이그레이션 계획이 있는가?
"프론트엔드는 다시 서버로 돌아왔지만, 돌아온 서버는 예전의 서버가 아니다."
Season 6가 시작됐다. 다음 편에서 만나자.
— Season 6 Ep 1, Fin.
현재 단락 (1/304)
1990년대 서버 렌더링(PHP·JSP) → 2010년대 SPA(React·Vue·Angular) → 2020년대 다시 **서버 중심**. 역사는 반복한다. 그러나 이번엔 다르다....