cookies was called outside a request scope.
// server.tsx
import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";
export function createClient() {
const cookieStore = cookies();
return createServerClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_KEY!, {
cookies: {
getAll() {
return cookieStore.getAll();
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options));
} catch {
// The `setAll` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
},
});
}
export const supabase = createClient(); // 🚨 전역에서 supabase 클라이언트를 생성
// server-actions.ts
import { supabase } from "./server"; // 🚨 전역으로 생성한 supabase 클라이언트 사용 중
export async function signin() {
const { error } = await supabase.auth.signInWithPassword();
// ...
}
이 코드를 사용해 supabase 클라이언트를 전역에서 생성하려 하자 cookies was called outside a request scope 오류가 발생했다.
이 오류는 cookies() 함수가 요청(Request)이 있을 때만 사용할 수 있는 함수이기 때문에 발생한다. 전역에서 supabase 클라이언트를 생성하려 하면서, 요청이 없는 상황에서 cookies()가 호출되었고, 그 결과 해당 오류가 발생한 것이다.
Next.js에서 cookies()는 서버에서 클라이언트의 요청에 포함된 쿠키 데이터를 가져오는 함수이다. 따라서 요청이 없을 때 전역에서 cookies()를 호출하면, Request scope가 없기 때문에 해당 함수는 사용할 수 없다.
해결 방법은 요청이 있을 때마다 새로운 supabase 클라이언트를 생성하는 것이다. 전역에서 클라이언트를 생성하지 말고, 필요한 함수 내에서 매번 클라이언트를 생성하여 요청에 맞는 쿠키 정보를 사용할 수 있도록 한다.
// server.tsx
import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";
export function createClient() {
const cookieStore = cookies();
return createServerClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_KEY!, {
cookies: {
getAll() {
return cookieStore.getAll();
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options));
} catch {
// The `setAll` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
},
});
}
// ✅ 전역에서 불러오지 않음
// server-actions.ts
import { createClient } from "./server"; // ✅ createClient 함수를 불러옴
export async function signin() {
const supabase = createClient(); // ✅ 요청마다 새로운 클라이언트를 생성
const { error } = await supabase.auth.signInWithPassword();
// ...
}
정리: Next.js에서는 요청마다 필요한 데이터를 가져와야 하기 때문에, 쿠키나 세션 같은 정보는 전역에서 다루기 어렵다. 따라서 요청이 있을 때마다 새로운 클라이언트를 생성해서 요청에 맞는 데이터를 처리하는 것이 안전하다.