Ch.16 Next.js 입문 — 풀스택 React 프레임워크
서버 vs 클라이언트 컴포넌트
'use client' 붙이면 뭐가 달라지는데?
Next.js 프로젝트에서 useState를 썼더니 에러가 납니다. 'use client'를 붙이면 해결되는데... 왜?
서버 컴포넌트와 클라이언트 컴포넌트, 언제 뭘 써야 할까?
서버 컴포넌트 = 데이터, 클라이언트 컴포넌트 = 인터랙션. 역할을 나누면 빠르고 안전합니다.
핵심 내용
Next.js의 모든 컴포넌트는 기본적으로 서버 컴포넌트입니다
// 서버 컴포넌트 — 별도 표시 없음 (기본값)
// app/users/page.tsx
export default async function UsersPage() {
// ✅ 서버에서 직접 DB 조회!
const users = await db.user.findMany();
// ✅ 서버에서 직접 API 호출!
const data = await fetch("https://api.example.com/data");
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
// ❌ useState, useEffect 사용 불가!
// ❌ onClick 등 이벤트 핸들러 불가!'use client' 한 줄이면 브라우저에서 실행되는 컴포넌트로 전환됩니다
"use client"; // ← 이 한 줄이 핵심!
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>
+1
</button>
</div>
);
}서버에서 데이터를 가져오고 클라이언트에서 인터랙션을 처리합니다
// 1️⃣ 클라이언트 컴포넌트 — 좋아요 버튼
// components/LikeButton.tsx
"use client";
import { useState } from "react";
export function LikeButton({ initialLikes }: {
initialLikes: number;
}) {
const [likes, setLikes] = useState(initialLikes);
return (
<button onClick={() => setLikes(likes + 1)}>
❤️ {likes}
</button>
);
}// 2️⃣ 서버 컴포넌트 — 게시글 페이지
// app/post/[id]/page.tsx
import { LikeButton } from "@/components/LikeButton";
export default async function PostPage({
params,
}: {
params: { id: string };
}) {
// ✅ 서버에서 DB 조회
const post = await db.post.findUnique({
where: { id: Number(params.id) },
});
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
{/* ✅ 클라이언트 컴포넌트에 데이터 전달 */}
<LikeButton initialLikes={post.likes} />
</article>
);
}서버 컴포넌트: DB에서 게시글 데이터 조회
HTML 생성: 서버에서 완성된 HTML 렌더링
클라이언트 컴포넌트: LikeButton만 브라우저에서 활성화
인터랙션: 좋아요 버튼 클릭 가능!
바이브 코더 원칙 기본은 서버 컴포넌트로 두고, useState, onClick이 필요한 부분만 'use client'를 붙이세요. 최소한의 클라이언트 컴포넌트가 최적의 성능을 만듭니다.
Next.js에서 컴포넌트의 기본값은?
서버 컴포넌트에서 useState를 사용할 수 있다.
서버 컴포넌트 안에서 클라이언트 컴포넌트를 사용하려면?
'use client'를 최대한 많이 사용하는 것이 좋다.
핵심 용어
JS 번들 없음
서버에서 실행되므로 브라우저에 JS를 보내지 않음 — 빠름!
직접 DB 접근
API 없이 서버에서 바로 데이터베이스 조회 가능
보안
API 키, DB 비밀번호가 클라이언트에 노출 안 됨
비교 정리
| 항목 | 서버 컴포넌트 | 클라이언트 컴포넌트 |
|---|---|---|
| async/await | ✅ 가능 | ❌ 불가 |
| useState/useEffect | ❌ 불가 | ✅ 가능 |
| onClick 등 이벤트 | ❌ 불가 | ✅ 가능 |
| DB/파일 직접 접근 | ✅ 가능 | ❌ 불가 |
정리 노트
서버 vs 클라이언트 컴포넌트 비교
핵심 개념
- 서버 컴포넌트
- Next.js의 기본값 — 서버에서 렌더링, JS 번들 없음
- 클라이언트 컴포넌트
- 'use client' 선언 — useState, onClick 등 인터랙션 처리
- 최소 클라이언트 원칙
- 인터랙션이 필요한 최소 단위에만 'use client' 사용
- 서버+클라이언트 조합
- 서버 컴포넌트 안에 클라이언트 컴포넌트를 자식으로 배치
'use client'는 최소한으로 — JS 번들이 작을수록 성능이 좋습니다.
시각 자료
퀴즈와 인터랙션으로 더 깊이 학습하세요
play_circle인터랙티브 레슨 시작