Hyesung Oh

AWS Cloudfront를 통해 알아보는 CDN(Contents Delivery Network) 본문

Web

AWS Cloudfront를 통해 알아보는 CDN(Contents Delivery Network)

혜성 Hyesung 2022. 6. 10. 18:26
반응형

우리 회사가 CDN을 통해 글로벌 웹 컨텐츠를 제공하고 있다는 사실을 어렴풋이만 알고있었고, 이번에 호기심에 짬내서 살펴보며 공부한 내용을 정리해보았다.


 

CDN

https://www.highcharts.com/blog/news/50-codehighchartscom-moves-to-cdn/

CDN(콘텐츠 전송 네트워크)은 지리적으로 분산된 여러 개의 서버이다.
당연하게도 웹 콘텐츠를 사용자와 가까운 곳에서 전송함으로써 전송 속도를 높일 수 있기에 사용하는 모든 웹서비스 회사에서 사용하는 서비스이다.

전 세계 데이터센터는 파일 복사본을 임시로 저장하는 프로세스인 캐싱을 사용한다. 따라서 사용자는 가까운 서버를 통해 웹 활성화 디바이스 또는 브라우저에서 인터넷 콘텐츠에 빠르게 접속할 수 있다.

개인적으로 CDN을 ATM에 비유하는게 제일 맘에 든다. 여러 곳에 ATM을 설치해 놓으면 사용자가 중앙은행에 가지 않고도 ATM 기기에 보관된(지리적으로 분산된 서버에 캐싱된) 현금(컨텐츠)을 인출(응답받아)하여 사용할 수 있는 것 처럼 말이다.

또한 CDN은 보안을 강화해 DDoS(Distributed Denial-of-Service) 공격과 같은 보안 문제와 악의적 공격자를 차단하는 기능을 웹사이트에 제공할 수도 있다고 한다. 아마 회사마다 SRE, 시스템 관리 팀에서 관리하는 부분이고 현재 회사의 경우 SRE팀에서 담당하고 있다.

AWS Cloudfront

각 클라우드 벤더사 마다 제공하는 CDN서비스가 있고, 그 중에 AWS가 제공하는 CDN 서비스이다. 참고

Amazon CloudFront는 .html, .css, .js 및 이미지 파일과 같은 정적 및 동적 웹 콘텐츠를 사용자에게 더 빨리 배포하도록 지원하는 웹 서비스입니다. CloudFront는 엣지 로케이션이라고 하는 데이터 센터의 전 세계 네트워크를 통해 콘텐츠를 제공합니다. CloudFront를 통해 서비스하는 콘텐츠를 사용자가 요청하면 지연 시간이 가장 낮은 엣지 로케이션으로 요청이 라우팅되므로 가능한 최고의 성능으로 콘텐츠가 제공됩니다.

우선 S3 버킷에 파일을 생성하고 파일 오리진으로서 서빙을 할 수 있다. (S3를 이용한 정적 웹사이트 서빙을 참고)
그리고 Cloudfront가 유저의 요청을 처리하는 과정을 순서대로 나타내면 아래와 같다.

https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/HowCloudFrontWorks.html

  1. 사용자가 웹 사이트에 액세스하고 이미지 파일 및 HTML 파일 같은 객체에 대한 요청을 보냄.
  2. DNS가 요청을 최적으로 서비스할 수 있는 CloudFront POP(엣지 로케이션)로 요청을 라우팅. 해당 위치는 일반적으로 지연 시간과 관련해 가장 가까운 CloudFront POP임.
  3. CloudFront는 해당 캐시에 요청된 객체가 있는지 확인하고, 캐시에 있으면 CloudFront는 객체를 사용자에게 반환. 객체가 캐시에 없으면 CloudFront가 다음을 수행
    1. CloudFront는 배포의 사양과 요청을 비교하고 요청을 해당하는 객체로 사용자의 원본 서버(예: Amazon S3 버킷 또는 HTTP 서버)에 전달.
    2. 원본 서버는 객체를 다시 엣지 로케이션으로 보냄.
    3. 오리진에서 첫 번째 바이트가 도착하면 CloudFront가 객체를 사용자에게 전달하기 시작. CloudFront는 다음에 다른 사용자가 객체를 요청할 때 캐시에 해당 객체를 추가

파일 원본을 업데이트 하는 방법과 각 방식에 따른 캐시 동작 결과에 대한 자세한 내용은 여기를 참고.

Cloudfront에서는 아래와 같은 항목들을 설정할 수 있으며 세부 사항들이며 자세한 설정 및 배포 방법에 대해서는 여기를 참고.

  • 콘텐츠 오리진 - CloudFront가 배포할 파일을 가져오는 Amazon S3 버킷, AWS Elemental MediaPackage 채널, AWS Elemental MediaStore 컨테이너, Elastic Load Balancing 로드 밸런서 또는 HTTP 서버. 배포당 최대 25개 오리진의 조합을 지정할 수 있습니다.
  • 액세스 - 파일을 모든 사람이 사용할 수 있도록 할지 아니면 일부 사용자로만 액세스를 제한할지 여부.
  • 보안 - CloudFront에서 사용자가 HTTPS를 사용하여 콘텐츠에 액세스하도록 지정할지 여부.
  • 캐시 키 - 캐시 키에 포함할 값(있는 경우)입니다. 캐시 키는 지정된 배포에 대한 캐시의 각 파일을 고유하게 식별합니다.
  • 오리진 요청 설정 - CloudFront가 오리진에 전송하는 요청에 HTTP 헤더, 쿠키 또는 쿼리 문자열을 포함할지 여부입니다.
  • 지리적 제한 - CloudFront에서 특정 국가의 사용자가 콘텐츠에 액세스하는 것을 차단할지 여부.
  • 로그 - CloudFront가 최종 사용자 활동을 표시하는 표준 로그 또는 실시간 로그를 생성할지 여부.

 

Customizing with edge function

마지막으로 자체 코드를 작성하여 CloudFront 배포에서 HTTP 요청 및 응답을 처리하는 방법을 사용자 지정할 수있도록 지원하는 Customizing with edge function을 끝으로 글을 마치겠다. 자세한 내용은 여기를 참고

아래와 같은 동작을 코드레벨에서 조작할 수 있다. python 과 node.js로 간단하게 작성가능하다.

  • Cache key normalization – You can transform HTTP request attributes (headers, query strings, cookies, even the URL path) to create an optimal cache key, which can improve your cache hit ratio.
  • Header manipulation – You can insert, modify, or delete HTTP headers in the request or response. For example, you can add a True-Client-IP header to every request.
  • URL redirects or rewrites – You can redirect viewers to other pages based on information in the request, or rewrite all requests from one path to another.
  • Request authorization – You can validate hashed authorization tokens, such as JSON web tokens (JWT), by inspecting authorization headers or other request metadata.

Customizing with cloudfront function과 Customizing with Lambda@edge 두 가지 기능이 지원되며, Customizing with Lambda@edge 활용 사례를 코드 레벨에서 가볍게 소개하려한다.

export const handler = (event, context, callback) => {
  const { request } = event.Records[0].cf
  let path = request.uri
  let isRedirectedRequest = false
  if (path.startsWith(`${cfDistributionConfig.redirectDiscriminator}/`)) {
    path = path.replace(cfDistributionConfig.redirectDiscriminator, '')
    isRedirectedRequest = true
  }

  try {
    const host = request.headers.host[0].value
    const query = querystring.parse(request.querystring)
    const storage = getContentStorage(host, request.uri)
    request.uri = storage.manipulateUrl(path, query, request.headers, isRedirectedRequest)
  } catch (e) {
    if (e instanceof NotFoundMatchedContentStorage) {
      request.uri = path
    ~
    } else {
      console.log('origin request handler - an error occurred: ', e)
    }
  }

  callback(null, request)
}

요청을 처리하는 Lambda handler function이다. 요청의 uri path를 확인하고 특정 경우에 해당하면 redirection해주고 있다. 

이상으로 글을 마치겠습니다. 감사합니다.

 

반응형

'Web' 카테고리의 다른 글

JWT, Cookie&SessinId를 활용한 Auth, 인증(Authentication)  (0) 2022.06.09
REST API를 이용한 Web APIs design  (1) 2022.06.04
Comments