개발자

NextJS 14에서 JWT를 쿠키를 통해 관리하려고 하는데 서버에서 set-cookie 해주는 방식말고 route 핸들러에서 주입할수는 없나요?

2024년 04월 03일조회 1,057

안녕하세요. 최근 NextJs를 공부하며 이전 리액트 기반의 사이드 프로젝트를 NextJs로 구현해보고 있습니다. 카카오 로그인만 지원을 하고 있고, 프론트 쪽에서 카카오 인가 코드를 백엔드로 넘기면 백에서 jwt를 발급해서 응답으로 access token과 refresh token을 프론트로 넘겨주고 있습니다. 이전 프로젝트에서는 두 토큰 모두 localStorage에 저장하는 방식으로 했었는데요, 이번에는 쿠키를 이용해보려고 하고 있습니다. 다만 백엔드에서 set-cookie를 해놓지 않아서 응답으로 받은 토큰을 따로 쿠키에 저장해야하는 상황입니다. 하지만 Server Component에서는 set cookie가 안되는 것으로 알고 있습니다. <목표 구현 방식> route handler를 통해서 백엔드 api를 호출하고 그 값을 쿠키에 저장하도록 코드를 짰습니다. (/app/api/token/route.ts) return 값은 확인을 위해서 임의로 넣었습니다. 그리고 쿠키에 저장된 토큰을 통해서 서버 컴포넌트에서 이를 이용해 백엔드 api 통신을 하고 싶습니다. 하지만 서버 컴포넌트에서 쿠키를 확인하니 비어있는 쿠키인 것을 알 수 있었습니다. 얕은 지식으로 생각을 했을때, (route handler - 브라우저 혹은 서버 컴포넌트)에서 생성한 쿠키는 (백엔드 도메인 - 브라우저 혹은 서버 컴포넌트) 통신에 사용되는 쿠키와 다르기 때문이라고 생각이 들었는데 해답을 찾지 못했습니다. <질문 사항> - 백엔드 서버에서 set-cookie를 하지 않고 직접 구현할 순 없을까요? 쿠키는 forwarding이 안되나요? - 제가 생각한 구조 말고 추천하시는 토큰 관리 방식에 대해서 알려주셔도 감사하겠습니다. 아직 초보 개발자에 글도 잘 쓰지 못해 이해하시기 힘들 것 같지만, 넓으신 아량으로 지식을 나눠주신다면 정말 큰 도움이 될 것 같습니다. 긴글 읽어주셔서 감사합니다 (_ _)

1// /app/api/token/route.ts
2export async function GET(req: NextRequest) {
3  const cookieStore = cookies();
4  const authCode = req.nextUrl.searchParams.get("code");
5  const res = await fetch(`${SERVER_URL}/auth/login/kakao?code=${authCode}`, {
6    method: "GET",
7    headers: {
8      "Content-Type": "application/json",
9    },
10  });
11  const data = await res.json();
12  cookieStore.set("accessToken", data.data.accessToken, { httpOnly: true });
13  cookieStore.set("refreshToken", data.data.refreshToken, { httpOnly: true });
14
15  const at = cookieStore.get("accessToken")?.value;
16  const rt = cookieStore.get("refreshToken")?.value;
17
18  return Response.json({
19    data: { accessToken: at, refreshToken: rt },
20  });
21}
22
23
24// /app/oauth/callback/kakao/page.tsx
25async function getToken(authCode: string | string[]) {
26  const response = await fetch(
27    `http://localhost:3000/api/token?code=${authCode}`,
28    {
29      method: "GET",
30    },
31  );
32
33  const json = await response.json();
34  return json;
35}
36
37export default async function Page({ searchParams }: Props) {
38  const { code } = searchParams;
39  if (!code) redirect("/login");
40
41  await getToken(code);
42
43  return <div>Page</div>;
44}
이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 1

안희수님의 프로필 사진

response 에 쿠키를 담는 것은 저도 시도해 보았지만 METHOD POST 방식에서는 그 방식이 좀 문제가 있어서 json 형식으로 넘겨받아서 사용했습니다 그리고 쿠키는 이제 점진적으로 폐지되어가는 추세인지라 인터셉터로 받아서 처리하는 방식을 한번 찾아보시면 어떨까 합니다

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2024년 04월 03일

Next.js에서 서버 컴포넌트는 모두 일관된 도메인에서 실행됩니다. 즉, 브라우저가 로드한 페이지와 API 요청들이 모두 같은 도메인에서 발생하므로 Cookie에 대한 접근이 가능합니다. 하지만 문제는 서버사이드 렌더링 (SSR) 시에는 특정 요청과 연관된 쿠키를 Node.js 서버에서 직접 처리해야 한다는 것입니다. 그래서 백엔드에서 Set-Cookie를 이용해 응답을 수신할 경우 프론트엔드(브라우저 혹은 Next.js 서버) 에서 해당 쿠키를 저장하게 됩니다. 반면 직접 구현한다는 건 브라우저에서 JavaScript를 사용하여 document.cookie 객체에 토큰 값을 설정하는 것을 말하며, 이럴 때는 HttpOnly 옵션을 사용할 수 없습니다. HttpOnly 속성이 있는 쿠키값은 클라이언트 사이드 스크립트(Javascript)로 접근할 수 없고 서버쪽으로만 값이 전송됩니다. 주로 세션을 관리하기 위해서 혹은 XSS(Cross-site scripting) 공격 방어를 위해 사용됩니다. 따라서, 엄격한 보안 요건이 필요한 경우에는 서버측에서 set-cookie를 사용하는 것이 좋습니다. 만약 백엔드에서 set-cookie 없이 구현하려고 한다면, Fetch API 어디에서든 credentials 옵션을 'include'로 설정하여 쿠키가 포함된 요청을 보내야 합니다. 추가적으로 토큰 관리 방식으로는 localStorage에 저장하는 것 외에도 session storage나 IndexedDB등을 이용할 수도 있습니다. 다만 이들은 모두 XSS 공격의 위험성이 있어 적절한 보안 조치가 필요합니다. API route handler의 경우 context의 res 객체를 통해 직접 쿠키를 설정할 수 있습니다. 하지만 이렇게 할 경우 XSS 공격에 노출될 위험이 있기 때문에 보안 대책이 필요합니다. 마지막으로 JWT 토큰은 가능한 서버 사이드에서 관리되어야 합니다. 클라이언트 사이드에서 관리하게 되면 CSRF, XSS와 같은 보안 문제에 노출될 가능성이 매우 높습니다.

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!