BLOG
소비자 대상 웹사이트의 경우 사이트의 로딩 속도가 사용자의 경험과 비즈니스 성공에 대하여 직접적인 영향을 끼칩니다. 만약 웹사이트가 로딩되는데 오래 걸릴 경우, 사용자는 트랜잭션이 완료 되기 전에 웹사이트를 나올 수 있으며 이는 수익에 직접적인 영향을 줄 수 있습니다. Amazon CloudFront와 같이 CDN(콘텐츠 제공 네트워크)을 사용하여 지연 시간이 적고 전송 속도가 빠른 전 세계 고객에게 안전하게 데이터, 비디오, 애플리케이션 그리고 API를 제공함으로써 웹사이트의 성능을 향상시킬 수 있습니다.
성능을 향상시키기 위해서는 CloudFront distribution을 설정하고 CloudFront의 전 세계적으로 엣지 네트워크를 통해 웹사이트의 트래픽을 전송하도록 구성하십시오. 추가적으로 CloudFront는 다양한 최적화 옵션을 제공합니다. 이번 게시물에서는 CloudFront에서 사용할 수 있는 최적화 옵션을 활용하여 웹사이트의 성능을 세부적으로 조정하는 법에 대하여 배울 것 입니다.
CloudFront의 가속화 이점
Amazon CloudFront는 global network of edge locations과 지능형 소프트웨어로 전 세계에 위치한 사용자들에게 콘텐츠를 전달합니다. HTML, 이미지, 스타일시트, 그리고 자바스크립트 파일 같은 웹 사이트의 일부는 CloudFront 엣지 위치 및 지역 엣지 캐시에 저장된 복사본에서 제공됩니다. 새로 업데이트된 콘텐츠나 API dynamic 요청 같이 로컬로 캐시화 되지 않은 경우 CloudFornt는 AWS 관리 global network를 통해 지속적인 연결로 빠르고 최적화된 경로를 통해 서버에서 해당 부품을 가져옵니다. GET, PUT 그리고 POST를 포함한 모든 HTTP방법에 대한 지원을 통해 CloudFront는 전체 웹사이트를 가속화 할 수 있습니다.
CloudFront는 인터넷 커뮤니케이션 프로토콜에 새로운 기술을 지속적으로 구현하여 사용자들에게 제공합니다. TLS세션 재개, TCP fast open, OCSP stapling, S2N, 그리고 request collapsing과 같은 기능은 기본적으로 구성할 필요 없이 설정됩니다. 추가적으로 다음과 같은 CloudFront 분포에 대해 활성화 하도록 선택할 수 있는 최적화 기능이 있습니다. 다음과 같습니다:
- 웹사이트의 모든 구성 요소를 다운로드 하기 위해서 동일한 도메인과 동일한 TCP연결을 사용하려면 Enable HTTP/2 를 사용하도록 설정해야 합니다. 이를 활성화 하기 위해 다운로드 성능을 향상시키는 기존 방법인 도메인 sharding을 구현할 필요가 없으며 사용자에게 필요한 DNS resolutions를 줄일 수 있습니다.
- Origin에 대해 round trip을 저장하려면 Enable HTTP to HTTPS redirection을 활성화 해야 합니다.
- Fine-tune origin timeouts. CloudFront를 사용하면 두 가지의 timeout을 구성하여 origin에 연결을 최적화 할 수 있습니다. 읽기 제한 시간은 CloudFront가 사용자 지정 origin에서 응답을 기다리는 시간을 말합니다. 기본값은 30초이지만 특정 작업이 있는 경우 사용자가 한 요청에서 트랜잭션을 성공적으로 완료 할 수 있도록 읽기 제한 시간을 더 길게 구성해야 합니다. Keep-alive idle timeout은 CloudFront가 연결을 닫기 전에 origin 서버와 연결을 유지하는 최대 시간을 말합니다. 제한 시간은 5초이지만 origin 서버가 지원하는 경우 최대 60초까지 더 높은 값으로 구성할 수 있습니다. 이 기능은 CloudFront를 통해 dynamic 콘텐츠를 제공할 때 굉장히 유용합니다. 그 이유는 모든 요청이 origin으로 전달 되어도 매번 새 연결을 만들지 않아도 되기 때문입니다.
Caching 전략 정의
웹 애플리케이션의 경우 CloudFront와 사용자 브라우저를 결합하여 사용자에게 더 가까운 콘텐츠를 캐싱할 수 있습니다. 이러한 캐시를 제어하는 방법은 origin에서 보내는 Cache-Control HTTP 헤더를 통해, TTL(Time to live)를 설정하여 개체가 캐시되는 기간을 설정할 수 있습니다.
CloudFront는 캐시컨트롤 해더를 수상합니다. 이 뜻은 응답에 있어 캐시-제어 헤더가 있는 경우 CloudFront는 캐시-컨트롤 최대값으로 지정된 시간 동안 엣지 위치에서 개체를 캐시합니다. 만약 캐시-컨트롤 헤더가 없는 경우 CloudFront는 해당 캐시 동작에 지정된 Default TTL 기간 동안 개체를 캐시합니다. 추가적으로 캐시 동작의 Minimum TTL과 Maximum TTL필드를 사용하여 의도치 않게 너무 짧거나 긴 TTL이 설정되지 않도록 보호함으로써 CloudFront에 의해 개체가 캐시되는 최소시간 과 최대시간에 대하여 정의할 수 있습니다.
웹 사이트를 구성하는 다양한 개체에 대하여 원하는 캐싱 행동을 정의하기 위해 캐시-컨트롤 헤더를 기본방법으로 사용하는 것을 추천 드립니다. 예를 들면 다음과 같습니다:
- 만약 캐시-컨트롤 헤더의 max-age 값이 사용자가 정의한 minimum TTL과 maximum TTL 사이에 있는 경우 CloudFront는 최대 기간에 지정된 시간에 대해 개체를 캐시합니다.
- 만약 max-age 값이 사용자가 정의한 minimum TTL보다 작으면 CloudFront는 minimum TTL값에 대해 개체를 캐시합니다.
- 만약 max-age 값이 사용자가 정의한 maximum TTL보다 큰 경우 CloudFront는 최대 TTL 값에 대해 개체를 캐시합니다.
웹사이트에서 아래의 예제인 e-commerce 웹사이트를 통해 최적화한 캐싱 전략을 정의하는 방법을 알아보겠습니다.
일반적으로 쇼핑 웹사이트의 한 페이지에는 네 가지 메인 카테고리 중 하나에 속할 수 있는 정적 구성요소와 동적 구성요소가 조합되어 있으며, 각 구성 요소에는 고유한 특성을 충족하는 캐싱 정책이 필요합니다.
- 로그인한 사용자의 이름 같은 Private cacheable content입니다. 이 데이터는 오직 한 사용자만 로그인 할 수 있으며 변경되지 않으므로 사용자 브라우저의 캐싱에는 이상적이지만 CloudFront에는 적합하지 않습니다. 예를 들어 사용자 브라우저에서 1시간 동안 이 정보를 캐시 하려면 HTTP 응답으로 캐시-컨트롤: 개인, max-age=3600 헤더를 보낼 수 있습니다. 이 private directive는 단일 사용자를 위한 것이며 Amazon CloudFront와 같은 CDN 공유 캐시 에 의해 캐시 되어서는 안 된다는 것을 의미합니다.
- 사용자 카트의 항목 수와 같은 private dynamic content입니다. 이 데이터는 단일 사용자와도 관련이 있지만 검색 세션 중에 변경될 수도 있습니다. 이 뜻은 캐싱에 적합하지 않다는 것을 의미합니다. 캐시-컨트롤: no-store 헤더를 전송하여 브라우저와 CloudFront 모두에서 이 정보에 대한 캐싱을 사용하지 않도록 설정 할 수 있습니다.
- 홈페이지에 있는 제품 이미지 같은 shared static content입니다. 이 이미지는 많은 사용자에게 제공되며 자주 바뀌지 않습니다. 따라서 CloudFront와 브라우저에서 모두 캐싱 할 수 있습니다. 예를 들어 이 이미지를 일주일 동안 캐시하려는 경우 응답에 캐시-컨트롤: public, max-age=604800 헤더를 보낼 수 있습니다. 만약 origin이 캐시-컨트롤 헤더가 돌아오지 않는다면 CloudFront 헤더에서 cache behavior를 생성하고 기본 TTL을 604800초 (7일)로 구성할 수 있습니다. 다른 제품 이미지를 디스플레이 하려면 버전 URL을 사용하는 것을 추천 드립니다. 예를 들어 현재 이미지가 /products/product-v1.jpg 를 사용하여 새 이미지를 생성하고 홈페이지 HTML에 참조하십시오. 이렇게 하면 CloudFront에서 알 수 있으나 이전에 캐시된 이미지를 처리해서는 안됩니다.
- 홈페이지의 HTML같은 shared mutable content 입니다. 이 콘텐츠는 많은 사용자가 요청하며 개발자가 새 기능을 발표하거나 제품 목록을 변경하는 등 시간이 지남에 따라 변경할 수 있습니다. 필요에 따라 브라우저 캐시와 CloudFront에 대해 서로 다른 TTL을 사용하여 사용자의 컨텐츠를 업데이트 할 속도와 원본에서 오프로드 할 트래픽 양을 조절할 수 있습니다. 예를 들어 브라우저 캐시에 TTL=0을 사용하여 사용자가 CloudFront에서 최신 콘텐츠를 가져오도록 하고 예를 들어TTL을 10분으로 짧게 설정하여 엣지 위치에서 최신버젼을 캐시하여 사용자에게 제공할 수 있습니다. CloudFront와 TTL을 구분하는 것에는 두 가지의 기술이 있습니다. 첫 번째 방법은 각 캐시를 개별적으로 대상으로 하는 캐시-컨트롤 헤더를 보내는 것입니다. 예를 들어 캐시-컨트롤: max-age-0, s-maxage=600은 개체를 캐시하지 않도록 브라우저에 알려주지만 CloudFront에 10분동안 캐시하도록 지시합니다. 두 번째 방법은 캐시-컨트롤: max-age=0 을 보내고 CloudFront 배포의 적용 가능한 캐시 동작의 minimum TTL 필드에 원하는 TTL을 추가하는 것 입니다. CloudFront에서 짧은 TTL일 경우 응답에 ETag header를 추가하여 리소스 내용의 해시를 사용하여 리소스 버전을 식별할 수 있습니다. CloudFront는 캐시에 있지만 만료된 리소스에 대한 요청을 수신하면 기존 개체의 ETag 값이 포함된 If-None-Match 헤더와 함께 origin에 요청을 보냅니다. Origin에서 리소스가 변경 되지 않은 경우 원본은 CloudFront에 기존 콘텐츠로 캐시에 제공될 수 있음을 알리는 304 Not Modified 응답으로 회신 할 수 있습니다. 이 매커니즘은 변경되지 않은 전체 리소스를 원본에서 가져올 필요가 없습니다. 홈페이지 HTML예제의 경우 지정된 간격에 따라 자동으로 변경사항을 감지하는 응답성과 CloudFront가 캐싱의 이점을 제공할 수 있습니다. S3를 origin으로 사용하는 경우, ETag header is added automatically to responses from S3.
객체 버전, 캐시-컨트롤 그리고 ETag와 같은 기술을 사용하여 CloudFront의 캐시에서 콘텐츠를 제거하는 방법을 컨트롤 할 수 있습니다. 또한 invalidations(무효화)를 사용하여 캐시된 개체를 Edge 캐시에서 직접 제거할 수 있습니다. 그러나 CloudFront에서 파일을 무효화 해도 사용자의 브라우저 캐시에서는 해당 파일을 삭제하지 않습니다.
캐싱 전략은 origin에서 HTTP 4xx 및 5xx 오류를 캐시하는 방법도 고려해야 합니다. 웹 사이트를 high available로 만들기 위한 최선의 노력에도 불구하고 origin에 오류가 생기는 경우가 있으며 CloudFront는 graceful 오류 처리 옵션을 제공합니다. 기본적으로 origin이 4xx 또는 5xx 상태 코드를 반환하면 CloudFront는 caches these error responses를 5분 동안 캐시하고 이 간격 후의 오류 원인이 된 문제를 해결하며 요청된 개체를 찾을 수 사용할 수 있는지 확인하기 위해 해당 개체에 대한 다음 요청을 origin에 제출합니다. 그러나 CloudFront를 사용하면 사용자 지정 TTL을 구성하여 특정 오류를 다양한 시간 동안 캐시 할 수 있습니다. 예를 들어 사용자가 기본 기간인 5분동안 캐시 된 오류 응답을 받지 않도록 하려면 10초 동안 특정 5xx 오류를 캐시하고 CloudFront를 구성할 수 있습니다. CloudFront에 만료되어 캐시된 개체가 있고 원본에서 새 개체를 가져오려고 하면 5xx 오류가 반환되고 CloudFronT는 오류 대신 오래된 (캐시되었지만 만료된) 개체를 처리합니다.
사용자가 403 또는 404개의 오류 페이지를 제공하는 대신 웹 사이트의 URL에 액세스할 수 없거나 존재하지 않는 URL로 이동한 경우 사용자 정의 오류 페이지를 제공할 수 있습니다. 예를 들어, 쇼핑 웹 사이트에서 가장 인기 있는 품목의 카탈로그나 200개의 OK 응답 코드가 있는 cute puppies 브라우저의 기본 오류 처리에 의존하지 않고 사용자의 만족도를 높이고 브랜드에 맞게 맞춤화됩니다. 예를 들어 이 응답 페이지는 Amazon S3에서 호스팅 할 수 있으므로 원본이 응답할 수 없는 경우에도 사용자에게 제공될 수 있습니다. 이를 통해 몇 가지 간단한 최후의 수단 중복성과 향상된 가용성을 제공합니다.
캐시 적중률 향상
웹 사이트의 성능을 최적화 하기 위해 CloudFront 캐시에서 가능한 오랫동안 제공할 수 있는 콘텐츠 양을 극대화 하는 것이 목표입니다. 이것을 캐시 적중률이라고 합니다. 캐시 적중률을 향상 시키는 방법에 대해 알아보기 위해서는 먼저 CloudFront가 캐시된 개체를 식별하고 저장하는 방법과 CloudFront 구성과 애플리케이션을 몇 가지 간단한 변경으로 이점을 활용하는 방법에 대해 살펴보도록 하겠습니다.
기본적으로 CloudFront는 뷰어 요청에 경로 및 Accept-Encoding 헤더를 기반으로 개체의 고유한 캐시 키를 생성합니다. 헤더, 쿠키 또는 쿼리 문자열과 같은 요청 메타데이터를 전달하도록 CloudFront 캐시 동작을 구성하면 이 추가 데이터가 캐시 키에 추가됩니다. 즉, CloudFront는 전달된 헤더 또는 쿠키 또는 쿼리 문자열의 모든 변형에 대해 서로 다른 캐시 키를 생성하고 이러한 값 중 일부에 대해 동일한 내용을 제공하더라도 고유한 개체로 캐시 합니다. 이 사실을 알고 있으면 다음과 같은 권장 사항을 따라 CloudFront에서 웹 사이트 콘텐츠에 대한 캐싱을 개선할 수 있습니다:
- 웹 사이트에 헤더 또는 쿠키 또는 쿼리 문자열의 값에 따라 응답이 다른 특정 URL이 있는 경우 CloudFront에서 해당 URL과 일치하도록 특정 캐시 동작을 생성하고 기본 캐시 동작에서 전달되는 값을 최소화하도록 그에 따라 전달된 값을 구성합니다.
- 모든 헤더, 쿠키 또는 문자열을 전달하지 않고 해당 값에 따라 다른 콘텐츠를 제공하는 데 실제로 중요한 특징 헤더, 쿠키, 또는 쿼리 문자열의 화이트리스트만 전달합니다.
- CloudFront에서 보낸 헤더를 활용합니다. 예를 들어 사용자 지정 콘텐츠를 제공하기 위해 사용자 장치 유형을 알아야 하는 경우 사용자-에이전트 헤더를 전달하여 해당 유형을 결정할 수 있습니다. 그러나 사용자-에이전트 문자열은 수천 가지 이상의 종류가 있으며 CloudFront의 origin 요청에 포함하면 각 변동에 대한 고유한 캐시 키가 생성이 되고 글로벌 캐시 적중률이 줄어들게 됩니다. 하지만 사용자-에이전트의 헤더를 전달하지 않고 대신 CloudFont에서 제공하는 사용자 지정 헤더(custom headers provided by CloudFront) 를 사용하여 장치 유형을 식별할 수 있습니다.
- 변동이 있을 수 있는 값을 전달해야 하는 경우 Lambda@Edge 을 사용하여 정규화(normalizing) 하고 고유한 변동 수를 줄이는 것이 좋습니다. Lambda@Edge는 Amazon CloudFront의 기능으로 사용자에게 보다 가깝게 코드를 실행하여 지연 시간을 줄이고 성능을 개선하며 CloudFront가 처리하는 요청 또는 응답을 프로그래밍 방식으로 수정할 수 있도록 지원합니다.
결론 및 다음 단계
우리는 CloudFront를 사용하여 웹사이트의 성능을 최적화하는 여러 가지 방법에 대하여 확인하였습니다. 애플리케이션 수준에서 페이지 로드 속도를 최적화 할 수 있는 더 많은 작업이 있습니다. 예를 들어 front end 최적화 기술에는 압축, 최소화, 이미지 최적화, JavaScript 차단 랜더 제거 등이 포함됩니다. 또 다른 옵션으로는 Lambda@Edge 를 사용하여 엣지 위치에서 분산된 애플리케이션 로직을 실행하여 사용자의 지연 시간을 줄이는 것입니다.
이러한 변경 사항이 웹 사이트 성능에 미치는 영향을 평가하려면 데이터 포인트를 갖는 것이 중요합니다. 실제 사용자가 모니터링을 수행하여 사용자가 경험한 성능을 측정(measure the performance) 하는 것이 제일 좋습니다. 추가적으로 Amazon Athena 또는 기타 HTTP 서버 로그 분석 도구를 사용하여 CloudFront 액세스 로그를 분석하여 웹 사이트 성능을 실시간으로 더 자세히 파악하고 필요에 따라 추가 사용자 지정을 할 수도 있습니다.
** 메가존 클라우드 TechBlog는 AWS BLOG 영문 게재 글 중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 게재하고 있습니다. 추가로 번역 및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS 페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.