주중 작업 중 정적 페이지가 아닌 next.js에서 [param].tsx
와 같이 사용하는 동적 페이지 라우팅 이슈 트래킹을 해보았다. 즉 이전 페이지나 이후 페이지가 동적 페이지인 경우 back
메소드가 제대로 동작하지 않았다. 작업 당시에는 피쳐 개발이 우선이었기에 push
혹은 replace
로 대체하여 사용했었다. 하지만 해당 메소드들은 이동하는 페이지 경로를 지정해야하기 때문에 히스토리가 꼬일 우려가 있었고 그런 이슈가 발생하기도 하였다. 그래서 해당 이슈에 대해 자세히 알아봐야겠다는 생각이 들었다. 케케
우선 첫번째로 push 메소드를 가져오는 useRouter
를 의심해보았다. next 13버전 이상부터는 next/router 대신 next/navigation
을 사용하기 때문에 이 부분에서 이슈가 발생했는지 확인해보았다. 하지만 우리 서비스는 next 12버전을 사용하고 있었기 때문에 정상적으로 next/router를 사용하고 있었다.
두번째로 back
메소드를 트리거 시키는 dom의 native event
를 의심해보았다. 간혹 dom의 native event로 인해 다른 이벤트가 정상적으로 트리거되지 않는 이슈가 발생하기도 하기 때문에 해당 부분을 의심해보았다. 하지만 back
메소드를 트리거 시키기 전 native event를 무효화시킨는 event 객체의 preventDefault 메소드를 트리거 시켜도 여전히 해당 이슈가 유지되었다. 하,,
세번째로 동적 페이지에서만 발생하는 이슈였기 때문에 해당 부분에 초점을 맞추어 알아보았다. 우선 next는 프로젝트를 빌드할 때 필요한 페이지를 미리 사전 렌더링 시킨 후 빠르게 사용자와 상호작용 할 수 있도록 하는 특징을 가지고 있다. (getStaticProps
또는 getServerSideProps
메소드가 정의된 경우 해당 메소드를 통해 페이지에 필요한 데이터를 미리 받아온다.) 또한 컴포넌트 내에 또한 정적 페이지보다 동적 페이지가 덜 캐싱된다는 특징도 가지고 있다. 이 때 동적 페이지의 경우 getStaticPaths
를 통해 사전 렌더링이 필요한 페이지들을 렌더링 시켜놓을 수 있다. 또 쿼리스트링이 있는 경우에는 쿼리스트링을 포함한 URL별로 페이지를 미리 불러와 캐싱한다.
위 next의 기본 동작을 생각하며 구글링을 해보니 이게 왠걸.. 잡았다 요놈… 이거다..
구글링 해본 결과 “next router의 경우 사전의 렌더링 되어 있지 않은 경로로 이동을 시도하는 경우 동작하지 않을 수 있다” 라는 내용을 찾을 수 있었다. 하.. 해당 내용을 확인하고 난 뒤 뒤로 가기나 앞으로 가기를 시도하는 동적 페이지가 사전 렌더링 되어있지 않아 페이지 url만 변경되고 실제 view는 바뀌지 않는다는 것을 알 수 있었다. 일단 이슈 트래킹은 완료했다. 하하…. 그럼 이걸 어떻게 해결할까.. 나는 우선 getStaticPaths를 핸들링해서 해결할 수 있을 것 같다는 생각을 하였다. 우선 해당 문제가 getStaticPaths의 fallback 속성의 특징은 아래와 같다.
| false | • getStaticPaths가 반환하지 않은 모든 path에 대해서 404 페이지를 반환한다. 아래와 같은 경우에 사용할 수 있다 ◦ 적은 숫자의 path만 프리렌더링 해야하는 경우 ◦ 새로운 페이지가 추가 될 일이 많지 않은 경우 → 새로운 페이지가 자주 추가 된다면, 추가될때마다 다시 빌드해줘야한다 | | --- | --- | | true | • getStaticProps의 동작이 바뀌게 된다.
1. getStaticPaths가 반환한 path들은 빌드 타임에 HTML로 렌더링된다
2. 이외의 path들에 대한 요청이 들어온 경우, 404 페이지를 반환하지 않고, 페이지의 **"fallback" 버전**을 먼저 보여준다
3. 백그라운드에서 Next js가 요청된 path에 대해서 getStaticProps 함수를 이용하여 HTML 파일과 JSON 파일을 만들어낸다
4. 백그라운드 작업이 끝나면, 요청된 path에 해당하는 JSON 파일을 받아서 새롭게 페이지를 렌더링한다. 사용자 입장에서는 **[ fallback → 풀 페이지 ]와 같은 순서**로 화면이 변하게된다.
5. 새롭게 생성된 페이지를 기존의 빌드시 프리렌더링 된 페이지 리스트에 추가한다. 같은 path로 온 이후 요청들에 대해서는 이때 생성한 페이지를 반환하게된다.
"fallback" 상태일 때 보여줄 화면은 next/router의 router.isFallback 값 체크를 통해서 조건 분기하면 된다. 이때 페이지 컴포넌트는 props로 빈값을 받게된다.
아래와 같은 경우에 사용할 수 있다 • 데이터에 의존하는 정적 페이지를 많이 가지고 있으나, 빌드 시에 모든 페이지를 생성하는건 너무나 큰 작업일 때 ◦ 몇몇 페이지들만 정적으로 생성하게 하고, fallback 옵션을 true로 설정해주면 이후 요청이 오는 것에 따라서 정적 페이지들을 추가하게 된다 → 빌드 시간도 단축하고, 대부분 사용자들의 응답 속도도 단축할 수 있다 | | blocking | true일 경우와 비슷하게 동작하지만, 최초 만들어놓지않은 path에 대한 요청이 들어온 경우 fallback 상태를 보여주지 않고 SSR처럼 동작한다. 이후 true 옵션과 같이 기존의 정적 페이지 리스트에 새로 생성한 페이지를 추가한다. |
참조 : https://velog.io/@mskwon/next-js-static-generation-fallback