Server Component에서 쿠키를 저장했는데 브라우저에 남지 않은 이유
문제 발생
첫 방문자에게 테마 쿠키를 심으려고 페이지에서 바로 설정했습니다.
export default async function Page() {
const cookieStore = await cookies();
if (!cookieStore.has("theme")) {
cookieStore.set("theme", "light"); // 여기서 오류
}
return <Dashboard />;
}응답 헤더에 Set-Cookie가 없었고, 다음 요청에도 쿠키는 그대로 없었습니다.
원인 분석
HTTP 순서 때문입니다. Next.js 문서가 이유까지 적어둡니다 — HTTP는 스트리밍이 시작된 뒤에 쿠키를 설정하는 것을 허용하지 않으므로, .set은 Server Function이나 Route Handler에서 사용해야 합니다.
Server Component 렌더링은 이미 응답 본문을 만드는 단계입니다. 헤더는 그 전에 확정되어 나가므로 그 시점에 Set-Cookie를 덧붙일 자리가 없습니다.
문서는 개념도 함께 정리합니다 — 읽기는 브라우저가 요청 헤더로 보내준 데이터를 보는 것이라 Server Component에서 동작하고, 쓰기는 Server Component 렌더링 중에는 지원되지 않습니다. 쿠키를 수정하려면 클라이언트에서 Server Function을 호출하거나 Route Handler를 사용합니다. 서버는 Set-Cookie 헤더로 지시만 할 수 있고 실제 저장은 브라우저가 합니다.
.delete도 같은 제약입니다. 문서는 추가로 .set을 호출한 것과 같은 도메인, 같은 프로토콜에서 실행되어야 한다고 적습니다.
해결 방안
- 사용자의 행동으로 바뀌는 값은 Server Action에서 씁니다. 폼 제출이나 토글이 그 계기입니다.
"use server";
export async function setTheme(theme: string) {
(await cookies()).set("theme", theme, { path: "/", httpOnly: false });
}-
요청 단계에서 결정해야 하면 Route Handler나
proxy.ts로 옮깁니다. 첫 방문 식별자처럼 렌더 전에 정해져야 하는 값이 여기 해당합니다. -
읽기만 하는 곳에서는
await를 잊지 않습니다. 문서 그대로cookies는 프로미스를 반환하는 비동기 함수이며, Next 16에서는 동기 접근이 동작하지 않습니다. -
쿠키를 읽으면 라우트가 동적이 된다는 것을 감안합니다. 문서 설명대로
cookies는 요청 시점 API라 레이아웃이나 페이지에서 사용하면 그 라우트가 동적 렌더링으로 전환됩니다. 전 페이지 공통 레이아웃에서 무심코 읽으면 사이트 전체가 동적이 됩니다. -
Server Action에서 쿠키를 바꾼 뒤 화면 데이터도 갱신해야 하면
revalidatePath/revalidateTag를 같은 함수 안에서 호출합니다. 문서가 안내하는 순서입니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.