Trouble Shooting
2025년 12월 03일

Supabase 사용시 쿠키 사용 에러

트러블슈팅: Cookies can only be modified in a Server Action or Route Handler 에러


1. 문제

  • 에러 메시지Cookies can only be modified in a Server Action or Route Handler.
  • 상황

2. Next.js 관점의 핵심 원인

Next.js App Router의 cookies()는 실행 환경에 따라 권한이 다름.

  • 서버 컴포넌트 / RSC (layout.tsx, 페이지 등)
  • Server Action / Route Handler (app/actions/*app/api/*)

즉, “쿠키를 수정하는 Supabase 클라이언트를 서버 컴포넌트에서 사용한 것” 이 에러의 본질이다.


3. 수정 전략: 용도별 Supabase 클라이언트 분리

3-1. RSC 전용: 쿠키 읽기 전용 Supabase 클라이언트

// shared/lib/supabase/server.tsexport function createServerComponentClient() { const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY if (!supabaseUrl || !supabaseAnonKey) { throw new Error('Missing Supabase environment variables') } const cookieStore = cookies() as any return createSupabaseServerClient(supabaseUrl, supabaseAnonKey, { cookies: { get(name: string) { return cookieStore.get(name)?.value }, set() { // RSC에서는 쿠키 수정 금지 → NO-OP }, remove() { // RSC에서는 쿠키 수정 금지 → NO-OP }, }, }) }
  • 사용처 예시: app/layout.tsx
// app/layout.tsximport { createServerComponentClient } from '@/shared/lib/supabase' const supabase = createServerComponentClient() const { data: { user }, } = await supabase.auth.getUser()

3-2. Server Action / Route 전용: 쿠키 읽기 + 쓰기 Supabase 클라이언트

// shared/lib/supabase/server.tsexport async function createServerClient() { const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY if (!supabaseUrl || !supabaseAnonKey) { throw new Error('Missing Supabase environment variables') } const cookieStore = cookies() as any return createSupabaseServerClient(supabaseUrl, supabaseAnonKey, { cookies: { get(name: string) { return cookieStore.get(name)?.value }, set(name: string, value: string, options?: any) { cookieStore.set(name, value, options) }, remove(name: string, options?: any) { cookieStore.set(name, '', { ...(options || {}), maxAge: 0, }) }, }, }) }
  • 사용처 예시: app/actions/auth-actions.tsapp/api/*

4. 결과

  • Next.js 규칙에 맞게:
  • 그 결과: