Next.js 프로젝트를 진행하면서 로그인 후 받은 유저 토큰을 httpOnly 쿠키에서 관리하게 되었다.
유저 인증을 위해 이 쿠키를 활용했는데, 로그아웃 시 쿠키 삭제를 위해 아래 코드를 작성했다.
"use server";
import { cookies } from "next/headers";
export const removeAuth = async () => {
const cookieStorage = await cookies();
cookieStorage.delete("accessToken");
cookieStorage.delete("refreshToken");
};
하지만 배포 후 서버에서 받은 쿠키가 삭제되지 않는 문제가 발생했다.
로그인을 카카오와 구글 소셜 로그인을 통해 진행했고, 서버에서는 소셜 로그인 성공 후 다음과 같은 방식으로 쿠키를 설정하여 리다이렉트했다.
.nebula-ai.kr
/
none
true
따라서 쿠키 삭제 시에도 정확한 옵션을 명시해줘야 했다.
아래처럼 옵션을 넣어서 작성하니 정상적으로 쿠키가 삭제되는 것을 확인했다.
"use server";
import { cookies } from "next/headers";
export const removeAuth = async () => {
const cookieStorage = await cookies();
cookieStorage.delete({
name: "accessToken",
domain: ".nebula-ai.kr",
path: "/",
sameSite: "none",
secure: true,
});
cookieStorage.delete({
name: "refreshToken",
domain: ".nebula-ai.kr",
path: "/",
sameSite: "none",
secure: true,
});
};
Next.js의 쿠키 관련 타입 정의를 통해 원인을 분석해보자.
Next.js에서는 쿠키 관리로 RequestCookies
와 ResponseCookies
클래스를 사용한다.
declare class RequestCookies {
delete(names: string | string[]): boolean | boolean[];
}
declare class ResponseCookies {
delete(...args: [key: string] | [options: Omit<ResponseCookie, 'value' | 'expires'>]): this;
}
wicg에서 제공하는 Cookie Store API를 기반으로 한 타입 정의이며, 특히 delete(name)
을 호출했을 때의 기본 동작은 다음과 같다.
옵션 | delete(name) 호출 시 기본값 | 실제 설정한 쿠키 옵션 |
---|---|---|
domain | null (호스트 전용) | .nebula-ai.kr |
path | / | / |
secure | true | true |
sameSite | strict | none |
여기서 domain이 다르고, sameSite 속성이 다르기 때문에 쿠키가 삭제되지 않았던 것이다.
example.com
, app.example.com
)즉, 기본 delete(name)
은 호스트 전용 쿠키만 삭제 가능하므로, 명시적 옵션을 넣어줘야 했다.
Next.js의 cookies()
메서드는 어떤 타입을 리턴하는지 살펴보았다.
export type ReadonlyRequestCookies = Omit<RequestCookies, 'set' | 'clear' | 'delete'> & Pick<ResponseCookies, 'set' | 'delete'>;
export declare function cookies(): Promise<ReadonlyRequestCookies>;
이 타입은 다음과 같은 특성을 가지고 있다.
RequestCookies
에서 쿠키 조작(set, clear, delete)을 빼고,ResponseCookies
의 set, delete만 추가.Next.js 개발자가 의도적으로 쿠키를 Readonly하게 관리하면서 부작용을 방지하기 위함이라고 판단된다.
이번 디버깅을 통해 Next.js의 쿠키 처리 과정을 깊이 이해할 수 있었으며, 정확한 쿠키 삭제 방법을 알게 되었다.