Backgrounds
회원가입 후, 백엔드에서 반환한 access, refresh 토큰을 cookie에 저장해야 했습니다.
// SignUpForm
const SignUpForm = () => {
const handleSubmit = async () => {
try {
// 회원가입 성공 시 AT, RT 반환
const { accessToken, refreshToken } = await signUpApi(form);
setAuthCookies(accessToken, refreshToken)
router.replace("/")
} catch (e) {
setErrors(e);
}
};
return <form onSubmit={handleSubmit} >(...)</form>
}
위 코드에서처럼, 회원가입 Form 제출 시 회원가입 요청(signUpApi)을 보내고
setAuthCookies 함수를 통해 반환받은 access, refresh 토큰을 cookie에 저장했습니다.
그 후 메인 페이지로 이동(router.replace)해 정상적으로 서비스를 이용할 수 있게 했습니다.
// utils/auth-token.ts
"use server";
import { cookies } from "next/headers";
import { AuthKeyName } from "@/shared/constant";
export async function setAuthCookies(
accessToken: string,
refreshToken: string
) {
cookies().set('access-token', accessToken, options)
cookies().set('refresh-token', refreshToken, options)
return;
}
setAuthCookies 함수는 서버 액션(use server 지시어 사용)으로 작성했고,
next.js에서 제공하는 cookies API를 통해 cookie에 인증 관련 토큰을 저장할 수 있도록 했습니다.
Problems
위 코드들은 코드상으로도 아무런 문제가 없어 보이고, 개발 환경에서도 정상적으로 동작합니다.
하지만 해당 프로덕션에서 직접 회원가입을 테스트해본 결과...
router로 이동한 페이지의 서버 컴포넌트가 2~3번 정도 reload 되는 현상이 있음을 발견했습니다.
// page.ts
export const page = async () => {
// 서버에서 여러번 실행 => 복수개 워크스페이스 생성!?
const workspace = await getOrCreateWorkspaceApi()
(...)
}
이 때 메인 페이지(서버 컴포넌트)에는 서버로부터 워크스페이스를 조회하고, 존재하지 않을 경우 생성하는 함수가 존재했고,
이로 인해, 회원가입 후 메인 페이지 접근 시 워크스페이스가 복수개 생성되어 버리는 문제가 연이어 발생했습니다.
Cause
이런 저런 테스트 결과 내부적인 로직 문제는 아닌 것 같아, 관련된 이슈를 검색했습니다.
https://github.com/vercel/next.js/issues/50163
아하...
next.js 14 이상 버전에서 서버 액션을 통한 쿠키 설정 시, 의도하지 않은 페이지 리렌더링이 발생하는 이슈가 존재함을 확인할 수 있었습니다.
Solutions
https://nextjs.org/docs/pages/building-your-application/routing/api-routes
api route를 통해 cookie를 설정하는 방식으로 문제를 우회할 수 있었습니다.
// api/auth/set-token
import { NextResponse } from "next/server";
import { setAuthCookies } from "@/utils/auth-token";
export async function POST(request: Request) {
try {
// 클라이언트에서 전달된 데이터 추출
const { accessToken, refreshToken } = await request.json();
// 쿠키에 토큰 저장하는 함수 호출
setAuthCookies(accessToken, refreshToken);
// 성공적인 응답 반환
return NextResponse.json({ success: true });
} catch (error) {
return NextResponse.json(
{ success: false, message: "Failed to set tokens" },
{ status: 500 }
);
}
}
위와 같이 auth token을 cookie에 저장하는 api route를 생성한 후
// SignUpForm
const SignUpForm = () => {
const handleSubmit = async () => {
try {
// 회원가입 성공 시 AT, RT 반환
const { accessToken, refreshToken } = await signUpApi(form);
// api route를 통한 cookie 설정
await fetch("/api/auth/set-token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ accessToken, refreshToken }),
});
router.replace("/");
} catch (e) {
setErrors(e);
}
};
return <form onSubmit={handleSubmit} >(...)</form>
}
form 제출 시 해당 api로 fetch 요청을 보내, 의도대로 cookie가 설정될 수 있도록 했습니다.
'source-code > Next JS' 카테고리의 다른 글
[next js] app directory에서 token 저장하기 - (2) (1) | 2024.08.05 |
---|---|
[next js] server component 페이지 route 속도 개선하기 (with streaming) (1) | 2024.07.23 |
[next js] App Router Fetch Cache가 동작하지 않을 때 (0) | 2024.03.11 |
localhost fetch시 ECONNREFUSED 에러 해결하기 (0) | 2024.03.07 |
[next js] app directory에서 token 저장하기 (0) | 2024.02.13 |