: nextJS에서 핵심이 되는 개념들이다.
nextjs를 활용하면 페이지별로 pre-rendering 방식을 선택할 수 있다.
중요한건 페이지 별로 프리 렌더 혹은 렌더 방식을 정할 수 있다는 것
: 정적인 페이지
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)
이렇게 나온다.
: 일단 여기서 새롭게 써볼건 getStaticPaths 이다. SSG 를 씀과 동시에 dynamic path 를 쓰려면 사전에 빌드를 할 때 어떤 path로 만들어줄지 등을 정해놔야하는데 이걸 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 옵션이 있다.
: 빌드시에 생성되지 않은 페이지에 대한 처리를 하는 옵션
- 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')
하는 방법도 있다.