sol 개발 블로그 로고
Published on

AWS CloudFront

Authors
  • avatar
    Name
    Chan Sol OH
    Twitter

목차

CloudFront는 AWS에서 제공하는 Content Delivery Network (CDN) 서비스다. CloudFront는 여러 엣지 로케이션에서 웹사이트의 콘텐츠를 캐시 처리해 읽기 성능을 높인다. 전 세게에 캐시 서버가 있어서 전 세계의 사용자 경험이 향상된다. 또한 전 세계에 서버가 분산되어 있어 DDoS 공격을 해도 CloudFrontShieldAWS Web Application Firewall과 함께 방어할 수 있다. 전 세계에 캐싱하기 때문에 S3 버킷이 한국에 있어서 한번 캐싱되면 미국 사용자의 사용자 경험은 매우 향상된다.

Originis

CloudFront가 캐싱하는 데이터의 Origin은 여러 가지가 있다.

  1. S3 bucket은 CloudFront를 사용해 엣지에 파일을 분산하고 캐시처리하는 데 사용한다. S3에 오직 CloudFront만 접근하도록 하기 위해 **Origin Access Control(OAC)**를 사용할 수 있다.
  2. Custom Origin (HTTP) 백엔드도 사용할 수 있다. 이는 Application Load Balancer, EC2, S3 website가 될 수 있다. 이외에 어떤 HTTP 백엔드든 가능하다.

CloudFront와 S3 Cross Region Replication의 차이

  1. 글로벌 엣지 네트워크 사용 유무 : CloudFront는 글로벌 엣지 네트워크를 사용한다. 그리고 각 엣지 로케이션에 파일이 TTL이 하루 정도 캐싱된다. 즉 변하지 않는 스테틱 컨텐츠가 있다면 캐싱의 효과는 극대화된다.
  2. 복제 자동화 유무 : S3 Cross Origin Replication은 전 세계 모든 리전에 복제되지 않고, 어떤 리전에 복제본을 만들지 설정해야한다. 또한 파일이 실시간으로 복제되기 때문에 캐싱은 아니고, 읽기 전용이다. 따라서 변경이 자주 발생하는 동적 콘텐츠소수의 리전에 짧은 지연 시간 안에 서비스할 때 유용하다.

CloudFront의 캐싱 방법

cache는 각 Edge Location에 저장되기 때문에 Edge Location 만큼 생성된다. 또한, 각 캐시 객체는 캐시 키로 식별된다. 따라서 Client가 CloudFront로 요청을 보내면, edge location에 TTL을 기반으로 만료되지 않은 객체를 찾는다. 캐시가 없으면 Origin으로 요청을 전달한다.

Origin으로 가는 요청 수를 줄이기 위해선 CloudFront에 최대한 많은 데이터를 캐시 처리해야한다.

Cache Key는 뭐지?

캐시 키는 캐시에 있는 각 객체의 고유 식별자. 기본적으로 호스트 이름과 URI의 리소스 부분으로 구성된다. 예를 들어 호스트는 mywebsite.com이고, 리소스는 /content/stories/example.html이다. 캐시 키를 더욱 복잡하게 하면 사용자, 디바이스, 언어 등등 세부 사항에 따라 다르게 CloudFront 캐시 정책에서 캐시를 저장할 수 있다. 예를 들어 헤더, 쿠키, 쿼리 문자열 등등으로 캐시 키 생성 방법을 정의할 수 있다.

Cache Policy

  • HTTP : None(캐시키에 포함 X), Whitelist(적힌 것만 캐싱)

  • Cookies : None, Whitelist, Include-All-Except(적힌 것 제외하고 전부 캐싱), All(전부 캐싱)

  • Query Strings : None, Whitelist, Include-All-Except, All

  • TTL 제어 : Cache-Control 헤더와 Expires 헤더를 이용해서 0초에서 1년 사이 기간 동안 TTL을 설정할 수 있다.

위 모든 Cache 정책의 내용은 Origin 요청에 자동으로 포함되어 전달된다. 다시 말하면, 클라이언트가 보낸 요청의 HTTP 내용(헤더, 쿠키, 쿼리 스트링, ...)과 Cache Policy를 비교해서 요청에 대한 Origin의 응답을 저장하게 된다.

Origin Request Policy

Origin 요청에는 포함하지만 캐시 키에는 포함하지 않기 위해 Origin Request Policy를 설정할 수 있다.

  • HTTP 헤더 : None, Whitelist, All
  • Cookies : None, Whitelist, All
  • Query Strings : None, Whitelist, All

예를 들어 API 키나 보안 헤더처럼 저장되면 안되는 객체를 설정할 수 있다. 자체 정책이나 사전 정의된 관리형 정책을 이용할 수 있다.

Cache Policy vs Origin Request Policy

  1. 사용자가 쿼리 스트링, 쿠키, 헤더 등을 사용해 요청 발생
  2. Cache Policy 기반으로 엣지 로케이션에 캐시 저장
  3. Origin이 응답하기 위한 자격 증명 같은 것을 Origin Request Policy에 포함시켜 캐싱되지않고, Origin에 전달할 수 있다.

Cache 무효화

CloudFront는 요청에 응답하는 backend Origin이 있다. 만약 backend Origin을 업데이트할 경우 CloudFront Edge Location은 이를 알 수 없다. 단지, TTL이 만료되고 나면 다시 응답 받아서 저장할 뿐이다. 이를 위해서 전체적 또는 부분적인 캐시 리프레시를 적용해 캐시에 있는 모든 TTL을 제거할 수 있다. 설정 방법은 ()처럼 모든 파일이나 (/images/)처럼 접두사를 정해 특정 파일 경로를 설정할 수 있다.

Cache Behaviors

Cache Behaviors를 상요하면 CloudFront 요청에 응답하는 backend Origin을 요청 경로에 따라 여러개 설정 수 있다. 예를 들어 (/api/)은 로드 밸런서 origin으로 보내고, (/)과 같은 기본 캐시 동작은 S3 버킷 같은 오리진으로 보낼 수 있다.

실제로는 사용자가 (/login)으로 EC2에서 로그인을 수행한 후 EC2는 서명된 CloudFront 쿠키 응답한다. 또한 사용자는 (/)으로 S3 버킷에 객체를 접근할 수 있다. 이때, Cache Behaviors에 서명된 CloudFront 쿠키를 가져야만 요청을 받아들이도록 설정하면, 쿠키가 없는 사용자는 (/)에 요청할 수 없다. 단지 (/login) 페이지로 리다이렉트될 뿐이다.

다른 예로는 정적 파일에 접근할 때는 cache 정책을 설정하지 않고, 단지 리소스가 일치하면 캐싱하도록 해서 캐시 적중률을 극대화할 수 있다. 또한 동적 파일 (Load Balancer, EC2)에 요청할 때는 세부적으로 정책을 설정해서 정확한 헤더와 쿠키를 기준으로 캐싱 처리할 수 있다.

ALB를 Origin으로

CloudFront는 ALB를 Origin으로 해서 데이터를 캐싱할 수 있다. 아래 그림처럼 Security Group 설정으로 Private subnet에 있는 EC2와 Public subnet에 있는 ALB를 연결하고 ALB는 CloudFront의 Edge Location과 연결해서 EC2의 응답을 캐싱할 수 있다.

cloudfront와 alb 연결

위처럼 서버에 응답을 잠시동안 캐싱하는 프록시 서버로 CloudFront를 사용할 수 있고, 이는 EC2의 부하를 줄일 수 있는 역할을 한다.

CloudFront 지리적 제한

특정 국가에만 데이터를 보여주거나 특정 국가에 데이터를 차단하기 위해서 허용 목록과 차단 목록에 여러 국가들을 작성할 수 있다. 사용자의 IP와 사용자의 국가를 매치하기 위해 서드 파티 Geo-IP database를 이용한다. 예를 들어 저작권 법에 따라 컨텐츠 제공이 제한되는 경우 사용할 수 있다.

CloudFront Signed URL / Signed Cookies

CloudFront 배포를 비공개로 설정해서 전 세계에서 프리미엄 사용자만 유로 공유 콘텐츠를 접근할 수 있게 하거나, CloudFront 배포에서 어떤 사용자가 어떤 콘텐츠에 액세스 권한이 있는지 확인하기 위해 Signed URL, Sigined Cookies를 사용한다.

Sigined URLSigined Cookie는 정책을 통해 만료 시점을 지정해야한다. 또한 데이터에 접근할 수 있는 IP 범위도 설정해야한다. 사용자의 대상 IP를 알면 사용할 수 있을 것이다. 당연히 데이터 접근 허가 서명을 위한 AWS 계정도 필요하다. 그리고 Sigined URL 1개는 공유 파일 1개를 뜻한다. 공유할 파일이 100개라면 URL도 100개다. 다만, Signed Cookie 1개는 공유 파일 여러개를 뜻한다.

서명의 만료 기한?

  • Shared Content : 영화나 음악 같은 컨텐츠는 몇분 정도로 짧게 설정
  • Private Content : 사용자가 오랫동안 액세스할 개인 콘텐츠는 몇년 단위로 설정

CloudFront Sigined URL vs S3 Pre-Signed URL

  • CloudFront Sigined URL : 오리진과 상관 없이 경로의 액세스를 허용한다. 즉 오리진이 S3이든 어떤 http backend든 상관 없이 작동한다. 또한 계정 전체에 적용되는 키기 때문에 root 계정만 관리할 수 있고, IP, 경로, 날짜, 만료일을 기준으로 필터링할 수 있다. 또한 CloudFront의 모든 캐시 기능을 이용할 수 있는 만능키이다.
  • S3 Pre-Signed URL : 서명한 계정의 권한으로 요청을 발행하고, 만료일이 존재한다. 그리고 S3 버킷에 바로 접근할 수 있다.

사용자에게 CloudFront 배포에 대한 액세스를 부여하고 이 배포를 S3 앞에 연결하는 경우 CloudFront Signed URL을 사용하고, 버킷 정책에서 OAC를 적용해 S3 버킷 액세스를 제한할 수 있다. 반면 사용자가 S3에 바로 접근하려면 S3 Pre-Signed URL을 사용해야한다.

CloudFront 고급 개념

CloudFront 가격 정책

CloudFront의 Edeg Location은 전 세계에 퍼져있기 때문에 edge location에 따른 데이터 전송 비용도 아래 그림처럼 대륙과 지리적 위치에 따라 다르다.

cloudfront 비용

왼쪽에서 오른쪽으로 넘어갈 수록 가격이 다르기 때문에 원하는 edge location만 설정해서 가격을 최적화할 수 있다. 이를 위해 나온 것이 Price Class이다.

  1. Price Class All : 모든 지역, 최적의 성능, 하지만 비싼 비용
  2. Price Class 200 : 가장 비싼 지역을 제외한 대부분의 지역 제공
  3. Price Class 100 : 가장 저렴한 지역만 제공
cloudfront 비용

100은 북아메리카와 유럽만 포함하고 200은 중동과 동북아시아만 포함한다. All은 당연히 전부 다 포함한다.

CloudFront Multiple Origin

content type이나 경로에 따라 다른 여러 backend Origin로 리다이렉트할 수 있다. 예를 들어 이지지용 경로 (/images/)나 api용 경로(/api/)가 있다면, 경로에 따라 다른 Origin을 설정할 수 있다.

또한 Origin Groups는 고가용성을 증가시키고, 한 오리진에서 장애가 발생한 경우 장애 조치가 가능하게 한다. 따라서 주 오리진보조 오리진으로 구성된다. 만약 CloudFront가 주 오리진으로 요청을 보내고, 에러가 발생하면 보조 오리진으로 다시 요청을 보내서 응답을 받는다. 또한 S3 버킷은 region에 제한이 있기 때문에 주 버킷의 region이 재해가 발생할 경우 CloudFront가 보조 region에 버킷에게 객체를 요청하게된다. 이를 위해선 Cross-Region Replication이 필요하다.

Field Level Encryption

애플리케이션 스택을 통해 유저의 민감 정보를 보호하는 기능이다. HTTPS를 이용하는 통신 암호화에 추가적인 보안을 더한다. 사용자가 민감한 정보를 요청할 경우 Edge Location이 암호화하고 캐인 키에 대한 권한을 가진 사용자만이 이 정보를 해독할 수 있는 개념이다.

암호화하길 원하는 POST 요청 필드를 최대 10개 지정할 수 있다. (ex, 신용카드 번호) 그리고 이 필드를 해독할 공용키도 함께 저장된다.

정리하면 유저가 제공한 POST 요청 속 특정 필드를 Edge Location이 찾고, 이를 공용키로 암호화한다. Edge Location이 암호화한 데이터가 WAS로 전달되면 WAS에 저장된 private 키로 데이터를 복호화해서 사용한다. 따라서 HTTPS로 암호화하고 또 특정 필드에 대해 다시 암호화하는 것이다.