Next.js 13 이후 App Router 환경에서는 컴포넌트의 기본 동작이 이전과 달라졌다. 핵심은 Server Component가 기본값이라는 점이다. 그래서 "use client"의 의미를 이해하려면 먼저 이 기본 동작을 알아야 한다.
App Router 기본 동작: 모든 컴포넌트는 Server Component

App Router에서는 별도 선언이 없으면 모든 컴포넌트가 Server Component로 동작한다.
Server Component의 특징:
- 서버에서만 실행됨
- 브라우저로 JavaScript 번들이 내려가지 않음
- 서버 렌더링 중심 구조
이 구조 때문에 다음 기능을 사용할 수 없다.
- useState
- useEffect
- useRef
- 이벤트 핸들러 (onClick, onChange 등)
- window, document 접근
즉 인터랙션이 필요한 UI 로직은 Server Component에서 동작할 수 없다.
"use client"의 역할
"use client"는 파일 상단에 선언하는 directive다. 이 선언이 있으면 해당 파일은 강제로 Client Component가 된다.
Client Component의 특징:
- 브라우저에서 실행됨
- 상태 관리 가능
- 이벤트 처리 가능
- React Hook 사용 가능
Client Component의 제약:
- JavaScript 번들 크기 증가
- 서버 전용 기능 사용 제한
- DB 직접 접근 같은 서버 로직 사용 불가
그리고 중요한 점: "use client"는 전파된다. 해당 파일 + 그 안에서 import한 컴포넌트가 전부 Client Component로 처리된다. 그래서 범위를 잘 관리하는 게 중요하겠다.
common error
App Router를 사용할 때 다음 에러를 많이 보게 된다.
현재 import한 컴포넌트가 useState를 필요로 한다.
이 Hook은 Client Component에서만 동작한다.
따라서 이 파일(또는 상위 컴포넌트)에 "use client"를 선언하라.
Server Component 안에서 Client 전용 기능을 사용하고 있기 때문에 에러가 난 것.
권장 패턴: "use client" 범위 최소화
그럼 페이지 전체를 Client Component로 만들면 되는거 아냐? 싶겠지만 이 방식은 권장되지 않는다. 번들 크기가 증가하고, 서버 렌더링 장점이 감소하고, 성능 저하 가능성이 있기 때문이다.
권장 패턴:
페이지는 Server Component로 유지하고 인터랙션이 필요한 부분만 Client Component로 분리한다.
예시 구조:
page.tsx (Server Component)
components/
Counter.tsx (Client Component)
예시 코드:
page.tsx
import Counter from "./components/Counter";
export default function Page() {
return <Counter />;
}
Counter.tsx
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
특히 다음 UI는 보통 Client Component로 분리한다.
- 버튼 인터랙션
- 탭 UI
- 드롭다운
- 모달
- 폼 상태 관리
반대로 다음은 Server Component로 유지하는 경우가 많다.
- 페이지 레이아웃
- 데이터 fetching
- SEO 관련 렌더링
- 서버 데이터 처리
정리
App Router에서는 기본이 Server Component이므로, 다음 상황에서 "use client"가 필요하다.
- React Hook 사용
- 사용자 인터랙션 처리
- 브라우저 API 사용
권장 패턴: Client Component 범위 최소화. 페이지 전체에 "use client"를 붙이지 말고 인터랙션이 필요한 컴포넌트만 분리하자.
'Dev & Study' 카테고리의 다른 글
| [javascript] Epoch time이란, 현재 Epoch time 얻는 법 (0) | 2026.03.03 |
|---|---|
| [npm] npm uninstall, 패키지 제거 방법 (0) | 2026.03.03 |
| [git] merge 되돌리는 방법 (0) | 2026.03.03 |
| [npm] peerDependency strictness란 (0) | 2026.03.03 |
| [git] stash: 브랜치 이동 시, 하던 작업을 잠시 치워두는 법 (0) | 2026.03.02 |