동적 라우팅 페이지에서 getStaticPaths
및 getStaticProps
를 통해 Static Generation을 적용하려는 상황에서, 다음과 같은 문제가 발생하였다.
Link
컴포넌트를 통해 동적 라우팅 페이지로 접근할 때에는 getStaticProps
가 정상적으로 호출됨.getStaticProps
가 호출되지 않음.내 코드의 경우 getStaticProps
에서 비동기 함수를 통해 외부 데이터를 불러와 페이지 컴포넌트로 넘겨주고 있으며, getStaticPaths
에서 빌드 시 미리 생성할 페이지 경로(path
)를 따로 주진 않았다.
fallback
이 true
이므로 미리 생성되지 않은 페이지여도 요청 시점에 동적으로 잘 생성될 것이라 생각했는데, getStaticProps
가 호출되지 않아 페이지 렌더링에 필요한 데이터를 받지 못해 에러가 발생한 모습이다.
예상치 못한 현상이 일어나서 조금 당황스러웠다.
처음엔 이렇게 getStaticPaths
에 모든 동적 페이지 경로를 포함하여 빌드 시 모든 페이지를 미리 생성하도록 하였다. 다만 이 방법의 경우 개발 모드에서 매 요청마다 전체 DB 쿼리가 호출되므로 속도가 상당히 느려진다는 단점이 있었다.
Static Generation을 포기하고 대신 이렇게 getServerSideProps
을 사용하면 매 요청마다 해당 함수가 정상적으로 호출되었고 페이지 렌더링 문제 또한 해결되었다. 속도 측면에서도 위 방법보다 훨씬 빨랐다.
처음엔 Link
컴포넌트를 통해 접근하는 것과 URL을 통해 직접 페이지를 요청하는 것이 내부적으로 다르게 동작하는 것으로 추측했다. 하지만 원인은 따로 있었고 결과적으로 에러가 아닌 정상적으로 동작하는 상황이었다.
사실 getStaticProps
가 호출되지 않는 것이 아니라 뒤늦게 호출되는 것이었다.
Next.js 공식 문서의 getStaticPaths
부분에는 fallback
에 대한 다음 설명이 존재한다.
만약
fallback
이true
이면, 빌드 시간에 만들어지지 않은 페이지를 요청해도 404 페이지를 응답하지 않는다.
대신, 첫 요청에 대해서는 fallback 버전의 페이지를 응답하고, 백그라운드에서 요청받은 경로에 따른 HTML 및 JSON을 정적으로 생성한다. 여기에는getStaticProps
를 호출하는 것 또한 포함된다.
나는 getStaticProps
가 어떤 상황에서도 페이지 생성 전 반드시 호출되는 줄 알았기에, 이를 통해 받는 데이터가 존재하지 않을 경우의 분기 처리를 따로 하지 않았다. 그렇기에 렌더링에서 에러가 발생하는 것이었다. (fallback 페이지에 대한 개념도 느슨하게 생각하고 있었다)
fallback == true
를 페이지 요청 시에 동적으로 생성하도록 해주는 옵션 정도로만 알고 있었는데, 생각보다 중요한 절차가 있었다. 버그가 아니여서 다행이지만, 앞으로 이런 일이 있을 때마다 가장 먼저 공식 문서를 꼼꼼히 읽어봐야겠다...