Amazon S3, CloudFront로 정적 이미지 제공하기

Lechros·2024년 5월 15일

기존에 CloudFlare R2 서비스를 사용해서 이미지를 제공하고 있었는데, 로드 속도가 최소 300ms ~ 600ms로 엄청 느려서 S3로 갈아탔다.
S3 버킷을 만들고, CloudFront와 도메인을 연결하고, HTTPS/CORS를 설정했다.

S3 버킷 만들기

  1. Amazon S3 콘솔에서 버킷 만들기를 선택한다.
  2. image-lechros로 이름을 지었다. 이름이 다른 버킷과 안겹치게 잘 지어보자. (버킷 이름 지정 규칙)
  3. 나머지는 그대로 냅두고 만들면 된다. 객체 소유권 ACL 비활성화, 모든 퍼블릭 액세스 차단이 기본으로 설정되어 있다.
  4. 여기에 올리는 이미지는 날라가도 상관 없어서 버전 관리도 비활성화했다.

CloudFront 연결하기

  1. CloudFront 콘솔에서 배포 생성을 선택한다.
  2. Origin domain에서 {버킷명}.s3.ap-northeast-2.amazonaws.com을 선택한다.
  3. 원본 액세스 - 원본 액세스 제어 설정(권장)을 선택하고 아래에 Create new OAC에서 생성한 걸 선택하면 된다.

  4. 기본 캐시 동작 - 뷰어 프로토콜 정책을 Redirect HTTP to HTTPS로 변경하고 나머지는 기본값으로 진행했다.
    • CORS를 설정하려면 아래의 응답 헤더 정책을 설정하면 된다. 이 글에서는 나중으로 미루겠다.
    • 도메인을 연결하려면 또 Custom SSL certificate를 설정하면 된다. 이것도 나중으로 미루겠다.
    • 서버가 좋아질 거 같은 여러 보호 옵션을 제공해주는데 대부분 추가 요금이 들어서 비활성화했다.

  1. 생성 완료하면 S3 버킷 정책을 업데이트하라고 알려준다. 시키는 대로 복사하고 링크를 누른다.
  2. 버킷 - 권한 탭에서 버킷 정책 - 편집을 누르고 그냥 붙여넣고 저장하면 된다. AWS가 정말 친절해진 것 같다.

CORS 설정하기

img 태그는 따로 cross-origin을 설정하지 않으면 CORS 헤더가 없어도 잘 작동하므로 필요 없다면 이 부분은 넘어가도 된다. 나는 XHR로 이미지를 요청하는 경우가 있어서 설정했다. (처음에 설정 안했다가 누가 사이트에 이미지 안보이는 오류가 있다고 제보가 와서 급하게 추가)

  1. CloudFront 배포 - 동작 탭에서 생성된 동작을 선택하고 편집을 누른다.
  2. 캐시 키 및 원본 요청 아래의 응답 헤더 정책을 찾아가고, 아래 Create ...를 누른다.
  3. 응답 헤더 정책 생성 페이지로 이동해서 원하는 이름으로 짓는다.
  4. 아래 교차 오리진 리소스 공유 구성을 누르고 원하는 항목을 수정하면 된다. 여기서는 Origin만 추가하고 나머지는 유지했다. (얼마 전에 할 때는 JSON 편집기로 등록했던 것 같은데...)
  5. 생성하고 이전 페이지에서 선택하고 저장한다.

도메인 연결하기

Route53을 쓰면 아마존이 또 친절하게 알려줄 것 같은데, 아쉽게도 CloudFlare DNS를 사용해서 직접 설정했다. 먼저 도메인에 사용할 SSL 인증서를 발급받아야 한다.

  1. CloudFront 배포 - 일반 탭 - 설정 - 편집에 접속한다.
  2. 대체 도메인 이름을 입력하고 인증서를 요청한다.
  3. 사용할 도메인 주소를 입력한다. 한 인증서로 돌려막기하고 싶다면 여러 도메인을 추가하거나 와일드카드도 사용 가능하다.
  4. 검증 요청 도메인을 보고 자신의 DNS 설정 페이지에 추가한다.


    (몇분 후)

    (이제 DNS에서 방금 추가한 내용을 지워도 된다.)
  5. 인증서를 선택하고 저장한다.
  6. CloudFront 배포 - 일반 탭에서 배포 도메인 이름을 복사해서 CNAME 레코드의 Target으로 추가하면 된다.

이미지 업로드하기

다시 버킷으로 돌아와서 아무 이미지나 추가한다. 나는 linesticker1를 추가했다.

잘 접속된다. https으로 자동으로 리디렉션도 된다.
파일이 몇 개 없다면 콘솔로 넣어도 되지만 사이트에 필요한 이미지가 대충 55000개라서 AWS CLI를 사용해서 업로드했다.
| https://aws.amazon.com/ko/cli/

aws s3 sync myfolder s3://image-lechros/myfolder

업로드하면서 캐시 헤더를 설정할 수도 있다.

aws s3 sync myfolder s3://image-lechros/myfolder --cache-control max-age=86400,s-maxage=604800

max-age=86400: 브라우저 캐시에 86400초(1일) 간 저장
s-maxage=604800: CloudFront 캐시에 604800초(7일) 간 저장

TMI

  • max-age로 설정한 기간만큼 브라우저 캐시에 저장된다. 이걸 없애려면 기다리거나, 브라우저 캐시를 날려달라고 사용자한테 부탁하거나 (!), 요청 파일명을 바꿔야 한다. 그러므로 같은 경로의 내용이 변경될 가능성이 있는 경우 너무 길게 가져가지 말자.
  • s-maxage는 CloudFront가 사용하는 캐싱 기간이다. CDN한테 캐시를 날려달라고 부탁하는게 사용자한테 부탁하는 것보다 쉽기 때문에 이건 좀 더 길게 가져가도 된다.
  • S3는 Etag로 브라우저의 마지막 요청 시점에서 파일이 변경되지 않았다면 304 Not Modified를 반환할 수 있다. 왕복 딜레이는 있지만 파일 크기가 큰 경우 데이터를 아낄 수 있다.
  • CloudFront 캐시가 적중되면 응답 헤더에 X-Cache: Hit from cloudfront가, 미스되면 X-Cache: Miss from cloudfront가 포함된다. 아주 작은 S3 파일 기준 Hit은 약 10ms, Miss는 약 100ms의 요청 시간을 기록했다.

참고

0개의 댓글