Skip to content

필사 모드: RSC 이후의 프론트엔드 2025 완전 정복: React Server Components 철학, Next.js App Router·Remix/React Router 7·SvelteKit·SolidStart·Astro Islands·Qwik Resumability 비교, 서버·클라이언트 경계 설계, 실전 마이그레이션 — Season 6 Ep 1

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

프롤로그 · 프론트엔드는 다시 서버로 돌아왔다

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가지 혁신

1. **번들 크기 절감**: 라이브러리를 서버에서만 쓰면 클라이언트 번들에서 사라짐

2. **데이터 Fetching 단순화**: "어디서 데이터를 가져올까" 고민 종식, 컴포넌트에서 직접

3. **네트워크 경계의 시각화**: `'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

1. **'use client'를 과하게 씀** — 트리 최상단에 붙이면 전부 클라이언트

2. **Fetch를 클라이언트에서 반복** — 서버에서 한 번이면 충분

3. **Caching 가정** — Next.js 15부턴 명시적 opt-in 필요

4. **Server Action에서 무거운 로직** — 별도 API·큐 필요

5. **`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와 비슷한 추상화

**예시**:

let count = $state(0);

let doubled = $derived(count * 2);

$effect(() => {

console.log('count changed', count);

});

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 (

);

}

장점

- **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 (

<>

</>

);

}

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

1. 우리 프로젝트가 2025년 메타 프레임워크 중 **적절한 것**을 선택했는가?

2. **서버·클라이언트 경계**가 의식적으로 설계되어 있는가?

3. `'use client'`는 **가장 아래 leaf**에만 붙어 있는가?

4. **Server Action**으로 mutation이 처리되는가?

5. **Streaming·Suspense**로 느린 부분이 격리되어 있는가?

6. **PPR 또는 동등한 정적+동적 하이브리드**를 활용하는가?

7. **Core Web Vitals (LCP/CLS/INP)** 를 측정하고 있는가?

8. **Hydration Mismatch**가 없는가?

9. 데이터 Fetching이 **서버에서 한 곳**으로 정리되어 있는가?

10. Edge Runtime·Node Runtime이 **의도적으로 선택**되었는가?

11. 번들 크기를 **정기 모니터링**(Bundle Analyzer)하고 있는가?

12. Pages Router 잔재가 있다면 **마이그레이션 계획**이 있는가?

> **"프론트엔드는 다시 서버로 돌아왔지만,**

> **돌아온 서버는 예전의 서버가 아니다."**

Season 6가 시작됐다. 다음 편에서 만나자.

— Season 6 Ep 1, Fin.

현재 단락 (1/293)

1990년대 서버 렌더링(PHP·JSP) → 2010년대 SPA(React·Vue·Angular) → 2020년대 다시 **서버 중심**. 역사는 반복한다. 그러나 이번엔 다르다....

작성 글자: 0원문 글자: 8,256작성 단락: 0/293