본문 바로가기
Javascript/Next.js

Next.js의 'use client' 지시어 완벽 가이드

by daddydontsleep 2024. 11. 19.
728x90
728x90

사진: UnsplashMarine Brochard

Next.js의 'use client' 지시어 완벽 가이드

안녕하세요! 오늘은 Next.js 13+ 버전에서 도입된 'use client' 지시어(directive)에 대해 자세히 알아보도록 하겠습니다. 서버 컴포넌트와 클라이언트 컴포넌트의 개념부터, 실제 사용법과 주의사항까지 상세히 다뤄보겠습니다.

목차

  1. 서버 컴포넌트 vs 클라이언트 컴포넌트
  2. 'use client' 란?
  3. 언제 'use client'를 사용해야 할까?
  4. 실제 사용 예시
  5. 주의사항과 best practice
  6. 성능 최적화 전략

1. 서버 컴포넌트 vs 클라이언트 컴포넌트

서버 컴포넌트 (기본값)

Next.js 13 이후부터 모든 컴포넌트는 기본적으로 서버 컴포넌트로 동작합니다. 서버 컴포넌트의 특징은 다음과 같습니다:

  • 서버에서만 실행됨
  • 번들 사이즈에 영향을 주지 않음
  • 데이터베이스에 직접 접근 가능
  • 환경 변수에 직접 접근 가능
  • useState, useEffect 같은 클라이언트 훅 사용 불가

클라이언트 컴포넌트

'use client' 지시어를 사용하여 명시적으로 선언된 컴포넌트입니다. 특징은 다음과 같습니다:

  • 브라우저에서 실행됨
  • 자바스크립트 번들에 포함됨
  • 브라우저 API 사용 가능
  • React 훅 사용 가능
  • 이벤트 리스너 추가 가능

2. 'use client' 란?

'use client'는 Next.js에서 해당 컴포넌트가 클라이언트 사이드에서 실행되어야 함을 명시하는 지시어입니다. 파일 최상단에 선언되어야 하며, 해당 파일과 이를 임포트하는 모든 하위 컴포넌트에 영향을 미칩니다.

'use client'

import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  )
}

3. 언제 'use client'를 사용해야 할까?

다음과 같은 상황에서 'use client'를 사용해야 합니다:

  1. 브라우저 API 사용 시

    • window, document 객체 접근
    • localStorage, sessionStorage 사용
    • 브라우저 이벤트 핸들링
  2. React 훅 사용 시

    • useState
    • useEffect
    • useReducer
    • 커스텀 훅
  3. 상호작용이 필요한 UI 컴포넌트

    • 버튼 클릭 이벤트
    • 폼 제출
    • 애니메이션

4. 실제 사용 예시

잘못된 사용 예시

// 🚫 서버 컴포넌트에서 useState 사용 시도
export default function WrongComponent() {
  const [value, setValue] = useState("")  // 에러 발생!

  return <input value={value} onChange={e => setValue(e.target.value)} />
}

올바른 사용 예시

'use client'

// ✅ 클라이언트 컴포넌트에서 useState 사용
export default function CorrectComponent() {
  const [value, setValue] = useState("")

  return <input value={value} onChange={e => setValue(e.target.value)} />
}

5. 주의사항과 best practice

1. 컴포넌트 분리

  • 상호작용이 필요한 부분만 클라이언트 컴포넌트로 분리
  • 데이터 페칭은 가능한 서버 컴포넌트에서 처리
// page.js (서버 컴포넌트)
async function Page() {
  const data = await fetchData()  // 서버에서 데이터 페칭
  return <ClientComponent initialData={data} />
}

// ClientComponent.js
'use client'
function ClientComponent({ initialData }) {
  const [data, setData] = useState(initialData)
  // 클라이언트 로직 처리
}

2. 번들 사이즈 관리

  • 클라이언트 컴포넌트는 번들 사이즈에 영향을 주므로 필요한 부분만 사용
  • 큰 라이브러리는 가능한 서버 컴포넌트에서 사용

3. 성능 고려사항

  • 서버 컴포넌트는 초기 페이지 로드 시 더 빠름
  • 클라이언트 컴포넌트는 인터랙션이 필요한 경우에만 사용

6. 성능 최적화 전략

1. 하이브리드 접근법

// ServerComponent.js (서버 컴포넌트)
export default async function ServerComponent() {
  const data = await fetchData()
  return (
    <div>
      <StaticContent data={data} />
      <ClientInteraction />
    </div>
  )
}

// ClientInteraction.js
'use client'
export default function ClientInteraction() {
  const [isOpen, setIsOpen] = useState(false)
  return <button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
}

2. Suspense 활용

import { Suspense } from 'react'

export default function Layout() {
  return (
    <div>
      <Suspense fallback={<Loading />}>
        <SlowComponent />
      </Suspense>
    </div>
  )
}

결론

'use client' 지시어는 Next.js의 서버 컴포넌트 아키텍처에서 핵심적인 역할을 합니다. 이를 효과적으로 사용하면 다음과 같은 이점을 얻을 수 있습니다:

  • 초기 페이지 로드 성능 향상
  • 서버 리소스 효율적 사용
  • 번들 사이즈 최적화
  • 더 나은 사용자 경험

서버 컴포넌트와 클라이언트 컴포넌트를 적절히 조합하여 사용하면, 최신 웹 애플리케이션에서 요구되는 성능과 사용자 경험을 모두 만족시킬 수 있습니다.

#NextJS #React #JavaScript #WebDevelopment #FrontEnd

728x90
300x250