Next.js - Page에 대해 알아보자

2022. 4. 14. 21:23프론트엔드/React.js

728x90
 

Basic Features: Pages | Next.js

Next.js pages are React Components exported in a file in the pages directory. Learn how they work here.

nextjs.org


Next.js에서의 페이지

Next.js에서는 pages 폴더 안에 있는 컴포넌트들은
각 URL로 접속가능하게 된다.

즉 자동으로 라우팅을 해주는 것인데,
pages/abc.js가 있다면 /주소/abc로 접속하면 해당 컴포넌트가 출력이 된다.

만약 변할 수 있는 param을 처리하고 싶다면
[param_name].tsx으로 생성하면 된다.

예를 들어 param 이름을 id로 받는다면,

위와 같이 [id].tsx로 생성하면 /user/1과 같은 URL을 처리할 수 있다.

그리고 /user의 경우에는

index.tsx가 폴더 내에 있으면 해당 URL을 처리해준다.
자세한 라우팅은 나중에 정리해보도록 하자.


Next.js의 핵심: Pre-rendering

Next.js의 중요한 역할은 사전 렌더링을 하는 것이다.
즉 각 페이지에 대하여 HTML 파일을 미리 생성하여 출력 속도를 높여준다.
단, 클라이언트에서 처리할 Javascirpt는 처리하지 못한다.

Next.js에서는 이 사전 렌더링을 두가지 방법으로 처리하는데,
SSG(Static Site Generation)SSR(Server-side Rendering)이다.

원한다면 각각의 페이지에 따라 다른 방법으로 처리할수 있다.
예를 들어 A페이지는 SSG로, B페이지는 SSR로 처리하는 것이 가능하다.
(또는 CSR - Client side rendering으로 하는 것도 가능하다)


SSG (Static Site Generation)

말 그대로 '정적 사이트 생성'이다.
빌드 단계에서 (next build 명령어 실행 시) HTML 파일이 생성된다.
이렇게 생성된 HTML 파일은 여러번의 호출에 재활용되면서 효율성을 높인다.

이 HTML파일은 CDN에 캐싱이 되기 때문에
클라이언트는 더 빠르게 HTML 파일을 받아서 처리할 수 있다.


데이터가 없는 페이지 처리

동적으로 처리할 데이터가 없다면,
일반 React 컴포넌트처럼 생성해주면 된다.

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

export default About

이렇게 평범하게 작성하면 자동으로 SSG가 처리된다.


동적인 컨텐츠를 사용하는 경우: getStaticProps

예를들어 서버에서 블로그 게시글 목록을 가져와서 출력한다고 생각해보자.
그럼 다음과 같이 작성하면 된다.

// 4. 페이지 컴포넌트에서 posts를 전달받는다.
function Blog({ posts }) {
  // Render posts...
}

// 1. async function getStaticProps를 선언한다.
export async function getStaticProps() {
  // 2. API를 호출한다.
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // 3. 값을 반환한다.
  return {
    props: {
      posts,
    },
  }
}

export default Blog

순서대로 살펴보자.

1. async function getStaticProps를 export한다. 꼭 이름이 getStaticProps여야 한다.
2. API를 호출한다.
3. props에 담아 전달한다. (예제에서는 posts라는 이름의 변수를 전달)
4. 3번에서 전달한 post를 props로 받음

동적인 Path를 사용하는 경우: getStaticPaths

위에서 설명한대로 /user/1과 같은 경로를 처리하려면
pages/user/[id].tsx와 같은 파일을 만들어야 한다.

이런 경우에는 각각의 데이터에 대하여
사전 렌더링을 할 것이다.

만약 id가 1,2,3,4,5인 게시물들(총 5개)이 있다고 하면,
빌드 단계에서 실제로 API를 호출해본 다음에,
1,2,3,4,5에 대한 페이지를 사전에 생성한다.

사용 방법은 다음과 같다.

// 1. async function getStaticPaths를 export해준다.
export async function getStaticPaths() {
  // 2. API를 호출한다.
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // 3. paths 변수에 (이름이 paths여야 함) 각 페이지를 처리할 수 있도록 params를 추가함.
  const paths = posts.map((post) => ({
    // 만약 [pid].tsx라면, 아래의 변수는 id가 아니라 pid로 전달해야 한다.
    params: { id: post.id },
  }))

  4. paths를 전달한다.
     fallback: false는 실제 있는 페이지들 (1,2,3,4,5)가 아니면 404를 호출하는 것이다
  return { paths, fallback: false }
}

그리고 getStaticProps도 처리해준다.

전체 흐름대로 보면,

1. getStaticPaths: 실제로 존재하는 페이지들을 파악하고 params를 넘겨줌
2. getStaticProps: params를 받아서 id값을 처리함. 
3. 페이지 컴포넌트: 전달받은 동적인 데이터를 기반으로 페이지를 구성함

의 순서대로 데이터의 흐름이 구성된다.


SSG는 언제 사용할까?

스스로에게 이런 질문을 해보자.
100명이 요청하면 100명한테 똑같은 걸 보여주는 페이지인가?

맞다면 무조건 쓰는게 좋다.

다만, 한 페이지내에서 데이터가 자주 업데이트된다면, (주식 화면 같이)
그리고 페이지 내부 컨텐츠가 계속 변화한다면 사용하지 않는 것이 좋다.

그런 경우라면 Client-side Rendering(CSR)이나
Server-Side Rendering(SSR)을 하는 것이 좋다.


SSR (Server-Side Rendering, Dynamic Rendering)

SSR을 이용하면, 각 요청이 발생할 때마다 HTML이 생성된다.
엥? 그럼 CSR과 다를게 뭐죠?
나도 그걸 잘 모르겠어서 아래의 링크를 읽어봤다.

 

Data Fetching: getServerSideProps | Next.js

Fetch data on each request with `getServerSideProps`.

nextjs.org

- 브라우저가 아닌 서버에서 실행된다.
- 기존 CSR은 '요청 -> HTML -> 데이터 가져오기(클라이언트) -> 출력'이라면
         SSR은 '요청 -> 데이터 가져오기(서버) -> HTML 생성 -> 출력'이다.
- 매번 요청을 할때마다 데이터를 패치해서 가져온다. 예를 들어 서버가 어제 켜졌는데, 데이터가 오늘 바뀌었다고 치자. 그러면 SSG는 어제 데이터로 가져올 것이다. SSR은 매번 업데이트 해서 가져오기 때문에 오늘자 데이터로 가져온다.

사용방법은 getStaticProps와 비슷하다.

function Page({ data }) {
  // Render data...
}

// This gets called on every request
export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

export default Page

마무리

한번 SSG와 SSR에 대해 공부를 해봤는데,
생각보다 간단한 내용이라서 괜찮았다.

요새 새롭게 공부해야 할 내용이 많아서
불안감도 든다.

그래도 하나하나 차근차근 공부하다보면 어떻게든 되겠지?

'프론트엔드 > React.js' 카테고리의 다른 글

객체 지향 설계 - SOLID  (0) 2022.05.14
React Atomic Design  (0) 2022.04.22
Next.js 튜토리얼  (0) 2022.03.20
React CRA 없는 프로젝트 베이스  (0) 2022.03.15
Redux 실전기 1 - 깡프로젝트에 Redux 추가하기  (0) 2021.11.26