본문으로 건너뛰기
개발 머꼬
개발 노트Nuxt.js
hohyeon.dev23

브라우저에서는 되는데 첫 SSR 요청만 401이 난 이유

  • #Engineering Note
  • #Nuxt.js
  • #Security

문제 발생

로그인 후 새로고침하면 화면이 잠깐 비어 있다가 채워졌습니다. 서버 로그에는 첫 요청만 401이 찍혔습니다.

const { data } = await useFetch("https://api.example.com/me");

같은 코드가 클라이언트 내비게이션에서는 정상이었습니다.

원인 분석

SSR 중의 fetch는 브라우저가 보내는 요청이 아닙니다. 서버에서 도는 코드에는 사용자의 쿠키 저장소가 없고, 인증 쿠키는 브라우저가 Nuxt 서버로 보낸 들어온 요청 헤더 안에 있습니다. 그 헤더를 다음 요청으로 옮겨 담지 않으면 익명 요청이 됩니다.

Nuxt 문서는 상대 경로에 한해 이걸 자동으로 해준다고 적습니다 — 서버에서 상대 URL을 요청할 때 Nuxt가 useRequestFetch를 사용해 헤더와 쿠키를 프록시합니다. 그래서 /api/me는 되는데 https://api.example.com/me는 안 되는 차이가 생깁니다.

외부 API로 보낼 때는 직접 넘겨야 하고, 문서는 그 방법으로 useRequestHeaders(['cookie'])로 쿠키에 접근해 API로 보내는 것을 안내합니다.

해결 방안

  1. 내부 API는 상대 경로로 부릅니다. 가장 단순하고, 헤더 전달이 기본으로 동작합니다.
const { data } = await useFetch("/api/me");
  1. 외부 API에는 필요한 헤더만 골라 넘깁니다. 전부 넘기지 않습니다 — hostcontent-length 같은 헤더를 그대로 전달하면 상대 서버가 오작동합니다.
const headers = useRequestHeaders(["cookie"]);
const { data } = await useFetch("https://api.example.com/me", { headers });
  1. 여러 곳에서 필요하면 useRequestFetch로 감쌉니다. 요청 컨텍스트가 붙은 fetch 인스턴스를 돌려주므로 호출부마다 헤더 조립을 반복하지 않습니다.

  2. 어디로 새는지 확인합니다. 쿠키를 넘기는 코드는 서드파티 도메인에 사용자 인증 정보를 보내는 코드이기도 합니다. 신뢰하는 백엔드에만, 필요한 쿠키만 보냅니다.

  3. "클라이언트에서만 부르면 되지 않나"는 마지막 선택지로 둡니다. { server: false }로 넘기면 401은 사라지지만 초기 HTML에서 그 내용이 통째로 빠집니다. 검색 노출이 필요한 콘텐츠라면 대가가 큽니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.