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.ts,app/api/*
4. 결과
- Next.js 규칙에 맞게:
- 그 결과: