Next.js는 기본적으로 빌드 시 아래와 같이 .html이 붙게 된다.
하지만, 빌드 된 파일에서 이동 시에 .html이 사라지게 된다. (프론트 분들이 잘 모르겠다고 해서 이유는 잘 모르지만, 추측건데 Next.js가 싱글 페이지 방식을 사용하면서 아예 새로운 창을 띄우는 것이 아닌 내부 html을 바꿔치기를 하면서 .html 확장자를 숨기는 듯 하다.)
이 경우 새로고침을 하게 되면, 결국 사용자는 아래와 같은 화면을 마주하게 되고, 사용자 입장에서는 이 서비스를 더 이상 사용하고 싶지 않을 것이라고 판단했다.
이를 해결하기 이전에, 우리는 AWS CloudFront를 CDN 서버로 두었다. 이유는 TLS HandShake를 위한 인증서 발급을 위해 두었다. (뿐만 아니라, CDN을 두면 먼 거리도 빠르게 접근 가능하고 실제 S3 위치를 숨기는 등 여러모로 장점이 있다.)
여기서 문제를 해결하기 위해, Lambda Function을 두어 들어오는 요청 이벤트에 따라 url을 변경하려고 하였다. 하지만 더 좋은 방법이 존재했는데, 바로 CloudFront의 함수 기능이었다. 아래와 같이 단순하게 요청 이벤트가 들어왔을 때, uri를 바꿔 return하게 되면, CloudFront에서 S3로 원본 데이터에 대해 요청을 보내게 될 때, 변경을 해줄 수 있게 된다. (물론 CloudFront 배포 생성 시 함수를 설정 해야 한다.)
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri.endsWith('/')) {
request.uri += 'index.html';
} else if (!uri.includes('.')) {
request.uri += '.html';
}
return request;
}
참고
- Origin Request: CloudFront가 오리진 서버에 요청을 보내기 전에 발생하는 이벤트입니다. 이 이벤트는 요청을 변경하거나 오리진 서버로 보내지기 전에 캐싱을 수행할 수 있습니다. 예를 들어, 캐시 미스 시 오리진 서버에서 요청한 콘텐츠를 동적으로 생성하여 CloudFront에서 캐싱하도록 변경하는 등의 작업을 수행할 수 있습니다.
- Viewer Request: 클라이언트의 요청이 CloudFront에 도착하기 전에 발생하는 이벤트입니다. 이 이벤트는 요청을 변경하거나, 요청에 대한 인증 및 권한 부여, URL 리라이팅 등을 수행할 수 있습니다.
사실 이 문제를 봉착했을 때 고민을 정말 많이 했는데 (프론트 정적 파일의 .html 확장자를 전부 제거해야겠다! 또는 서버 사이드 렌더링으로 바꿔야하나 하는 등의 고민...), 지금 생각해보면 매우 간단하게 해결한 것 같다.