[ 공모전 ] SSR : 모듈과 React-Query로 Session,HTTP 통신 받기

최문길·2024년 8월 1일
0

공모전

목록 보기
40/46
post-thumbnail

이전포스팅들과 달리 포스팅이 짧을 것같다.
개념과,이해를 설명하는데 중점적으로 설명했으며, 이제는 그것들을 가지고 적용과 활용을 할 차례이기 때문이다.

Axios 모듈화

const axiosInstance_SSR = axios.create({
  baseURL,
});
/**
 *
 * @param ctx ServerSideProps를 사용할 때 호출하는 함수입니다. 각 로그인시 데이터 통신을 할 때 사용할 axios instance 입니다.
 * @returns
 */
export const getAuthorizedAxios = async (ctx: GetServerSidePropsContext) => {
  if (!isServer) return; // 클라이언트에서 실행하지 않음
  if (axiosInstance_SSR.defaults.headers.Authorization || axiosInstance_SSR.defaults.headers.refreshToken) {
    // axiosInstance_SSR의 default header안에 token이 있으면 그냥 return 합니다.
    // 의미없는 비동기 통신안하려고 넣어놓은 조건문 입니다.
    return axiosInstance_SSR;
  }
  const req = ctx.req;
  try {
    const session = await getToken({ req });

    if (session) {
      axiosInstance_SSR.defaults.headers.Authorization = `Bearer ${session.accessToken}`;
      axiosInstance_SSR.defaults.headers.refreshToken = session.refreshToken;
    }
  } catch (error) {
    console.error('Error fetching session:', error);
  }

  return axiosInstance_SSR;
};

위와 같이 따로 axios를 사용하여 SSR에서 통신할 함수를 만들었다.

_app.tsx

export default function App({ Component, pageProps: { session, ...pageProps } }: AppProps) {
  return (
   <SessionProvider session={session}>
      <QueryClientProvider client={queryClient}>
        <HydrationBoundary state={pageProps.dehydratedState}>
          <main className={cn(myFont.variable)}>
            <CommonLayout>
              <Component {...pageProps} />
            </CommonLayout>
        </HydrationBoundary>
      </QueryClientProvider>
    </SessionProvider>

Sample - Calendar Page SSR

export const getServerSideProps: GetServerSideProps = async (ctx: GetServerSidePropsContext) => {
  const queryClient = new QueryClient();
  // accessToken, refreshToken을 탑재한 axios instance 입니다.
  const axiosInstance = await getAuthorizedAxios(ctx);
  if (axiosInstance)
    try {
      await queryClient.prefetchQuery({
        // 본인이 사용할 페이지에서 SSR로 불러오고 싶은 queryKey를 넣어주세요,
        queryKey: ['SCHEDULE_QUERY'],
        queryFn: async () => {
          const { data } = await axiosInstance.get('schedule');
          return data;
        },
      });
    } catch (err) {
      return {
        redirect: {
          destination: '/',
          permanent: false,
        },
      };
    }

  if (!axiosInstance)
    return {
      redirect: {
        destination: '/',
        permanent: false,
      },
    };
  return { props: { dehydratedState: dehydrate(queryClient) } };
};

// _app.tsx

우리 프로젝트에서 Calendar.tsx 에서 SSR을 해줘야 한다고 했어서 임시로 만들어줬다.

번외 - Session값도 SSR로 pre-fetch 받기

Next.js Page Router에서도 Session값을 SSR을 통해 ' 미리 ' 받을 수가 있다.
next-auth 를 사용했기에, next-auth에서 인증/인가 유지는 cookie를 통해서 값을 받아와 세션 유지를 진행하므로,

페이지를 호출할 때 next-auth의 메소드를 통해 server로부터 유저 세션을 받아올 수 있기 때문이다.

// index.tsx
const HomePage = () => { ... }
export const getServerSideProps = (async (ctx: GetServerSidePropsContext) => {
  const session = await getSession(ctx);
  // Pass data to the page via props
  return { props: { session: session } };
}) satisfies GetServerSideProps<{ session: Session | null }>;

// _app.tsx
 <SessionProvider session={session}> // Component 컴포넌트에 session 내려줌
  <Component {...pageProps} />
//...생략

이렇게 하면, Server로부터 받아온 값을 <SessionProvider session={session}> 에 props로 전달 해줄 수 있기 때문이다.

그리고 Layout.tsx

const Layout = ()=> {
  const session = useSession()
  //...로직
}

해주면 pre-fetch를 받아오기에 useQuery 등 인가 통신에 필요한 값을 빠르게 받아올 수 있다. 그리고 새로고침시에도 깜빡임(조건부)도 사라지게 된다.

마무리

SSR 로직을 작성하면서
Next.js는 기본적으로 서버로부터 파일을 만들기에, sessionStorage , localStorage가 없다는 점을 다시 한번 알게 되었다.
뿐만 아닌, document , window와 같은 전역객체를 불러들이려면 useEffect와같은 훅, 또는 server가 아닐 때의 조건부 로직으로 처리해야 한다는 점을 다시 한번 더 깨닫게 되었다.

hydration과 serializing, React-Query의 cache등 여러 가지를 배우면서

SWR을 사용할 지 react-query를 사용할 지를 고민 하는 것보단 react-query의 전반적인 내용을 안 이후에 SWR을 도전하는 것이 낫겠다라는 생각도 든다.

3개의 댓글

comment-user-thumbnail
2024년 8월 1일

서버단에서 pre-fetch하여 react query와 같이 사용할 때 가장 문제가 되는 점은 캐싱이 되지 않는겁니다. 참고 바랍니다.

https://until.blog/@love/서버-컴포넌트와-tanstack-query-사용기

2개의 답글

관련 채용 정보