ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Next.js] CSR vs SSR (그리고 SSG)
    Frontend/React 2022. 2. 20. 00:12

    Next.js는 리액트 프레임워크로, 아래 리액트가 가진 문제점에 대한 솔루션을 제공한다. 

    • CSR으로 유저가 첫 화면을 보기까지 시간이 오래 걸린다.
    • SEO를 활용할 수 없다.

     

    Next.js가 공식문서에서 "최고의 개발자 경험"을 위해 제공하는 기능은 다음과 같다.

    • 직관적인 페이지 기반 라우팅 시스템 (동적 경로 지원 포함)
    • 사전 렌더링 , 정적 생성 (SSG) 및 서버 측 렌더링 (SSR) 모두 페이지 단위로 지원
    • 더 빠른 페이지 로드를 위한 자동 코드 분할
    • 최적화된 프리페칭을 통한 클라이언트 측 라우팅
    • 내장 CSS 및 Sass 지원 및 모든 CSS-in-JS 라이브러리 지원
    • Fast Refresh 를 지원하는 개발 환경
    • 서버리스 함수로 API 엔드포인트를 빌드하기 위한 API 경로
    • 완전히 확장 가능

     

    그렇다면 먼저 Next.js의 특징에 알아보기 전에, 앞서 나온 용어의 개념에 대해 짚고 넘어가보자.

     

    Framework vs Library

    Framework는 개발 시 필수적인 코드, 알고리즘, 데이터베이스 연동 등 뼈대나 기반이 제공되며 개발자는 정해진 규칙에 맞춰 코드를 작성한다. next.js는 프레임워크에 속한다. 

     

    Library는 단순 활용 가능한 도구들의 집합을 의미한다. 개발자가 직접 호출하여 사용한다. 대표적인 예로 리액트가 있다.

     

    프레임워크와 라이브러리의 차이점은 제어 흐름에 대한 주도성에 있는데 프레임워크는 전체적인 흐름을 자체적으로 가지고 있고 개발자가 여기에 맞게 코드를 쓰는 반면, 라이브러리는 개발자가 필요한 라이브러리를 호출하여 가져다 쓰면서 개발자가 흐름에 대한 제어를 직접 한다.

     

    CSR vs SSR

    Client Side Rendering이란 렌더링이 클라이언트 쪽에서 일어난다. 서버는 요청을 받으면 클라이언트에 HTML과 JS를 보내준다. 클라이언트는 그것을 받아 렌더링을 시작한다. 자바스립트가 모두 다운로드 되고 실행이 끝나기 전까지 유저에게 빈 화면이 노출된다.

     

    Server Side Rendering이란 서버쪽에서 렌더링 준비를 끝마친 상태로 클라이언트에 전달하는 방식이다. 클라이언트에 전달되는 순간,  HTML은 즉시 렌더링 되고 클라이언트가 자바스크립트를 다운받기 전까지 화면은 보이지만 조작은 불가하다. SEO를 활용할 수 있다.

     

    Next.js는 SSR을 제공하며 기본적으로 pre-rendering을 하여 사전에 미리 HTML 문서를 생성해 가지고 있다가 서버의 요청이 들어오면 그에 맞는 페이지를 반환한다. 사전 렌더링은 두 가지 형태로 나눠져 있는데 자세한 내용은 아래 특징에서 살펴보자.

     

    https://nextjs.org/learn/basics/data-fetching/pre-rendering

     

    2가지 형태의 사전 렌더링 (SSG & SSR)

    Next.js에서는 Static Site RenderingServer Side Rendering의 2가지 형태의 사전 렌더링 방식이 있다.

     

    1. Static-Generation (추천) : HTML을 빌드 타임에 각 페이지별로 생성하고 해당 페이지로 요청이 올 경우 이미 생성된 HTML 문서를 반환한다.
      • 퍼포먼스에 집중 (CDN을 통해 더 빠른 응답 가능)
      • 마케팅 페이지 / 블로그 게시물 / 제품의 목록 등과 같이 정적 생성하여 각 요청에 동일한 문서를 반환할 수 있는 경우
    2. Server-Side-Rendering : 요청이 올 때 마다 해당하는 HTML 문서를 그때 그때 생성하여 반환한다.
      • 항상 최신 상태를 유지해야 하는 경우 (요청에 따라 응답해야 할 내용이 시시각각 변함)
      • 제품의 상세 페이지 / 분석 차트 등 요청 마다 다른 내용 또는 형식의 HTML 문서가 반환되는 경우

     

    https://nextjs.org/learn/basics/data-fetching/two-forms

     

    적용하기

    SSG 적용하기

    데이터 없는 정적 생성 / 데이터를 사용한 정적 생성 2가지 방법이 있다. 

     

    데이터 없는 정적 생성

    기본적인 페이지는 정적 생성의 방식으로 페이지를 미리 렌더링 한다. Next.js는 빌드 시 페이지당 하나의 HTML 파일을 생성한다.

    function About() {
      return <div>About</div>
    }
    
    export default About

     

    데이터를 사용한 정적 생성 

    1. 페이지 컨텐츠는 외부 데이터에 따라 다를 때, getStaticProps를 사용할 것.
    2. getStaticProps 함수는 빌드 시 호출되며 가져온 props데이터를 사전 렌더링 시 페이지에 전달할 수 있다.
    // 페이지가 사전 렌더링 전에 posts라는 props를 받는다.
    function Blog({ posts }) {
      return (
        <ul>
          {posts.map((post) => (
            <li>{post.title}</li>
          ))}
        </ul>
      )
    }
    
    // 빌드 시 호출되는 함수
    export async function getStaticProps() {
      // 외부 API를 호출
      const res = await fetch('https://.../posts')
      const posts = await res.json()
    
      // 빌드 시 블로그 컴포넌트에 props를 posts로 전달된다.
      return {
        props: {
          posts,
        },
      }
    }
    
    export default Blog

     

    1. 페이지 경로는 외부 데이터에 따라 다를 때, getStaticPaths를 사용할 것. (getStaticProps도 자주 함께 씀)
    2. 동적 경로로 이동하는 페이지를 만들 때 사전 렌더링하려는 항목은 외부 데이터에 따라 달라진다. getStaticPaths를 호출되며 사전 렌더링할 경로를 지정할 수 있다.
    function Post({ post }) {
      // 포스트 렌더링
    }
    
    // 빌드 시 호출. 동적 경로 라우팅에서도 정적 생성을 하고 싶을 때
    export async function getStaticPaths() {
      // 외부 API 호출
      const res = await fetch('https://.../posts')
      const posts = await res.json()
    
      // posts에 사전 렌더링 하고 싶은 경로를 지정
      const paths = posts.map((post) => ({
        params: { id: post.id },
      }))
    
      // { fallback: false }는 지정되지 않은 다른 경로일 때 404로 보낸다.
      return { paths, fallback: false }
    }
    
    // 빌드 시 호출
    export async function getStaticProps({ params }) {
      // params은 post `id` 값을 포함
      // params.id가 1이면, 라우트는 /posts/1
      const res = await fetch(`https://.../posts/${params.id}`)
      const post = await res.json()
    
      // props를 post에 담아 전달한다.
      return { props: { post } }
    }
    
    export default Post

     

    SSR 적용하기 

    • getServerSideProps는 모든 요청에 ​​대해 서버에서 호출된다.
    function Page({ data }) {
      // 데이터 렌더링
    }
    
    // 요청 시마다 호출됨
    export async function getServerSideProps() {
      // 외부 API에서 fetch
      const res = await fetch(`https://.../data`)
      const data = await res.json()
    
      // props를 data에 담아 전달
      return { props: { data } }
    }
    
    export default Page

     

    정리

    nomadcoder에서 next.js 기초를 배우고 항상 머릿속에만 담아두다가 이번엔 꼭 글로 남겨서 애매한 개념들을 정리해보고 싶었다. 

    공식 문서도 살펴보고 여러 블로그의 도움을 받으며 next.js의 아주 기본적이고 핵심적인 개념만 정리해보았다. 

    실제로 프로젝트에서 쓰다보면 생각지 못한 문제가 발생할 수 있겠지만 하루종일에 걸쳐 정리한 개념들이 있어 든든하다😌

     

    참고문서

    https://nextjs.org/

    https://velog.io/@longroadhome/FE-SSRServer-Side-Rendering-%EA%B7%B8%EB%A6%AC%EA%B3%A0-SSGStatic-Site-Generation-feat.-NEXT%EB%A5%BC-%EC%A4%91%EC%8B%AC%EC%9C%BC%EB%A1%9C

    https://nomadcoders.co/nextjs-fundamentals/lobby

    반응형

    댓글

Designed by Tistory.