SSR를 이용하여 리다이렉트 방식 수정하기

공상현 (Kong Sang Hyean)·2024년 1월 29일
1

study

목록 보기
2/4

개요

현재 진행 중인 사이드 프로젝트에서 로그인 기능을 추가하면서 다음과 같은 피드백을 받았습니다.

페이지 접근을 처리하는 시간이 많이 소요되어서 시간 단축을 위해 랜더링이 끝나기 전 접근을 처리 하는 방식으로 변경했으면 좋겠어요.

'use client';

/*...*/

export default function Login() {
    const { data: session } = useSession(); // 로그인 정보를 알려준다.
    const router = useRouter();
    useEffect(() => {
        const error = params.get('error');
        if (session && session.user) {
            router.push('/');
        }
        if(error !== null && error !== undefined) {
            alert('로그인 요청 실패 : ' + error);
        }
    }, [session]);
    
 	/*...*/
 }

피드백 전 코드

기존의 방식은 위와 같이 useEffect() 에서 브라우저 내 토큰의 유무에 따라 판단하는 방식으로 작성하였습니다. useEffect()같은 경우 서버 랜더링 도중에는 실행되지 않고 랜더링 이후에 실행이 되어 처리 시간이 많이 소요 된 것을 알게 되었습니다.

위의 피드백을 해결하기 위해 Next.js 의 특징 중 하나인 Server Side Randering (줄여서 SSR)을 활용 하기로 하였습니다. SSR에 대해서 어느 정도 알고 있었지만 다시 개념을 복습도 할 겸 Next.js 13 이후에서는 어떻게 코드를 작성해야 하는지 알아보기 위해 SSR에 대하여 조사 및 스터디를 진행하였습니다.


SSR(Server Side Rendering) 이란?

제가 생각했던 서버사이드 랜더링은 기존 Client Side Rendering처럼 클라이언트에서 서버로 요청 및 응답 이후 랜더링을 진행하는 것과는 달리 서버에서 미리 데이터를 불러와서 랜더링을 하는 것으로 알고 있었습니다.

조사를 한 결과 SSR은 웹 페이지를 브라우저에서 렌더링하는 대신 서버에서 랜더링하여 렌더링된 페이지를 클라이언트에 보내는 것을 의미 한다고 합니다.

추가로 서버사이드 랜더링은 다음과 같은 특징들이 있다는 것을 알게 되었습니다.

  • 클라이언트의 인터넷 연결이 좋지 않거나 갱신이 오래될 경우 유리한 방법입니다.
  • 검색 엔진 최적화에서 중요한 역할을 하며 웹 페이지의 색인을 올바르게 생성합니다.
  • 페이지를 더 빠르게 로드하여 더 나은 사용자 경험을 제공합니다.

위와 같이 SSR에 대하여 조사를 하게 되면서 단순히 서버에서 데이터만 보내지는 것이 직접 페이지가 랜더링 되어 클라이언트에 보내진다는 방식이라는 것을 정확히 알게 되었고 위의 방법을 통하여 다양한 활용 예시가 있다는 것을 알게 되었습니다.

이미지 참조

Next.js 공식 문서 내의 캐싱 과정 이미지를 살펴보면 서버 내에 Full Route Cache 라는 단계에서 페이지가 랜더링 된 후 랜더링 된 페이지를 클라이언트로 보낸다는 것을 알 수 있습니다.

Next.js에서 SSR는 어떻게 사용될까?

Next.js에서 13 이전(/page 디렉토리)에서 서버사이드 랜더링 처리는 getServerSideProps 를 활용하여 사용하였습니다. 하지만 제가 사용하는 프로젝트 같은 경우 Next.js 13 이상(/app 디렉토리) 을 사용하고 있기 떄문에 13 이상에서는 어떻게 사용하게 되는지 확인해볼 필요가 있었습니다.

공식 문서에 따르면 Next.js 13 이상에서는 서버 컴포넌트 ("use server";)에서 랜더링된 페이지 내에 fetch를 이용하여 사용된다는 것을 알게 되었습니다.

async function getData() {
  const res = await fetch('https://api.example.com/...')
  
  if (!res.ok) {
    throw new Error('Failed to fetch data')
  }
 
  return res.json()
}
 
export default async function Page() {
  const data = await getData()
 
  return <main></main>
}

next.js 공식 문서에서 나와있는 예시

또한 fetch 내 다음과 같은 옵션을 이용할 수 있습니다.

  • cache : 데이터 캐싱 방식을 수정한다.
fetch('https://...', { cache: 'force-cache' })
  • revalidate : 요청된 리소스의 제한 시간을 설정합니다.
fetch('https://...', { next: { revalidate: 3600 } })
  • tags : 요청시 태그를 지정할 수 있습니다.
const res = await fetch('https://...', { next: { tags: ['collection'] } })

SSR를 이용하여 피드백 적용하기

우선 로그인 페이지에 SSR를 적용하기 위하여 각 랜더링되는 페이지 별로 분리하는 작업이 필요했습니다. 아래의 그림과 같이 page.tsx는 Server Rendering 파일로 나머지 컴포넌트는 따로 컴포넌트 폴더를 생성하여 Client Rendering 파일로 정리하였습니다.

Server Rendering 파일로 변경한 page.tsx 내에서는 비동기 함수를 이용하여 다음과 같이 랜더링 전 로그인 정보를 확인하는 로직으로 변경하였습니다.

const checkLogin = async () => {
    if (cookies().get("loginUser")) {
        redirect('/');
    }
    return ;
}

export default async function Login() {
    const test = await checkLogin();
    return (<>
        {LoginPage()}
    </>)
}

SSR로 변경 결과 로그인 된 상태에서 로그인 페이지 접속시 지연 없이 바로 메인페이지로 리다이렉트 되었습니다.

추후 위와 방법을 이용하여 권한이 필요한 페이지를 라우팅할 시 리다이렉트를 처리하는 로직을 개발할 예정입니다.

참고
What is server-side rendering?
Caching in Next.js
Data Fetching, Caching, and Revalidating

profile
개발자 같은 거 합니다. 1인분 하는 개발자로서 살아갈려고 노력 중입니다.

0개의 댓글