CloudFront + CloudFront functions 이용하여, Next.js 번들파일 효율적으로 서빙하기! 🧞
안녕하세요.
원티드랩 프론트엔드팀 김성광 입니다.
배경 🧪
원티드를 WebPageTest에서 체크를 해보았습니다.
아래와 같이 Next.js 서버에서 js, css 서빙 시간이 오래 걸리는 것을 발견하였습니다.
느린 원인은 2가지로 판단됩니다.
- 지리적인 Latency 발생 🌏
WebPageTest: Virginia USA 🇺🇸
Next.js 서버: 한국 🇰🇷 - 서버 부하 🔥
일반 Request 처리
번들파일 (js, css) Request 처리
CDN Support with Asset Prefix 🌐
CDN Support with Asset Prefix 를 적용하게 되면, 번들파일 (js, css)을 CDN에서 서빙할 수 있게 되고, CDN을 이용하게 되면, 사용자와 가까운 곳에서 콘텐츠를 전송함으로써 더 빠르고 안정적인 온라인 경험을 제공합니다.
출처: https://imagekit.io/blog/what-is-content-delivery-network-cdn-guide/
CDN에 파일만 올리면 어느 정도 성능이 올라가지만,
더 영리하고, 효율적으로 이용하기 위해서 셋팅이 필요합니다.
이번 글에서
CloudFront + CloudFront functions을 이용하여, Next.js 번들 파일을 효율적으로 이용하는 방법에 대해 소개합니다.
목표 ✨
(번들 파일을 CDN 서빙시)
아래 Response Header 셋팅이 목표 입니다.
access-control-allow-origin: * // CORS
cache-control: public,max-age=31536000,immutable // 캐싱 정책
content-encoding: br // 최신압축 알고리즘 적용
x-cache: hit from cloudfront // cache hit
흐름(flow): Browser ↔ CloudFront ↔ S3
본격적인 작업에 들어가기전에
흐름에 대해서 알아보겠습니다.
아래 그림은 Browser ↔ CloudFront ↔ S3 기본 흐름입니다.
여기서 주목해야 할 포인트는 아래와 같습니다.
- CloudFront의 캐싱 만료 시간은 TTL 값을 사용한다.
- S3(origin) 응답 해더에
Cache-Control
설정이 없으면 CloudFront “기본 TTL” 값으로 캐싱 만료가 세팅됩니다. (Clinet1 호출 시)
S3에 Response Header에Cache-Control
을 붙여보겠습니다.
S3 Response Header 추가 방법
- 파일, 디렉토리를 체크
- 작업 → 메타데이터 편집
- 메타데이터 추가
Client 1 호출 시, CloudFront → S3 순서로 호출되고,
S3에서 “메타데이타" 세팅한 값이 내려옵니다.
CloudFront는 S3 Response HeaderCache-Control
값으로, 캐시 만료 타임을 세팅됩니다.
참고:
더 자세한 캐시 만료 관리에 대한 글은 아래 링크를 확인해 주세요.
관심사 분리 ➗
S3에 “메타데이터” 및 CORS 설정을 추가하게 되면, CloudFront, S3 양쪽 모두 추가될 수 있어, 아래와 같이 역할을 나누겠습니다.
S3
파일 저장만 담당. (다른 역할은 없음)
CloudFront
- CloudFront 캐시만료
- Response Header 조작 (CORS,
Cache-Control
)
이제 본격적으로 원하는 Response Header를 만드는 방법에 대해 알아보겠습니다.
access-control-allow-origin: * // CORS
cache-control: public,max-age=31536000,immutable // 캐싱 정책
content-encoding: br // 최신압축 알고리즘 적용
x-cache: hit from cloudfront // cache hit
x-cache: hit from cloudfront
캐시 hit가 일어나야 성능이 좋아지게 됩니다.
CloudFront를 사용하는데, hit가 일어나지 않는다면 사용 의미가 크게 없어집니다.
CloudFront TTL 조정
빌드 될 때마다 번들 파일명이 변경되기 때문에, CloudFront에서 캐시를 오래가지고 있을수록 이득입니다.
CloudFront에 기본 제공하는Managed-CachingOptimized
정책을 살펴보겠습니다.
위에 말한 “관심사 분리”를 통해 S3에 max-age 설정하지 않습니다.
(S3 max-age 응답이 없을 시 기본 TTL 값 캐시 만료)
기본 TTL을 최대 TTL 값으로 세팅 하겠습니다. (기본TTL == 최대 TTL)
신규 CloudFront 캐싱 정책 생성
신규로 캐시 정책 생성 하고, CloudFront에 적용을 합니다.
신규로 만든 캐시정책은 아래와 같습니다.
content-encoding: br
Brotli 압축을 CloudFront 정책에서 쉽게 적용이 가능합니다.
Brotli가 지원 안되는 브라우저도 있기 때문에, Gzip도 활성화 합니다.
access-control-allow-origin: *
cache-control: public,max-age=31536000,immutable
cache-control: public,max-age=31536000,immutable
이 헤더는 CloudFront 순수 세팅만으로 header를 내릴 수 있는 방법이 쉽지 않습니다.
CloudFront Functions
2021년 5월경에 도입 되었으며 4가지 사용 사례를 제공합니다.
캐시 키 정규화
URL 리디렉션 또는 다시 쓰기
요청 권한 부여
해더 조작 👈👈👈👈
“해더 조작” 원하는 기능을 제공하고 있습니다!
친절하게 예재코드까지 제공합니다.
예재코드를 참고하여, 우리가 추가하고 싶은 코드를 추가합니다
function handler(event) {
var response = event.response;
var headers = response.headers;
// CORS header
if (!headers['access-control-allow-origin']) {
headers['access-control-allow-origin'] = {value: "*"};
console.log("Access-Control-Allow-Origin was missing, adding it now.");
}
// cache-control
headers['cache-control'] = {value: 'public,max-age=31536000,immutable;'};
return response;
}
CloudFront에서 아래와 같이 연결 합니다.
적용 결과
Respose Header에 셋팅된 것을 확인하였습니다.
실제 성능은 얼마나 좋아졌을까?
Lighthouse 점수 향상 🚀
테스트 환경 (5번씩 측정, 중간값을 표기)
- URL:
https://www.wanted.co.kr/newintro
- 브라우저 : 크롬 (시크릿탭)
- lighthouse 설정:
AS-IS: 47점
TO-BE: 57점 (+10) 👍👍
번들파일 용량 감소 💫
AS-IS
- js: 631 kb
- css: 130 kb
TO-BE (기존대비: 12.8% 용량감소 👍👍)
- js: 547 kb (13% 용량감소 👍👍)
- css: 116 kb (11% 용량감소 👍👍)
2021–10–13: 서버 모니터링 결과 내용추가
프론트 서버의 Request 처리량 약 77% 감소 하였습니다. (서버 가용성 Up)
마무리
CDN Support with Asset Prefix을 적용하다가, 입사 후 첫 장애도 냈습니다.
장애를 발판 삶아 CloudFront에 대해 많이 배우고, 성장하게 된 것 같습니다.
현재에 안주하지 않고, 더 높은 목표를 세우고, 실패하고, 배우고, 성장하는 개발자가 되도록 하겠습니다.
참고
- https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/Expiration.html#ExpirationDownloadDist
- 자습서: CloudFront 함수를 사용하여 간단한 함수 생성 — Amazon CloudFront
- stale-while-revalidate
- Cache-Control — HTTP | MDN
원티드에서는 다양한 직군에서 적극적으로 채용중입니다! 서버, 웹, 앱, 디자인 등 제품을 만들어가는 각자의 분야에서 전문적인 분들과 함께 일하기를 기대하고 있습니다. 회사 채용 정보 페이지를 확인해 주세요!