SSR 때문에 액세스 토큰을 메모리에서 다시 쿠키로 저장해야 했다.

홍정민·2025년 5월 1일

기존의 프로젝트에서는 온전히 CSR로 리액트로 개발하였다. axios 인스턴스를 생성하여 다양한 컴포넌트에서 인스턴스를 공유하며 사용하였고, 문제 없이 API요청을 날릴 수 있었다.

그러나 NextJS를 사용하게 되면서, 기존의 서버측에서 렌더링해서 브라우저에 보여주는 새로운 시야를 경험하게 되고, 자연스럽게 서버 컴포넌트 데이터 패칭이 주는 장점을 얻기 위해 서버에서 데이터 패칭을 하게 되었다.

리액트 쿼리를 사용하여 RSC에서 데이터 패칭을 하는 방식이다.

export default async function FridgeDetailPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;

  const queryClient = new QueryClient();
  await queryClient.prefetchQuery(FridgeQueries.detailQuery(id)),

  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <FridgeDetail id={id} />
    </HydrationBoundary>
  );
}

나의 Fridge 페이지는 인증과 권한이 필요하다. Fridge와 연관된 API요청 또한 인증과 권한이 필요하다. 따라서 엑세스 토큰을 헤더에 포함시켜서 요청을 보내야 한다.

내가 엑세스 토큰을 저장하는 방법

나는 다음의 코드와 같이 엑세스 토큰을 axios.default.headers에 저장한다. 그리고 요청을 보낼 때, Authorization 헤더에 저장된 토큰을 함께 보내는 방식이다.

import axios from "..";

function issueAccessToken() {
  const response = (
    await axios.get(`${this.api}/issue-token`, { withCredentials: true }))?.data;

  axios.defaults.headers.common.Authorization = `Bearer ${response?.token}`;
}

메모리에 저장했을 때의 장점

엑세스 토큰을 axios 인스턴스에 저장했을 때 CSRF 공격을 방어할 수 있다. CSRF의 공격에서 사용자의 도메인에 저장된 쿠키의 토큰을 사용해서 사용자를 위조하게 되는데, 엑세스 토큰을 메모리에 저장하게 되면 쿠키에 토큰이 없기 때문에 위조할 수 없다.

장점 뒤에 큰 문제

문제는 RSC에서 해당 함수를 실행하여 요청을 할 때 발생한다. 왜냐하면 서버측에서는 메모리를 공유하지 않기 때문에 axios 인스턴스를 공유할 수 없다. 따라서 다음의 코드에서 RSC에서 데이터를 패칭할 때, 엑세스 토큰이 담겨져 있지 않게 된다.

await queryClient.prefetchQuery(FridgeQueries.detailQuery(id));

해결 방법 탐색

첫 번째 방법은 Fridge 페이지 부분을 완전히 CSR로 바꾸는 것이다. 그러나 이 방법은 해당 문제의 해결을 회피하는 것과 같다. 에러를 제거할 수 있다는 장점 외에, 여러가지 단점이 존재 했다.

  • RSC의 장점을 사용할 수 없음
  • Fridge의 다양한 하위 도메인에서도 CSR로 동작하도록 코드를 매 번 작성해야 한다.

해결 방법

일단 토큰의 저장 위치를 변경해야 했다. 서버측에서 작동해야 한다는 관점에서 살펴보면, 발급받은 엑세스 토큰을 서버에서 확인 할 수 있어야 한다.

따라서, 서버 측에서 읽을 수 있도록 쿠키에 저장을 해야 한다. 다음의 코드로 RSC에서 쿠키를 가져올 수 있다.

const cookieStore = await cookies();
const accessToken = cookieStore.get('access_token')?.value

이렇게 얻은 토큰을 API 요청할 때, 쿠키에 토큰을 설정하여 요청을 하면 문제를 해결할 수 있다.

결론

엑세스 토큰을 메모리에 저장하는 방식으로 RSC에서 데이터 패칭을 하면 토큰 동봉하지 않은 채 요청을 하기 때문에, 엑세스 토큰을 쿠키에 저장해서 네트워크 요청할 때 쿠키를 꺼낸 후 패칭 함수에 쿠키를 설정한 후 요청을 한다.

0개의 댓글