[NextJS] NextJS로 blog 만들어보기 - (2)

yongkini ·2023년 6월 23일
0

NextJS

목록 보기
2/4

nextjs에서 스타일링하기

  • 기본 적으로 styled-jsx 를 쓸 수 있는듯 하다(global로도 할 수 있고)
  • tailwindcss 도 프로젝트 만들 때 물어보는 것보면 당연히 지원하는 것 같다.
  • css-module도 지원하는데, 이걸 써보고자 한다.
  • 물론 PostCSS 등등 다른 것도 쓸 수 있다.

Pre-rendering / Data Fetching

: nextJS에서 핵심이 되는 개념들이다.

nextjs를 활용하면 페이지별로 pre-rendering 방식을 선택할 수 있다.

  • getStaticProps를 사용하면 SSG
  • getServerSideProps를 사용하면 SSR
  • 당연히 CSR도 가능
  • ISR 도 가능

중요한건 페이지 별로 프리 렌더 혹은 렌더 방식을 정할 수 있다는 것

SSG

SSG를 사용하면 좋은 페이지

: 정적인 페이지

  • Marketing pages
  • Blog Posts
  • E-commerce product listings
  • Help and Documentation

SSG 적용 여부의 기준점

  • 사용자가 페이지를 요청하기 전에(build 시기에) pre-render 할 수 있는가? 즉, 유저 인터랙션에 따라 결정되는게 아닌 static한 페이지인가?
    • yes 이면 SSG
    • No 이면 SSR or ISR 혹은 CSR

SSG의 2가지 케이스

  • 외부 데이터 없이 pre-rendering(정말 순수하게 정적인 페이지)
  • 외부 데이터를 가져와서 pre-rendering
    • 다른 파일
    • API
    • DB 등등..
export async function getStaticProps() {
  // getStaticProps 내에서 url은 상대경로로 줄 수 없다!
  const response = await fetch('http://localhost:3000/api/posts')
  const json = await response.json()

  return {
    props: {
      allPostsData: json.allPostsData,
    },
  }
}

data를 fetching 하는데 static 한 페이지라는게 이해가 좀 안됐는데, build 과정에서 호출해서 가져오는걸 말하는 것 같다. 실제로 빌드할 때

(SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

이렇게 나온다.

SSG로 Dynamic Routes 만들기

: 일단 여기서 새롭게 써볼건 getStaticPaths 이다. SSG 를 씀과 동시에 dynamic path 를 쓰려면 사전에 빌드를 할 때 어떤 path로 만들어줄지 등을 정해놔야하는데 이걸 getStaticPaths에서 해준다.

getStaticPaths

: SSG는 build 할 때 페이지를 그려놓고 준비해놓는거라고 했었다. 이 때, 다이나믹 라우팅을 구현하려면? 즉, 어떤 url endpoint가 올지 모르는 상황에 해당 페이지를 그려놔야 한다고 하면, 이에 대해 build 할 때 next에게 알려주는 절차가 필요할 것이다. 예를 들어, domain/first/a 라는 url에서 a가 들어왔을 때는 어떤 페이지, b가 들어왔을 때는 어떤 페이지 이렇게 알려줘야 그에 대한 대비를 한다(페이지를 그려놓는다). 이 때, 어떤 페이지가 들어올지를 정해놓는 곳이 getStaticPaths 이다. 여기서

export async function getStaticPaths() {
  return {
    paths: getAllPostIds(),
    fallback: 'blocking',
  }
}

이런식으로 설정을 해놓으면 되는데 paths에는 이러한 형태의 배열이 들어간다.

   [
     {
       params: {
         fileName: 'ssg-ssr'
       }
     },
     {
       params: {
         fileName: 'pre-rendering'
       }
     }
   ]

fileName은 내가 다이나믹 라우팅을 위해 파일명에 [fileName].js 로 세팅해놨고, 거기에 어떤 값이 들어갈지를 저렇게 키와 값으로 세팅해놓은 것이다. 이제

export async function getStaticProps({ params }) {
  // 이렇게 여기서 params를 받을 수 있다.
  const postData = await getPostData(params.fileName)
  return {
    props: {
      postData,
    },
  }
}

getStaticProps의 props의 params로 해당 fileName을 받아서 어떤 처리를 할 수 있고 그에 따라 각각의 페이지를 그려놓을 수 있게 된다. 내가 만든 케이스의 경우 a라는 파일명이 들어오면 그에 따른 파일을 열어서 파싱한 데이터를 보여주고, b도 마찬가지로 처리한다. 이 때, a도 b도 아닌 값이 들어오면 어떻게할까? 그러한 상황을 대비해 fallback 옵션이 있다.

fallback

: 빌드시에 생성되지 않은 페이지에 대한 처리를 하는 옵션
- false : 처리하지 않는다. 404 에러
- true : callback 동작으로 loader를 보여줬다가 데이터가 있다면 그 때 그리겠다.
- blocking을 하면 loader도 없이 안그리다가 제너레이션 되는 순간 그리겠다

true, blocking을 해놓으면, 예를 들어, 기정의해놓지 않은 c라는 값으로 접근하면 true로 해놨을 때는 loader를(로딩 스피너 같은 것) 보여주면서, 그 때는 데이터가 있다면 그 때 그리는걸로 한다. 이것도 서버에서 처리를 하겠지만, SSG는 build 때 그리는 것이라는 점에서는 좀 다르다. 그 당시에 유동적으로 생성하는 거니까. blocking은 loader를 안그리다가 그릴 수 있게 되면 그리는 형태이다. 예를 들어, 갑자기 c라는 데이터가 생겼을 경우가 이러한 경우에 해당될 것 같다. 실제로 blog 플젝을 하면서 CRUD의 Create 기능을 만들었는데, 이렇게 없던 데이터가 생겼을 때 blocking or true option을 fallback에 주니까 일정 시간 동안 해당 페이지를 그리고 그 페이지로 이동시키는 것을 볼 수 있었다(false로 하면 실제 데이터는 추가됐는데, 404 에러를 리턴함)

추가로 알고 갈것

: fetch() promise는 HTTP Error 에 의해 reject 되지 않는다. 즉, fetch.then 등을 쓸 때 끝에 catch를 써도 http 요청에 대한 응답에서 error가 났을 때 이를 catch에서 잡을 수 없다. 그래서 특정 상황에 예를 들어, response.ok === false 이런 상황일 때
throw new Error('Fetch Error') 를 써서 에러를 일으켜야 then.catch에서 캐치할 수 있다. or http request 문을 try에 넣어놓고 catch문에 throw new Error('Fetch Error') 하는 방법도 있다.

profile
완벽함 보다는 최선의 결과를 위해 끊임없이 노력하는 개발자

0개의 댓글