Next.js 13부터 도입된 App Router와 RSC (React Server Component) 개념은 처음 접했을 때 꽤나 헷갈립니다.
저도 최근 작은 프로젝트를 하면서 "이걸 어떻게 구조화하지?", "fetch는 어디서 해야 하지?" 같은 고민을 정말 많이 했어요.
그 과정에서 직접 부딪히며 느꼈던 시행착오들을 공유하려고 합니다. 아래의 폴더 구조를 파악해서 예시 코드를 보시면 이해 하기 수월합니다!
## 폴더 구조
/src
├── app # Next.js의 App Router
│ ├── api/apiName # 서버에서만 동작하는 API Route (route.ts)
│ └── pageName # 사용자에게 보여줄 페이지들 (page.tsx)
├── lib
│ ├── server # 서버 컴포넌트에서 직접 사용하는 서버 로직
│ └── client # 클라이언트 컴포넌트에서 fetch로 API 호출하는 로직
*lib/server 같은 경우 Prisma, fs, process.env 등 서버 전용 코드를 사용하기 때문에 클라이언트(브라우저)에서 실행 될 경우 오류 발생
위 구조는 제가 직접 사용한 폴더 구조입니다.
서버용 코드와 클라이언트용 코드를 구분하였습니다.
■ RSC 방식이란?
RSC(React Server Components) = 서버에서 실행되는 React 컴포넌트
Next.js에서는 기본적으로 page.tsx가 서버 컴포넌트입니다.
즉, 이곳에서 API 호출을 하거나 DB에 직접 접근하는 게 가능합니다.
// 서버 컴포넌트 (app/gift/update/page.tsx)
import { getGiftData } from '@/lib/server/gift';
export default async function GiftPage() {
const data = await getGiftData(); // ✅ 직접 DB 접근 가능!
return <ClientComponent data={data} />;
}
- 이처럼 서버 컴포넌트에서는 lib/server에 있는 서버 전용 로직을 불러와 직접 실행할 수 있습니다.
- fetch나 /api를 거칠 필요 없이 곧바로 Prisma 등 DB 호출이 가능합니다.
서버 컴포넌트 안에는 클라이언트 컴포넌트를 사용 할 수 있어서 서버 클라이언트에서 데이터를 받아서 props로 전달 할 수 있습니다. 하지만 그 반대 상황인 클라이언트 컴포넌트('use client')에서 서버 컴포넌트를 호출 할 수 없니다. 그 이유는 클라이언트 컴포넌트는 브라우저에서 실행되기 때문에, 직접 DB 접근은 불가능
// GiftForm.tsx (클라이언트 컴포넌트)
'use client'
import { getGiftData } from '@/lib/server/gift';
export default function GiftForm() {
// ❌ 서버 함수는 클라이언트에서 호출 불가
// 🔴 Error: Cannot serialize a function returned from server
}
→ 이럴 때는 아래와 같이 클라이언트 컴포넌트에서는 lib/client → fetch → app/api → lib/server(게시글 초기 폴더 구조 확인)를 거쳐야 합니다.
// lib/client/gift/getGift.ts
export async function getGift() {
const res = await fetch('/api/gift/getGift');
const json = await res.json();
return json;
}
// 'use client' 컴포넌트
'use client';
import { getGift } from '@/lib/client/gift/getGift';
useEffect(() => {
getGift().then((res) => {
// 응답 처리
});
}, []);
■ 요약
| 구분 | 사용 위치 | 동작 방식 |
| lib/server | 서버 컴포넌트, API | 직접 DB접근 가능 |
| lib/client | 클라이언트 컴포넌트 | 직접 DB접근 불가능 하므로 fetch사용 |
| /app/api/** | Api route(API 전용) | lib/server 함수 불러서 사용 가능 |
| page.tsx(서버 컴포넌트가 default) | 초기 랜더링 시 DB접근 | lib/server 함수 직접 호출 |
| use client | 이벤트 발생 후 데이터 요청 | lib/client에 접근 하여 api 사용 |
■ 결론
Next.js에서 **RSC 방식은 서버에서 먼저 데이터를 준비해서 화면을 그려주는 방식**
그래서 페이지 초기 렌더링(특히 GET 방식)에 적합하고, 클라이언트에서 발생하는 액션(예: 버튼 클릭, 전송, 수정)은 기존처럼 fetch를 통해 API를 호출하여 사용합니다.
'React > 프론트엔트 개념 정리' 카테고리의 다른 글
| [Next.js] - RSC에서 수정 후 이전 데이터가 보일 때 해결 방법 (0) | 2025.11.04 |
|---|---|
| JWT – Stateless 인증의 핵심 (0) | 2025.10.22 |
| 클로저(Closure)란? – React에서 stale 값이 생기는 이유 (0) | 2025.10.17 |
| Vue가 다시 뜨는 이유 (0) | 2025.10.14 |