(Next.js) getStaticPaths

devAnderson·2022년 1월 22일
0

TIL

목록 보기
36/106

해당 메서드의 존재 이유

보통, react component에서 useRouter을 이용하여 path와 param 정보를 얻어냈을 것이다.
스크린샷 2022-01-22 오후 1 49 20

그리고나서 해당 데이터를 이용해서 useEffect를 통해 서버에 자원을 요청하고 하는 방식이 가능하다.

그러나 해당 방식은 클라이언트 사이드에서 데이터를 패칭하는 방식이다

만약, 서버사이드에서 미리, 특정 dynamic route로 이동했을 때의 데이터를 pre-rendering해야한다고 하자.

그렇다면, param에 있는 값을 이용해서 업데이트를 해야 하는데, useRouter은 클라이언트사이드이므로 사용할 수가 없다.

이때 필요한 것이 getStaticPaths이다.

우선 getStaticProps에는

getStaticProps에는 인자로 context라는 것을 받을 수 있다. 이 context가 하는 역할이 useRouter과 같다.
스크린샷 2022-01-22 오후 1 49 20

그렇게 전달받은 context에 해당 페이지의 param이 존재하므로, 이 값을 이용해서 서버에 데이터를 요청한 후, props로 전달하면 되지 않을까? 그렇게되면 pre-rendering 타이밍에 getStaticProps가 먼저 호출되면서 props로 데이터를 전달하고, props로 전달된 값으로 function component를 pre-rendering하여 클라이언트에 전달해주기만 하면 될 것이다. 하지만,

스크린샷 2022-01-22 오후 1 57 05 스크린샷 2022-01-22 오후 1 57 19 스크린샷 2022-01-22 오후 1 58 30 스크린샷 2022-01-22 오후 1 58 36

다른 페이지에서 Link를 통해 해당 dynamic page로 이동할 경우, 저런식으로 getStaticPaths를 사용해달라는 에러를 낸다

getStaticPaths?

미리 언급되었듯이, Next.js는 미리 서버사이드에서 페이지에 대한 pre-rendering을 진행한다고 하였다.
그리고, 만약 미리 서버에서 데이터 패칭과 같은 행위가 필요할 경우 getStaticProps를 사용하고, 이 함수를 export한다는 것은 Next.js에게 "나 미리 SSG을 함께 해서 pre-rendering을 하고 싶습니다." 라고 요청하는 것이다.

근데, 만약 이 getStaticProps가 실행되는 장소가 dynamic path이고, context의 param을 알아야 한다고 하자.
첫 pre-rendering이 진행되는 시점에서 Next.js는 해당 param이 무엇인지를 알지 못한다. (왜냐하면 알게되는 순간은 링크를 눌러 이동했을 때에 그 순간이기 때문이고, 그 전까지는 pre-rendering상황에서는 알 수 없기 떄문이다)

즉, 다시말하자면 SSG시점에서 getStaticProps에게 context로 오는 값들을 미리 알려주어 이 값들을 가지고 pre-rendering을 하라고 일러줘야한다.

getStaticPaths는 dynamic path 파일의 getStaticProps 아래 설정해주면 된다.
(객체를 리턴하고, 프로퍼티로 paths라는 배열값을 가지는 내용이 존재해야 한다. 배열 요소는 객체로, 그 안에 params가 존재해야 한다.)
스크린샷 2022-01-22 오후 2 12 25

다시금 말하지만, 만약 SSG를 하지 않을것이라면 굳이 필요하지 않다. 어차피 클라이언트단에서 라우팅을 할 것이기 때문이다.
하지만, 해당 dynamic file들을 모두 pre-rendering을 하려는 의도가 존재한다면 이렇게 getStaticPaths를 이용한 사전 설정을 해줘야 한다.

해당 옵션을 통해, 첫 pre-rendering 당시 서버는 어떤 페이지를 랜더링해놔야 할지를 알게 된다.
실제로 build를 해보면 해당 dynamic routes들의 페이지들도 모두 랜더링이 된 것을 볼 수 있다.
스크린샷 2022-01-22 오후 2 26 35

그렇게 build를 완료하면, 해당 dynamic route로 전송되야 하는 props의 데이터들이 json 형태로 저장되어 있고,
스크린샷 2022-01-22 오후 2 31 39

만약 클라이언트가 Next.js 서버로부터 해당 페이지를 내려받는다면 이때 이 json 데이터들이 같이 한번에 딸려서 패치되는것을 볼 수 있다. 즉, 각각의 dynamic page에 들어가기 이전에, 이미 필요한 데이터들은 다 json 형태로 패칭되는 상태이다.

이말인 즉슨, getStaticProps의 내부에서 무언가를 작업해서 props로 넘겨줄 때, json 형태로 데이터가 다 날아가는 상태이므로 보안이 설정되지 않았다면 중요한 개인정보와 같은 것을 pre-rendering하는것은 피하는게 좋다. 해당 내용이 필요하다면 클라이언트 사이드에서 JWT와 같은 형태를통해 전달하는 것을 추천한다.

스크린샷 2022-01-22 오후 2 30 00

근데 만약 dynamic path가 수십만개면 어떻게 합니까?

상상해보면, 수십만개나 되는 dynamic path를 일일이 getStaticPaths로 전달해주는것은 불가능에 가깝다. 그렇다고 수십만개에 달하는 모든 dynamic path의 케이스에 대해서 다 pre-rendering을 하여 저장하고 있는것도 옳지 못하다.
그래서 현실적으로 말해서 저렇게 업데이트를 하는 경우는 없고, 추가적인 옵션인 fallback을 통해 해결한다.

fallback? : 이 옵션은 getStaticPaths에게 전부 다 첫 build 타임에 pre-rendering을 하는 것이 아닌, client가 필요할 때마다 dynamic path에 대해 getStaticPaths를 호출하여 페이지를 SSG을 실행한 후 유저한테 JSON을 전달하라는 의미가 된다.
즉, 처음부터 전부 다가 아닌, 필요에 따라. 라는 형태의 랜더링을 하게된다.

스크린샷 2022-01-22 오후 2 41 52

위와같이 설정할 경우, 실제 pre-rendering이 되는 dynamic page는 p1만 해당하고, 나머지는 요청이 들어올 때마다 rendering을 해서 전해진다.

다만 위와같은 경우로 제작했을 때, 유저가 Link가 아닌 고의적으로 URL에 page 경로를 입력하여 들어가려고 할 때 에러를 만들어낸다.

스크린샷 2022-01-22 오후 2 43 18

그 이유는 새로운 경로를 url에 쳐서 엔터를 누른다는것은 새로운 리퀘스트가 간다는 의미인데, 그 상황에서 서버가 새로운 json 데이터를 마저 생성하기도 전에 페이지적으로 뭔가를 보여주려고 시도하기 때문에 그렇다.

따라서, 이를 해결할 방법으로
스크린샷 2022-01-22 오후 2 44 46

이처럼 dynamic route에 대해서는 해당 필요한 값이 SSG 에 의해 생성되지 않았을 때의 처리를 따로 해주던가
스크린샷 2022-01-22 오후 3 00 07

blocking option을 통해 미리 json 데이터가 만들어지기 전까지는 페이지를 보여주지 않도록 대기시킬 수도 있다.

참고로, 존재하지 않는 데이터에 대해서 요청을 날리게 되는 경우가 있다. 예를들어 id는 3까지인데 4에 대한 내용을 요청했으면 로딩이 끝난 직후 필요한 데이터가 프랍에 없기 떄문에 에러를 낸다. 그래서 이것을 사전에 막아야 한다. getStaticProps 로직 내에서 return으로 404를 내도록 만들게 하면 된다.

정리하자면

getStaticProps를 이용해서 미리 pre-rendering을 하려고 할 때, 해당 페이지에 dynamic path가 존재한다면 처리해야 할 내용은 3가지이다.

  1. getStaticPaths를 설정하고, fallback을 true로 설정하거나 아니면 모든 dynamic page에 해당하는 값들을 param으로 리턴해줘서 pre-rendering하기
  2. 만약 fallback을 true로 설정했을 경우, getStaticProps에 path에러처리를 위한 return {notFound:true} 처리
  3. fallback을 true로 설정했을 경우, 클라이언트단에서 아직 prop이 준비되지 않은 상황에 대한 예외처리를 해줘야 함
profile
자라나라 프론트엔드 개발새싹!

0개의 댓글