본문 바로가기
nextjs

nextjs 기본 및 페이지 개념

by spare8433 2023. 2. 2.

12 버전 기준으로 정리한 내용이므로 주의 13 버전은 일부 바뀐 내용이 있습니다. 개념만 참고 추천

Next.js 는 무엇인가

Next.js is a flexible React framework that gives you building blocks to create fast web applications - 공식문서 소개 부분


Next.js는 서버 사이트 렌더링, 정적 웹 페이지 생성 등 리액트 기반 웹 애플리케이션 기능들을 가능케 하는 Node.js 위에서 빌드된 오픈 소스 웹 개발 프레임워크이다. - [출처] 위키 백과 (https://ko.wikipedia.org/wiki/Next.js )


정리: React 를 효율적인 사용하기 위한 프레임워크 이며 SSR 을 구현하는데 많이 사용함

 

설치

npx create-next-app@latest    # automatic
npx create-next-app@latest --typescript # add typescript
npm install next react react-dom     # Manual Setup

 

실행 부분

package.json and add the following scripts:

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

 

기본 폴더

public : 이미지, 폰트 등 프로젝트 필요한 자원 저장하는 곳 / 로 접근 가능
pages : 이 곳에 저장되는 파일의 이름이 라우터의 기본이 된다 ex) pages/profile/index.js => /profile
.js, .jsx, .ts, or .tsx 파일을 지원

 

NextJs 에서의 페이지 이해

By default, Next.js pre-renders every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript. Pre-rendering can result in better performance and SEO.

Each generated HTML is associated with minimal JavaScript code necessary for that page. When a page is loaded by the browser, its JavaScript code runs and makes the page fully interactive. (This process is called hydration.)

정리 :
NextJs 의 모든 페이지는 pre-render 를 활용하며 이건 SEO 에 유리하다

브라우저가 페이지를 로드될 js 가 페이지를 완벽히 상호작용 할 수 있게 내용을 채워준다 그리고 이런 과정을 hydration 라고 부른다

pre-render : 검색엔진을 인식하며 사전에 HTML파일들을 만듬
*SEO 통칭(검색 엔진 최적화) * : 검색엔진으로 부터 웹사이트가 검색 결과에 더 잘 보이도록 최적화하는 과정을 말한다.

Dynamic Routes

pages/posts/[id].js 이런 식으로 파일을 지정해두면 웹에서 posts/1 이런식으로 접근 가능

 

Two forms of Pre-rendering

 

-본문 내용중-

대부분의 페이지에는 정적 생성을 사용하고 다른 페이지에는 서버 측 렌더링을 사용하여 "하이브리드" Next.js 앱을 만들 수 있다.

당연한 내용이지만 Static Generation 이 성능상으로도 유리하고 추천하지만 Server-side Rendering 이 꼭 필요 할때가 있을 것이다.

또한 Client-side data fetching 도 함께 사용 가능하다 (아래에 설명)

 

Static Generation

위에도 설명한 것처럼 페이지 HTML은 빌드 시 생성되는 방식

 

Static Generation without data

데이터 없이 정적 페이지 생성 하는 방식

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

export default About

 

Static Generation with data

페이지 생성에 사전 데이터가 필요한 경우 정적 페이지 생성 하는 방식

  1. 외부 content 에 의존하는 경우 : getStaticProps.
    ex) api 를 통한 데이터 받아오기
  2. 외부 path 에 의존하는 경우 : Use getStaticPaths (대게 같이 씀 getStaticProps).
    ex) posts/[id] (dynamic routes) 처럼 path 의 데이터를 받는경우

getStaticProps :

  • 빌드 할때 함수가 호출되며 pre-renderprops 로 데이터를 던져줌
    getStaticPaths :
  • 빌드 할때 함수가 호출되며 pre-renderpath 에 적용 해줌
  • 위에 설명한 Dynamic Routes 주소에 값을 집어넣어 접근 할 때 활용함
  • 당연하게도 getStaticPaths 를 쓸때 따로 데이터가 필요하다면 getStaticProps 도 같이 사용하기도 함

eStatic Generation 은 잘 안 변하는 페이지를 쓸 때 좋다

 

Incremental Static Regeneration (ISR)

빌드 후에도 static 페이지를 생성하고 업데이트 할 수 있다

getStaticPropsrevalidate 추가

function Blog({ posts }) {
  return (
    <>{...}</>
  )
}

export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // 요청이 들어올때 10초마다 페이지를 다시 구성함
    revalidate: 10, // In seconds
  }
}
export async function getStaticPaths() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // 빌드 시 이러한 경로만 사전 렌더링합니다
  // { fallback: blocking }를 사용하면 경로가 존재하지 않는 경우 요청 시 페이지를 서버에서 검색합니다.
  return { paths, fallback: 'blocking' }
}

v12.2.0 부터는 ## On-demand Revalidation 를 지원해서 수동으로 캐시를 제거함

이제 getStaticProps 안에서 revalidate 를 쓸필요가 없다 기본적으로 revalidate가 없으면 false 로 설정되있고 오직 revalidate() 를 쓸때만 다시 구성된다.
Inside, you do not need to specify

    //api 상에서 사용 예
    await res.revalidate('/path-to-revalidate')
    return res.json({ revalidated: true })

 

Client-side data fetching

SEO 가 필요치 않을 때 수시로 데이터가 업데이트 될 때 사용

간단하게하면 useEffect 사용 하면 됨 swr 을 활용한 방식이 있ㄷ음

useEffect

import { useState, useEffect } from 'react'

function Profile() {
  const [data, setData] = useState(null)
  const [isLoading, setLoading] = useState(false)

  useEffect(() => {
    setLoading(true)
    fetch('/api/profile-data')
      .then((res) => res.json())
      .then((data) => {
        setData(data)
        setLoading(false)
      })
  }, [])

  if (isLoading) return <p>Loading...</p>
  if (!data) return <p>No profile data</p>

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.bio}</p>
    </div>
  )
}

swr

const { data, error } = useSWR('/api/profile-data', fetcher)