[Next.js] Pages

장유진·2022년 9월 27일
1

Next.js

목록 보기
2/6

원본: https://nextjs.org/docs/basic-features/pages


Next.js에서 page란 .js, .jsx, .ts, .tsx 파일에서 export 된 리액트 컴포넌트이다. 각 페이지는 파일 이름으로 라우팅된다.

  • 예) pages/about.js라는 파일이 있으면 이 파일은 /about이라는 주소로 접근 가능하다.

동적 라우팅 (dynamic routes)

Next.js는 동적 라우팅을 제공한다.

  • 예1) pages/posts/[id].js라는 파일이 있다면 이 파일은 posts/1, posts/2 등으로 매칭된다.
  • 예2) pages/posts/[pid].jsposts/1, posts/abc, 기타 등등으로 매칭된다.

Pre-rendering

기본적으로 Next.js는 모든 페이지를 pre-rendering한다. pre-rendering은 즉 클라이언트에서 javascript로 HTML을 생성하는 것이 아니라 Next.js가 HTML을 미리 생성해두는 방식을 의미한다. 이 방식을 사용하면 더 좋은 성능을 낼 수 있고 SEO에도 적합하다.

각각 생성된 HTML은 페이지에 필요한 최소한의 javascript 코드와 연결되어있다. 페이지가 브라우저에서 로드되면 HTML이 먼저 로드된 후, 이 javascript 코드가 실행되면서 동작 가능한 페이지로 완성된다. 이 과정을 hydration이라고 한다.

Pre-rendering의 2가지 방식

pre-rendering에는 Static GenerationServer-side Rendering이라는 두 가지 방식이 있다. 이 둘의 차이점은 언제 HTML을 생성하느냐이다.

  • Static Generation(권장됨): HTML이 빌드 시 생성되고 각 요청때마다 재사용된다.
  • Server-side Rendering: HTML이 매 요청마다 새로 생성된다.

Next.js에서는 이 두 가지 방식을 페이지별로 선택해서 사용할 수 있다.

Static Generation이 권장되는 이유는 정적으로 생성된 페이지가 CDN에 캐시되는 것이 가능해서 성능을 향상시킬 수 있기 때문이다. 하지만 일부 경우에는 Server-side Rendering이 더 좋은 선택지일 수도 있다.

Static Generation

Static generation을 사용하면 페이지의 HTML이 빌드 타임에 생성된다. 즉 next build를 실행했을 때 생성된다. 이 HTML은 매 요청마다 재사용될 것이며 CDN에 캐시 가능하다.
또한 페이지를 생성할 때 데이터를 포함할 수도 있고 그렇지 않을 수도 있다.

데이터 없는 Static Generation

기본적으로 Next.js에서는 data fetching(데이터 가져오기) 없이 pre-rendering이 진행된다.

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

export default About

데이터 있는 Static Generation

어떤 페이지들은 외부 데이터 로드를 필요로 한다. 이때 두 가지 경우가 있는데, 하나 또는 두 가지 전부 적용될 수 있다. 각각의 경우에 따라 Next.js에서 제공하는 getStaticPropsgetStaticPaths 함수를 사용하면 된다.

  • 페이지의 content가 외부 데이터에 따라 결정될 경우 -> getStaticProps
  • 페이지의 path가 외부 데이터에 따라 결정될 경우 -> getStaticPaths

getStaticProps(content)

// TODO: Need to fetch `posts` (by calling some API endpoint)
//       before this page can be pre-rendered.
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

export default Blog

위 코드에서는 posts라는 데이터를 가져와야 한다. 그러기 위해서는 같은 파일 내부에서 export async 키워드를 붙인 getStaticProps 함수를 작성하면 된다. 이 함수는 빌드 타임에 실행되며 pre-render 시 fetch된 데이터를 페이지의 props로 넘겨준다.

function Blog({ posts }) {
  // Render posts...
}

// This function gets called at build time
export async function getStaticProps() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

export default Blog

getStaticPaths(path)

동적 라우팅을 사용하면 pages/posts/[id].js라는 파일을 생성했을 때 id: 1을 가진 페이지를 posts/1에서 접속할 수 있다. 하지만 이 id는 외부 데이터에 따라 결정될 수 있다.
그러기 위해서는 같은 파일 내부에서 export async 키워드를 붙인 getStaticPaths 함수를 작성하면 된다. 이 함수는 빌드 타임에 실행되며 pre-rendering을 진행할 경로를 지정할 수 있다.

function Post({ post }) {
  // Render post...
}

export async function getStaticPaths() {
  // ...
}

// This also gets called at build time
export async function getStaticProps({ params }) {
  // params contains the post `id`.
  // If the route is like /posts/1, then params.id is 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

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

export default Post

언제 Static Generation을 사용해야 하는가?

user request 전에 pre-rendering을 진행할 수 있다면 Static generation을 사용하면 된다.
그렇지 않을 경우 Client-side rendering과 Static generation을 함께 사용하거나 Server-side rendering을 사용하면 된다.

Server-side Rendering(SSR)

Server-side rendering을 사용하면 각 페이지의 HTML은 매 요청 때마다 생성된다.
SSR을 사용하기 위해서는 같은 파일 내부에서 export async 키워드를 붙인 getServerSideProps 함수를 작성하면 된다. 이 함수는 모든 요청 때마다 서버에서 실행된다.

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

보다시피 getServerSidePropsgetStaticProps와 비슷하지만 빌드 타임에 실행되는 대신 매 요청 때마다 실행된다는 점만 다르다.

profile
프론트엔드 개발자

0개의 댓글