AWS S3, CloudFront를 이용한 CDN 구축하기

503·2022년 9월 25일
18
post-custom-banner

안녕하세요, 503입니다.

이번 포스팅은 AWS CloudFront를 이용한 CDN을 구축하는 방법을 이야기해보려고 합니다. 이전의 AWS S3 이미지 처리 개선하기에서 이어지는 글입니다.

본격적으로 시작하기 전, 이슈를 다시 언급해보자면 다음과 같았습니다.

상품 리스트를 불러올 때, S3 버킷에 있는 큰 이미지를 그대로 가져오느라 로딩시간이 엄청 오래걸리는 문제점이 발생!

이러한 문제점을 해결하기 위해서 '캐싱(Cashing)' 개념을 떠올렸습니다. 캐싱은 캐시(Cache)라고 하는 좀 더 빠른 메모리 영역으로 데이터를 가져와서 접근하는 방식을 말합니다. 캐시는 컴퓨터의 성능을 향샹시키기 위해 사용되는 메모리인데요. 이처럼 매번 요청할 때마다 이미지를 새롭게 가져오지 않고, 캐시를 두어 이미 로딩했었던 이미지를 빠르게 가져오고 싶었습니다.

웹에서 이런 캐시의 기능을 갖고 있는 프록시 서버(Proxy Server)가 있었습니다. 클라이언트 대신에 자신을 통해서 인터넷 상의 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 서버를 말합니다.

프록시 서버를 둠으로써 이미지 로딩 속도를 단축하고 싶었고, 그래서 AWS에서 제공하는 CDN인 CloudFront를 이용해 프록시 서버를 구현해보기로 했습니다.

CDN이란?

CDN(콘텐츠 전송 네트워크, content delivery network) 간단히 말하면 지리적으로 분산된 여러 개의 서버로 사용자에게 웹 콘텐츠를 효율적으로 제공할 수 있는 서버의 분산 네트워크입니다.

좀 더 자세히 설명하자면 사용자의 물리적 위치와 가까운 엣지(Edge) 서버가 있고, 이는 파일 복사본을 임시로 저장하는 프로세스인 캐싱을 사용합니다. 그렇게 캐시된 웹 콘텐츠를 전송함으로써 전송 속도를 높이게 되고, 사용자는 콘텐츠가 로딩될 때까지 기다릴 필요가 없게 되는 것입니다.

AWS CloudFront?

공식문서를 보고 간단히 정리해봤습니다.

  • Amazon CloudFront는 .html, .css, .js 및 이미지 파일과 같은 정적 및 동적 웹 콘텐츠를 사용자에게 더 빨리 배포, 응답하기 위한 캐싱 기능을 지원하는 웹 CDN 서비스
  • CloudFront는 엣지 로케이션이라고 하는 데이터 센터의 전 세계 네트워크를 통해 콘텐츠를 제공. 사용자가 콘텐츠를 요청하면 지연 시간이 가장 낮은 엣지 로케이션으로 요청이 라우팅되므로 가능한 최고의 성능으로 콘텐츠가 제공
  • 캐싱을 지원하지 때문에 S3에 지정된 컨텐츠를 직접 접근하지 않아도 되므로 S3 비용이 감소하며 함께 적용해주는 것이 좋다.
  • Amazon S3, Amazon EC2 또는 Elastic Load Balancing과 같은 AWS Origin을 사용하는 경우, 이러한 서비스와 CloudFront 간에 전송된 데이터에 대해서는 요금이 청구되지 않음
  • 파일(객체)의 사본이 전 세계 엣지 로케이션에 캐시되므로 안정성과 가용성이 향상됨.

이미 AWS S3를 사용하고 있으니, CDN으로 AWS CloudFront를 사용하는 것이 나쁘지 않은 선택이라는 걸 알 수 있었습니다.

why CDN(CloudFront)?

CDN의 장점은 다음과 같습니다.

1. CloudFront가 콘텐츠를 Edge Location에 캐싱하기 때문에 S3 버킷 부하감소 및 콘텐츠 응답속도 향상

S3 origin 서버를 대한민국 리전으로 생성했다고 가정해봅시다.

지구 반대편에 있는 유저들은 매 요청마다 한국에 위치한 S3 서버까지 해저 케이블을 통해 무선통신을 해야 합니다. 물론 빛의 속도는 매우 빠르지만 물리적인 레이턴시가 필연적으로 발생하게 됩니다.

하지만 CDN을 사용하면 전 세계에 프록시 서버를 두어 요청에 대한 응답 값들을 캐싱할 수 있고 물리적인 거리를 좁힐 수 있습니다

2. 트래픽 집중, 병목현상, 데이터 손실 해결

트래픽이 갑자기 몰릴 때 Origin 서버에 요청이 몰리는 것이 아니라 CDN 프록시 서버로 분산이 되기 때문에 Origin 서버의 트래픽 병목을 미연에 방지할 수 있습니다.

3. 콘텐츠 보안 유지

CDN은 보안을 강화해 DDoS(Distributed Denial-of-Service) 공격과 같은 보안 문제와 악의적 공격자를 차단하는 기능을 웹사이트에 제공합니다.
CloudFront를 사용하면 지리적 제한, 서명된 URL, 서명된 쿠키 등 액세스 제한을 추가로 설정하여 기준이 서로 다른 콘텐츠에 대한 액세스 제한을 강화할 수 있습니다.

s3와 CloudFront 연결하기

S3 구현은 이미 진행되었다고 가정하고, CloudFront를 만들고 기존 s3 코드를 수정해보겠습니다.

CloudFront 서비스의 CloudFront 배포 생성을 통해 CloudFront를 배포합니다.
원본 도메인(Origin Domain Name)은 사용중인 S3를 연결해주었습니다.

정상적으로 배포된 CloudFront의 배포 도메인 이름을 통해 S3 버킷에 접근되는 것을 확인할 수 있습니다.

기존에 반환하던 s3 버킷 객체 url는 아래와 같았습니다.

https://{s3 버킷 이름}.s3.ap-northeast-2.amazonaws.com/image/{req.file.key}

그리고 이젠 CloudFront의 배포 도메인 이름을 통한 S3 버킷에 접근하도록 합니다.

https://{배포 도메인 이름}/{req.file.key};

라우터에서 클라이언트에게 반환해주던 이미지 주소 값도 s3버킷 주소가 아니라 cloudfront 도메인 주소로 변경해야 했습니다.

imageRouter 에서 imagePath값을 cloudfront 도메인 주소로 변경합니다.

imageRouter.js

import { Router } from 'express';
import { imageUpload } from '../middlewares';

const imageRouter = Router();

// /api/images/upload
imageRouter.post('/upload', imageUpload.single('image'), async (req, res, next) => {
  try {
    // req.file : 저장된 이미지의 메타데이터를 받는 객체
    console.log(req.file);

    // req.file.location : req.file 객체 속성 중 s3 버킷에 저장된 이미지 파일의 경로(이미지 주소) 가 전달되는 키
    // 이 경로를 db에 저장하고 서버가 이 이미지 주소를 응답하면 클라이언트에서 이 이미지를 핸들링 할 수 있게 됨.
    console.log(req.file.location);
    
	// CloudFront 배포 도메인 + 파일 이름
    const imgurl = 'https://{배포 도메인 이름}/' + req.file.key;

    // req.file에서 이미지 경로를 가져와 프론트에게 경로 반환
    res.status(201).json({
      status: 201,
      message: '이미지 저장 성공',
      imagePath: imgurl,
    });
  } catch (error) {
    next(error);
  }
});

export { imageRouter };

Cache Hit 확인

위와 같이 CDN 도메인으로 변경한 후 get 요청을 보내봅니다.


네트워크 탭에서 Response Header를 살펴보면 최초 요청은 아직 엣지 서버에 콘텐츠가 없기 때문에 Miss from cloudfront 즉, 캐시 미스가 뜹니다.

하지만 두 번째 요청부터는 x-cache: Hit from cloudfront 이 뜨며, 엣지서버에 캐시된 이미지를 가져오는 것을 확인할 수 있습니다.

이미지 하나의 서버 응답시간을 비교해보면 Cache Hit에 성공한 경우, 약 80% 정도의 응답속도가 단축된 것을 확인할 수 있었습니다.


🔗 참고

CDN

S3와 CloudFront 연결

profile
얼레벌레 개발자로 살아가기. 개발하면서 만났던 이슈를 기록합니다.
post-custom-banner

0개의 댓글