본문 바로가기

programming/React

Next.js App Router SSR 용 fetch 코드 (헤더 쿠키, Authorization 세팅)

 

SSR 용 Fetch 인스턴스

 

구현 내용

  1. https://mypage.com/kr/ko" 와 같이, /[country]/[language] 정보를 url params 로 제공한다.
  2. 상품 디테일 페이지를 서버사이드 랜더링으로 제공한다.
  3. 상품 디테일 정보는 국가/언어 에 따라 달라진다.
  4. 국가/언어 정보를 HTTP 요청 헤더에 Country, Language 를 키값으로 전달한다.
  5. 상품 "좋아요"/"위시리스트" 등과 같은 유저 데이터를 제공하여야한다.
  6. 게스트는 쿠키의 "DJSESSION" 값 으로 유저 데이터를 제공한다 -> Cookie 를 헤더에 담아서 전송

 

코드

"use server";

import { cookies } from "next/headers";
import { getServerSession } from "next-auth";

import { CustomError } from "./customError";

interface FetchOptions extends RequestInit {
  headers?: HeadersInit;
}

const serverFetch = async (url: string, country: string, lang: string): Promise<Response | undefined> => {
  const headers: HeadersInit = {
    "Content-Type": "application/json",
    Country: country || "us",
    Language: lang || "en",
    Cookie: cookies().toString(), // DJSESSION SSR
  };

  const fetchOptions: FetchOptions = {
    headers,
    credentials: "include",
  };

  try {
    const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}${url}`, fetchOptions);

    if (response.status === 500) {
      throw new CustomError(`Undefined Error ${response.statusText}`, response.status);
    }

    if (response.status >= 400) {
      const errorData = await response.json();
      const error = new CustomError(errorData.message, errorData.status);
      throw error; // catch 로 빠짐
    }

    return response;
  } catch (error) {
    // Promise 자체가 rejected (network error, CORS 등)
    throw error;
  }
};

export { serverFetch };

 

Page 코드

app/[country]/[lang]/item/[id]/page.tsx

import Pdp from "@/components/pages/Pdp";
import { getProductWithSSR } from "@/shared/queries/pdp";

interface Params {
  params: {
    country: string;
    lang: string;
    sku: string;
  };
}

export default async function DetailPage({ params }: Params) {
  const { country, lang, sku } = params;

  // SSR - Country / Lang 전달
  const productDetail = await getProductWithSSR({ sku, country, lang });

  return (
    <section>
      <Pdp productDetail={productDetail} />
    </section>
  );
}

 

Query 코드

export const getProductWithSSR = ({ sku, country, lang }: PropductProps) =>
  serverFetch(`/service/catalog/product/${sku}`, country, lang)
    .then((response) => response?.json())
    .then((data) => data.data);

 

Description

1. page 에서 params 를 통해서 country / language 정보를 얻고, 이를 getProductWithSSR 쿼리 함수에 전달한다