본문 바로가기

next.js

[next.js] getStaticPaths

지금까지 상황)

지도 api를 가지고와서 매장의 위치가 핀에 꽂혀있을 수 있도록 만들고 해당 핀을 누르면 그 매장의 상세정보를 보려고 한다.

그럼 그 핀에 알맞는 상세page가 필요하게 되었다.

 

과정)

[name].tsx 파일을 pages 하위 파일로 만들어 준다. 여기서 []안에 들어가는 params를 지정해주면 페이지가 생성된다.

유동적으로 페이지를 만들 수 있다는 것.

 

예시 코드)

//[name].tsx

const StoreDetail : NextPage<Props> = ({store:Store})=>{
  return <div>detail<div>;
}

export default StoreDetail
export const getStaticPaths: GetStaticPaths = async()=>{
  const paths = [{params : {name: 'test'} }];
  return {paths,fallback:false}  //paths를 반환
}

//위와 같은 코드로 작성시 [name].tsx라고 지정해준게 test.tsx라고 하나의 페이지가 만들어진다.

그럼 이 함수는 어디다가 쓰면 될까?

많은 페이지가 필요할때 그때 마다 하나씩 만들지 않고 값만 넘겨주면 알아서 생성되도록 해주면 효율성이 좋겠다.

 

또, getStaticPaths는 getStaticProps 같이 쓰여야한다.

 

export const getStaticProps: GetStaticProps = async({params})=>{
  return {props:{}}
}

 

여기까지 만들고나서 실행 해보면 /test라는 경로에 detail이라는 글자를 확인할 수 있다.✅

그러나, /test2와 같이 경로를 입력하면 페이지가 뜨지 않는다. 즉, paths 변수에 지정해놓은 페이지들만 생성되다는것을 확인


그럼 저 paths에 매장들의 이름을 넣어주면 되겠다.

export const getStaticPaths: GetStaticPaths = async()=>{
  const stores = (await import('../public/stores.json')).default
  const paths = stores.map(store=>({params : {name: store.name} }));//모든 스토어의 경로를 만들어줌
  
  return {paths,fallback:false}
}

//여기있는 Params에 값이 들어가서 return이 가능하다.
export const getStaticProps: GetStaticProps = async({params})=>{
   const stores = (await import('../public/stores.json')).default
   const paths = stores.map(store=>store.name ===params.name)
  return {props:{store}}
}

paths는 가지고 있는 매장들(stores)을 map돌려 params를 매장들의 이름으로 넘긴다. 

그럼 아마도 /빽다방 <= 이런 경로가 되겠지ㅎ

 

그리고 아까 말한 getStaticProps를 사용해서 해당 페이지의 props로 넘겨준다.

{params}에 위의 코드에서 가져온 store.name들이 들어간다음에 가지고 있는 데이터와 일치한 매장들의 이름을 props로 넘겨준다.

잘 넘어왔는지 확인해보자면 요롷게 확인할 수 있지않을까?

const StoreDetail : NextPage<Props> = ({store:Store})=>{
  return <div>name:{store.name}<div>;  //빽다방
}

좀 더 추가적인 정보라면,

getStaticPaths는 페이지의 경로를 정적으로 생성한다. 즉, build타임에 stores~이 구문을 실행하여 API 또는 JSON 으로 저장된 데이터를 확인한 뒤, 미리 페이지를 프리렌더링 해놓는다👍

위의 코드를 보면 fallback이라는 속성을 볼 수 있다. 공식문서를 참고하면 가장 잘 나와있다. true/false/blocking으로 값을 줄 수 있다.

false : 빌드타임에 미리 경로를 다 생성해둔다, 만약 찾을 수 없는 경로를 입력한다면 바로 404페이지를 띄운다.

true :  똑같이 빌드타임에 경로를 생성해두지만, 존재하지 않더라도 약간의 로딩 후 404페이지를 띄우거나 안보이게 할 수 있다.

//true code

export const getStaticProps: GetStaticProps = async({params})=>{
   const stores = (await import('../public/stores.json')).default
   const paths = stores.map(store=>store.name ===params.name) //해당하는 매장을 못찾겟지?
   
   if(!store){
     return {
       notFound : true, //404페이지로 보낸다.
     };
   }
   
  return {props:{store}}
}

위 처럼 만약 store이 없다면? notFound를 줘서 404페이지로 보낸다.

그리고 이 404페이지를 띄우기 까지의 과정 또한

const StoreDetail : NextPage<Props> = ({store:Store})=>{
  const router = useRouter();
  if(router.isFallback){
    
  return <div>Loading...<div>
  };
}

위와 같이 isFallBack을 사용해서 사용자에게 페이지를 찾는 중이다~ 하고 Loading을 띄워줄 수 있다.

이렇게 아주 잠깐이지만 Loading이라는 글자를 확인 할 수 있고 404를 띄운다.

다시 과정을 정리하자면, store가 없어도 getStaticProps까지 함수가 실행될것이고 거기서 store을 못 찾으면 return 으로 404가 뜬다.

이 과정중에 설정해놓은 isFallBack속성으로 Loading이라는 구문을 추가할 수 있다.(store가 있다면 당연히 원래대로 진행되듯이 name이 뜰것이다.)

 

❓그럼 언제 true설정은 언제 하는게 좋을까?

수만개의 매장들이 있다면 build타임에 모든 경로를 만들어내기가 비효율적일것이다. 그러니 미리 최소한의 경로만 가지고 있고 유저가 때에 따라서 요청할때 그제서야 경로를 만드는 것이 좀 더 효율적일 수 도 있다.

 

❓DB에 새로 추가되는 게시물이나 매장이 있을 경우에 사용할 수 있다.

빌드타임에 미리 새로 추가가 될 것을 모르니 프리렌더링을 할 수 없기 때문이다.

 

❗️누군가가 최초로 호출을 하면 새롭게 만들어진 HTML파일을 정적페이지로 만들어서 가지고 있어 다음 사람이 호출하면 getStaticProps로 안가고 pre-rending된 페이지를 볼 수 있다.(매번 getStaticProps가 실행되는 것이 아니라는 점)


Blocking

true와 비슷하지만 약간의 시간을 가지고 404페이지를 던진다. 등록되지 않은 페이지에 접근을 하면 fallback이란느 Loading문구는 뜨지 않는다.

 

과정) getStaticPath > getStaticProps > 없넴 그럼 404(아까 위의 조건식으로 if(!store) 구문이 실행된다. 대신, isFallback은 안된다.

최초 HTML 생성과정 후 정적페이지로 되는 과정은 true와 동일하다.

 


404페이지 만들기

pages폴더 하위에 404.tsx 만들어서 꾸며주면된다. 간단 😎

'next.js' 카테고리의 다른 글

서버로 데이터 전송  (0) 2023.05.04
next.js server  (0) 2023.05.01
[next.js] Image  (0) 2023.04.05
[Next.js] link  (0) 2023.04.04
Next.js <getStaticProps>  (0) 2023.04.04