본문 바로가기
Insights/Troubleshooting

[SwimX] Next.js 서버 컴포넌트와 인증 분리로 NextAuth 에러 해결 🛠️

by suyeonnie 2025. 4. 3.

 

 

TL;DR

 

Next.js App Router(15+), Supabase로 진행하는 프로젝트에서 서버 컴포넌트로 작성한 헤더 내부에서 NextAuth의 useSession()을 사용하자 런타임 에러가 발생했다. SessionProvider가 필요한 클라이언트 컴포넌트를 서버 트리에서 렌더링했기 때문이었다.

 

해결을 위해 인증 UI 컴포넌트(로그인 버튼)만 클라이언트로 분리하고, layout.tsx에서는 <Header>와 children 모두를 <SessionProvider>로 감싸는 구조로 수정했다.

 

 

문제 상황

 

  • 기술 스택: Next.js 15 App Router, NextAuth(Credentails), Supabase(DB전용, 인증은 NextAuth 처리)
  • 목표: SSR이 가능한 <Header>를 서버 컴포넌트로 유지하면서 로그인/로그아웃 버튼은 useSession() 사용해 렌더링
  • 발생한 에러:
Error: [next-auth]: `useSession` must be wrapped in a <SessionProvider />
⨯ [Error: React Context is unavailable in Server Components]

 

 

원인 분석

1. React Context는 클라이언트 컴포넌트에서만 작동

 

  • useSession()은 SessionProvider 가 제공하는 context를 사용함
  • 서버 컴포넌트인 헤더 내부에서 useSession()을 직접 호출하면 context가 존재하지 않아 오류 발생

2. SessionProvider 자체가 클라이언트 전용 컴포넌트

 

  • layout.tsx는 기본적으로 서버 컴포넌트
  • 따라서 SessionProvider를 직접 layout.tsx에 넣으면 내부적으로도 context가 전달되지 않아 에러 발생

 

 

해결

 

  • SessionProvider를 'use client'가 선언된 클라이언트 컴포넌트(Providers.tsx)로 분리
  • layout.tsx에서 Providers로 감싸되 헤더 컴포넌트와 children 모두를 포함
  • 헤더는 서버 컴포넌트로 유지
  • 헤더 내부의 로그인 UI만 클라이언트 컴포넌트(HeaderAuthSection.tsx)로 분리
// app/layout.tsx
<Providers>
  <Header />            ← 서버 컴포넌트지만 내부에 클라 컴포넌트 있음
      └── HeaderAuthSection (클라이언트, useSession() 사용)
  {children}
</Providers>

 

 

 

// app/providers.tsx
'use client';

import { SessionProvider } from 'next-auth/react';

export function Providers({ children }: { children: React.ReactNode }) {
  return <SessionProvider>{children}</SessionProvider>;
}

 

// components/common/Header.tsx (서버 컴포넌트)
import HeaderAuthSection from '../auth/HeaderAuthSection';

export default function Header() {
  return (
    <header>
      <nav>...</nav>
      <HeaderAuthSection />
    </header>
  );
}

 

 

회고

 

  • App Router에서 서버/클라이언트 컴포넌트 분리 설계는 중요하다
    • 서버 컴포넌트는 클라이언트 컴포넌트 포함 가능 (Next.js 규칙)
    • 그 반대는 불가능
  • 인증/세션 등 클라이언트 상태가 필요한 요소는 클라이언트 컴포넌트로 분리하기
  • 결과적으로 헤더는 SSR로 유지하면서, 내부 인증 UI만 클라이언트 분리함

 

다음 계획

 

테스트 계정 로그인 기능 추가 (게스트 로그인)