Skip to content

Next.js 알고 사용합시다

Seogeurim edited this page Nov 29, 2021 · 3 revisions
  • 작성자: @jiyong1
  • 작성일: 2021.11.29
  • Description: 공식문서 정리
    • ???: 엇 저희 nextjs 안쓰지 않나요?
    • 앗 쓰는줄..

Navigate Between Pages

Next.js에서 페이지 컴포넌트는 pages 디렉토리 내에 저장한다.

route는 파일 이름과 관련되어진다.

  • pages/index.js : '/'
  • pages/posts/first-post.js : '/posts/first-post'

Link

페이지간의 link를 걸기 위해 Link 컴포넌트를 사용한다.

import Link from 'next/link'

Link 컴포넌트는 같은 app의 서로 다른 두페이지간의 client-side navigation을 가능하게 하도록 한다.

만약 a 태그를 사용할 경우 client-side navigation이 이루어지지 않는다.

  • 같은 앱의 다른 페이지로 이동하고자 한다면 Link 컴포넌트 사용
  • 외부의 다른 페이지로 이동하고자 한다면 a 태그 사용

Code splitting and prefetching

Next.js는 자동적으로 코드를 분할한다. 따라서 라우팅된 페이지에서 필요한 것들만 로드하게 된다.

이는 페이지 로딩의 속도를 향상할 수 있다.

각 페이지는 격리되어져 있기 때문에 다른 페이지에서 오류가 발생하더라도 다른 것들은 정상적으로 작동하게 될 것이다.


production build를 하게 되면 Link 컴포넌트가 브라우저의 viewport에 들어났을 때 자동적으로 코드를 prefetch한다.

따라서 link를 클릭하더라도 이미 목적 페이지의 코드를 로드해왔기 때문에 즉시 응답할 수 있다.




Assets, Metadata

정적 파일 제공


Image Component

Next.js 에서 제공하는 Image 컴포넌트를 사용하면 이미지를 최적화하는 핸들링을 직접적으로 할 필요 없이 쉽게 사용할 수 있다.

  • 필수 속성

    • src

    • width : 픽셀 (layout="fill" 속성을 사용한다면 필요없는듯..?)

    • height : 픽셀 (layout="fill" 속성을 사용한다면 필요없는듯..?)

  • optional 속성

    • layout : 고정적인 픽셀? 혹은 부모 컨테이너에 맞게 responsive한 이미지
    • quality : 1~100
    • priority : true로 설정하면 lazy loading 적용 x
    • placeholder : 로딩중에 보여줄 상태

Metadata

head 대신 Head 컴포넌트를 사용한다.

import Head from 'next/head'
import Link from 'next/link'

export default function FirstPost() {
  return (
    <>
      <Head>
        <title>First Post</title>
      </Head>
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </>
  )
}

만약 lang 과 같은 html 속성을 바꾸고자 한다면 pages/_document.js 파일을 생성하면 된다.


Layout

공통적인 layout을 정의하고 이를 import 하여 page를 작성할 수 있다.

function BaseLayout({children}) {
  return <div className="container">{children}</div>
}

styled-componentsemotion을 사용하지 않더라고 built-in CSS Modules를 사용하여 개발할 수 있다.

css file은 무조건 .module.css 로 끝나야 한다.

// layout.module.css
.container {
  max-width: 3rem;
  padding: 0 1rem;
}
import styles from './layout.module.css'

function BaseLayout({children}) {
  return <div className={styles.container}>{children}</div>
}

자동적으로 클래스 이름을 충돌되지 않게 선정해준다.

cross browsing issue를 해결해주는 것은 아닌 것 같습니다... 그러니 생략..




Pre-rendering and Data Fetching

기본적으로, Next.js는 모든 페이지를 미리 렌더합니다.

client-side 에서 javascript로 모든 일을 하는 것이 아니라 Next.js가 각 페이지를 미리 생성합니다. 따라서 SEO(검색 엔진 최적화)에 유리합니다.

따라서 Javascript가 실행되지 않는 환경에서도 각 컴포넌트들은 렌더링이 이루어지게 됩니다. 하지만 Link 와 같은 컴포넌트들이 작동하지는 않습니다. (clinet-side navigate)

prerender-nextjs


Two Forms of Pre-rendering

Next.js의 pre-rendering 방식은 두가지가 존재한다.

  • Static Generation : build time에서 생성, 각 request에 대해 재 사용된다.
  • Server-side Rendering : 각 request에서 생성한다.

개발 환경으로 빌드할 시 Static Generation 환경에서도 각 request에 대해 생성하여 응답해준다.


각 페이지에 대해 어떤 방식을 채택하여 응답할 것인지 선택할 수 있다.

왠만하면 Static Generation을 채택하는 것을 추천한다.

Server-side Rendering을 채택한다면 느릴 수 있지만 항상 최신 상태를 반영할 수 있다.


Static Generation with Data

데이터가 필요한 Static Generation page의 경우 getStaticProps 라는 async function을 export 하여 사용할 수 있다.

export default function Home (props) {...}

export async function getStaticProps() {
  // 외부 데이터 가져오기
  const data = ...
  
  // props 가 Home Component에 전달될 것이다.
  return {
    props: ...
  }
}

static-generation


Fetching Data at Request Time (SSR)

getServerSideProps 를 사용하면 된다.

export default function Home (props) {...}

export async function getServerSideProps(context) {
  // 외부 데이터 가져오기
  const data = ...
  
  // props 가 Home Component에 전달될 것이다.
  return {
    props: ...
  }
}

getServerSideProps 는 요청에 따라 실행되기 때문에 context 파라미터를 받는다. 결과가 캐시되지 않는다. (모든 요청에 대해 계산한다.)

server-side-rendering


굳이 pre-render 데이터가 필요하지 않다면 Client-side Rendering을 사용해도 된다.

  • private한 경우 (user page)
  • SEO와 관련이 없는 경우



Dynamic Routes

각 페이지가 외부 데이터에 의존되는 경우 사용된다. (/user/<userName>)

pages/user/[userName].js 형식으로 파일을 작성한다.

getStaticPaths async function을 export 한다. 이 함수에서는 가능한 userName list를 return 해야 한다.

이 후 getStaticProps를 사용하여 data를 fetching하여 페이지 컴포넌트에 전달한다. 해당 함수로 params가 매개변수로 전달되므로 params.userName 형태로 접근하면 된다.

import Layout from '../../components/layout'

export default function User() {
  return <Layout>...</Layout>
}

export async function getStaticPaths() {
  // 가능한 userName들을 return
}

export async function getStaticProps({ params }) {
  // params.userName을 통해 data fetching
}



Deploy

다음과 같은 script가 존재한다고 가정한다.

{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

build를 하게 되면 필드된 production app이 .next 폴더에 존재하게 된다.

build를 완료한 후 start를 하게 되면 Node.js Server가 페이지를 제공하게 된다. 포트변경을 원한다면 next start -p $Port 를 사용하자.




Typescript 사용하기

  • typescript 와 관련 패키지 설치
$ npm install -D typescript @types/react @types/node
  • tsconfing.json customize
  • next-env.d.ts 파일 생성, 해당 파일을 손대지 않는다.

Static Generation and Server-side Rendering type

import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'

export const getStaticProps: GetStaticProps = async context => {
  // ...
}

export const getStaticPaths: GetStaticPaths = async () => {
  // ...
}

export const getServerSideProps: GetServerSideProps = async context => {
  // ...
}

이외에 다른 타입 정의에 대한 내용은 혹은 다른 사항들은 공식문서 참고..



위의 정보들 이외에도 꽤나 많은 내용이 있는 것 같은데 필요에 따라 참고해서 사용하면 될 것 같습니다..

예를 들어 SEO 최적화, Performance, 환경 변수 파일 (.env) 와 같은 내용들도 있습니다.

Clone this wiki locally