Table of contents
Open Table of contents
문제 상황
Next.js 14 + next-auth0 SDK로 구성된 프로젝트에서 DB에 접근하는 Server Action을 사용할 때 서버 컴포넌트부터 의도치 않게 재 랜더링되는 문제가 발생했다.
next-auth0의 Rolling Session
auth0 SDK는 접속자의 세션을 유지하기 위해 middleware, route handler, server action에서 내부적으로 Cookie를 설정하는데, 이 때문에 서버 컴포넌트가 다시 렌더링될 수 있다. (Cookie 값이 페이지 렌더링에 영향을 주기 때문이라고 생각한다.)
getSession 함수를 실행하면 새로운 세션 쿠키를 set 하는데, 서버 컴포넌트에서 쿠키를 설정하면 sdk에서 아래와 같은 경고를 발생시킨다. (정확히는 AUTH0_SESSION_AUTO_SAVE가 false일때 무조건 경고가 나타난다.)
nextjs-auth0 is attempting to set cookies from a server component,see https://github.com/auth0/nextjs-auth0#using-this-sdk-with-react-server-components
auth0-sdk는 기본적으로 rolling session 방식으로 동작하는데, 서버 컴포넌트에서 getSession을 실행하면 세션 값을 갱신하여 쿠키에 저장한다. 그런데 서버 컴포넌트에서는 쿠키를 설정하는 것이 불가능하기 때문에 만약 프로젝트가 서버 컴포넌트만 사용하는 상황이라면 세션이 갱신되지 않을 수 있다는 경고가 발생하는 것이다.
문제 분석
아래 코드는 my-frame 프로젝트의 server action 일부이다.
export async function actionGetNextImagesById(_current_id: string, limit?: number) {
const viewerId = await actionGetUserIdBySub();
const owner = await actionGetImageById(_current_id);
return await getNextImagesById({ _id: _current_id, viewerId, ownerId: owner.owner, limit });
}
위 함수에서 actionGetUserIdBySub를 호출하고 있는데, 이 함수가 getSession을 호출하고 있다.
export async function actionGetUserIdBySub() {
const session = await getSession();
const user = session?.user;
const viewer = await actionGetUserBySub(user?.sub)
return viewer?._id;
}
Server Action에서 쿠키를 변경하면 Next.js는 페이지 전체를 (서버 컴포넌트 부터) 다시 렌더링한다.
때문에 쿠키가 변경되면서 컴포넌트가 전부 다시 렌더링되고, 불필요한 DB 호출이 발생하게 된다.
해결 방법
-
환경 변수로 AUTH0_SESSION_AUTO_SAVE=false를 설정하면 next-auth0의 rolling session을 비활성화하여 server action에서 쿠키가 설정되는 것을 막을 수 있다. 랜더링 문제는 해결되겠지만 로그인 세션이 일찍 expire 될 수 있다.
-
server action 함수에서 요구하는 userId를 매개변수로 전달한다. (action 내에서 getSession을 호출할 필요가 없도록)
두번째 해결책은 함수와 관련된 코드를 수정해야 하기 때문에 일단 첫번째 해결 방법을 적용하고 추후 Refectoring을 진행하기로 했다.
참고 자료
https://github.com/vercel/next.js/issues/50163 https://community.auth0.com/t/latest-nextjs-14-getsession-or-getaccesstoken-is-causing-re-rendering-the-entire-page-in-server-actions/126136