Next.js SSG + Cloudfront + S3 배포시 Cloudfront function 설정
✏️

Next.js SSG + Cloudfront + S3 배포시 Cloudfront function 설정

Description
Published
Published February 17, 2022

1. 무엇이 문제인가?

Next.js로 빌드한 스태틱(Static)을 S3에 서빙하면 생기는 문제 중 하나는 브라우저에서 요청한 주소와 실제 리소스의 주소(URI)가 다르다는 것입니다.
예를들어,
/pages/index.tsx/pages/foo/bar.tsx
를 Next.js(디렉토리 기반 라우팅)에서 빌드를 한 경우
dist/index.htmldist/foo/bar.html 로 스태틱이 생성이 될겁니다. 이 스태틱을 그대로 배포하면
www.AAAAA.com 은 문제가 없지만
www.AAAAA.com/foo/bar 혹은 www.AAAAA.com/foo/bar/로 접근을 한다면 www.AAAAA.com/foo/bar/index.html 을 조회 하게 되면서 원하는 리소스를 응답 받을 수 없습니다.
클라이언트 사이드 라우팅은 문제가 없습니다. 주소창에 직접 주소를 치고 들어가거나 새로고침을 했을때 처럼 새로운 문서를 요청 할 때 문제가 발생합니다.

2. 해결방법은?

1) trailingslash

사실 Next.js 에서는 trailingSlash 라는 옵션을 제공합니다.
// next.config.js module.exports = { ... trailingSlash: true, };
next export 를 하여 스태틱을 생성한다면 trailingSlash
  • true
    • /pages/foo/bar.tsx => /dist/foo/bar/index.html
  • false
    • /pages/foo/bar.tsx => /dist/foo/bar.html
로 빌드가 됩니다.
그렇게 되면 배포를 하더라도 www.AAAAA.com/foo/bar/ 로 접근이 가능하겠죠.

2) cloudfront function (or lambda)

근데 저는 뒤에 / 가 붙는게 마음에 들지 않았습니다.
www.AAAAA.com/foo
www.AAAAA.com/foo/bar 이런식으로 접근하고 주소창의 URL도 / 가 없었으면 좋겠습니다.
따라서 cloudfron function을 아래와 같이 작성해 주었습니다. (es5딥빡..)
var config = { suffix: '.html', appendToDirs: 'index.html', removeTrailingSlash: true, }; var regexSuffixless = /\\/[^/.]+$/; var regexTrailingSlash = /.+\\/$/; function handler(event) { var request = event.request; var uri = request.uri; var suffix = config.suffix; var appendToDirs = config.appendToDirs; var removeTrailingSlash = config.removeTrailingSlash; // Redirect (301) non-root requests ending in "/" to URI without trailing slash // /foo/bar/ => /foo/bar (res) if (removeTrailingSlash && uri.match(regexTrailingSlash)) { var response = { statusCode: 301, statusDescription: 'Moved Permanently', headers: { location: { value: uri.slice(0, -1) }, }, }; return response; } // Append ".html" to origin request if (suffix && uri.match(regexSuffixless)) { request.uri = uri + suffix; return request; } // If nothing matches, return request unchanged return request; }
  • AAA.com/foo/ => AAA.com/foo 로 리다이렉트
  • AAA.com/foo => AAA.com/foo.html 리퀘스트 리턴
notion image
notion image
필요에 따라 .html 패턴도 리다이렉트 시켜도 괜찮을것 같습니다.
사실 중요한건 통일 같습니다..!