이전 이미지 관련 최적화 포스팅이다.
S3 최적화 - WebP 변환 및 이미지 압축 적용기
이번에 새로운 서비스에 합류하게 됐는데,(문제 발생 당시) DAU 50명일 때 갑자기 월 S3 요금만 50만원이 발생했다는 소식을 들었다.-> 현재는 라즈베리파이로 이동해 있음. 명확한 해결은 없는 상
hyunco.tistory.com
S3 최적화 - 이미지 리사이징
이전 포스팅https://hyunco.tistory.com/78 현재는 라즈베리파이로 이동해 있음. 명확한 해결은 없는 상" data-og-host="hyunco.tistory.com" data-og-source-url="https://hyunco.tistory.com/78" data-og-url="https://hyunco.tistory.com/78"
hyunco.tistory.com
돌아보면 가벼운 내용들이지만, 처음 해보는 과정을 그대로 담았기에 글은 짧지 않다...!
마지막으로 CloudFront를 적용하는 과정과 개선 결과를 기록하려고 한다.
우선 기본 s3만을 사용했을 때와 CloudFront를 사용할 때의 비용 계산이다.
- 우리 서비스는 글 하나당 이미지는 최대 10MB 용량 하나만 등록 가능하다.
- 서비스 내 실제 하루 평균 편지 작성 수 : 150개
1. S3 비용 계산
S3의 경우, GET 요청과 데이터 전송에 대한 비용이 발생한다.
가정
- 이미지 용량 : 10MB
- 일일 조회 횟수 : 대략 1500번
- 한 달 조회 횟수 : 1500번 * 30일 = 45,000번
- 월간 데이터 전송량 : 10MB * 45,000 = 450,000MB = 450GB
S3의 GET 요청 비용 :
- AWS S3의 GET 요청 비용은 1000건당 약 $0.0004이다.
- 한 달에 45,000번의 조회가 있으므로 45,000 / 1000 = 45개의 1000번 묶음이 된다.
- 그러므로 GET 요청 비용은: 45 × 0.0004 = 대략 0.016USD
S3의 데이터 전송 비용 :
- AWS S3에서 데이터 전송은 1GB당 약 $0.126이다.
- 월간 데이터 전송량은 450GB 이므로, 450 × 0.126 = 56.7USD
따라서, S3에서 한 달 동안 발생하는 비용은 0.016USD (GET 요청 비용) + 56.7USD (데이터 전송 비용)로, 56.716USD이다.
Get 요청과 데이터 전송 요청의 차이
1. GET 요청 비용
- GET 요청은 사용자가 S3에서 객체를 요청할 때 발생하는 비용이다.
- 예를 들어, 사용자가 이미지를 요청하면 S3는 그 이미지를 제공하기 위해 GET 요청을 처리해야 하고, 이 요청에 대해 일정한 비용이 부과된다.
- 비용은 요청 횟수에 따라 발생하고, 1,000건당 일정 비용이 책정된다.
2. 데이터 전송 비용
- 데이터 전송 비용은 실제로 S3에서 사용자의 요청에 따라 데이터를 전송할 때 발생하는 비용이다.
- 예를 들어, 사용자가 10MB 크기의 이미지를 요청하면, 그 이미지가 S3에서 사용자에게 전송될 때, 데이터 전송에 대한 비용이 발생한다.
- 데이터 전송 비용은 전송된 데이터의 용량(GB 단위)에 따라 부과된다.
차이점 정리
- GET 요청 비용은 객체를 요청하는 횟수에 대한 비용이고, 데이터 전송 비용은 요청된 객체의 실제 데이터 전송에 대한 비용이다.
- S3에서 데이터를 요청하는 것만으로는 GET 요청 비용이 발생하고, 실제로 데이터가 S3에서 클라이언트로 전송될 때는 데이터 전송 비용이 발생한다.
2. CloudFront 사용 시
CloudFront를 사용하면 S3의 GET 요청 비용은 발생하지 않고, CloudFront의 데이터 전송 비용만 발생하게 된다.
CloudFront가 S3의 데이터를 캐시하여 전송하므로, S3에서의 GET 요청을 줄이고, 데이터 전송에 대해서만 비용이 발생한다.
CloudFront의 데이터 전송 비용 :
- CloudFront에서 데이터 전송 비용은 첫 1TB까지는 무료라서 아직은 비용이 발생하지 않을 확률이 높지만, 만약 1TB가 겨우 넘었다고 가정하고 계산해 보면 1GB당 약 $0.12이다.
- 월간 데이터 전송량은 여전히 450GB이므로, 450 × 0.12 = 54USD
CloudFront의 요청 비용:
- CloudFront에서 HTTP/HTTPS 요청 비용은 10,000건당 약 $0.01이다.
- 한 달에 45,000번의 요청이므로, 45,000 ÷ 10,000 = 4.5 , 4.5 × 0.01 = 0.045USD
따라서 CloudFront의 비용은 54USD (데이터 전송 비용) + 0.045USD (요청 비용)로, 54.045USD 이다.
CDN이란?
CDN은 Content Delivery Network의 약자다.
- Content: 웹사이트, 이미지, 비디오, 스타일시트, 자바스크립트 파일 등 웹 콘텐츠를 의미.
- Delivery: 이 콘텐츠를 사용자가 요청할 때 빠르게 전달하는 과정.
- Network: 전 세계에 분포된 서버들로 이루어진 네트워크.
CDN의 역할
CDN은 전 세계에 분산된 서버를 통해 웹 콘텐츠를 사용자에게 빠르게 전달하는 전송 네트워크다. 주로 웹사이트의 속도를 향상시키고, 서버의 부하를 분산시키기 위해 사용된다.
- 캐싱: CDN 서버는 자주 요청되는 콘텐츠를 캐시하여 저장하고, 사용자가 요청할 때 이 캐시된 콘텐츠를 가장 가까운 서버에서 제공함으로써 지연 시간을 줄이고 빠른 응답을 제공한다.
- 전 세계적인 분산: CDN 서버는 여러 지역에 위치하여, 사용자와 가장 가까운 서버가 콘텐츠를 제공하도록 하여, 웹사이트 로딩 속도를 크게 향상시킨다.
CDN을 사용하면 웹 사이트의 성능이 크게 향상되고, 특히 트래픽이 많은 콘텐츠(예: 이미지, 비디오 등)를 효율적으로 전송할 수 있다.
3. S3만 사용한 경우 vs CloudFront 사용한 경우 비교
- S3만 사용한 경우: 약 56.716 USD
- CloudFront 사용한 경우: 약 54.045 USD
CloudFront를 사용하면 S3의 GET 요청 비용을 절감하고, 데이터 전송 비용도 조금 더 저렴하게 발생하지만, 전체적으로는 큰 차이는 없을 수 있다.
그러나 위 계산 결과는 CloudFront의 무료 요금을 무시하고 계산한 결과이며,
실제 CloudFront를 사용하면 캐싱 효과로 인해 S3에서의 조회가 줄어들 수 있어, 더 많은 데이터 조회가 이루어질 경우 비용 절감 효과가 커질 수 있다.
CloudFront의 작동 방식
- 캐시된 데이터 제공:
CloudFront는 엣지 로케이션이라고 하는 전 세계의 여러 서버에 데이터를 캐시하여 저장한다. 사용자가 요청을 보내면, CloudFront는 그 요청을 가장 가까운 엣지 서버에서 처리하고, 그 서버에 이미지가 캐시되어 있으면 S3에 직접 요청하지 않고 이미지를 바로 제공한다. - 캐시되지 않은 경우:
만약 캐시된 이미지가 없으면, CloudFront는 요청을 원본 서버(S3)로 전달하고, S3에서 이미지를 받아와서 CloudFront의 엣지 서버에 캐시한 후 사용자가 요청한 이미지를 전달한다. 이 과정은 캐시 만료 시간(TTL, Time-to-Live) 동안 한 번만 발생하고, 이후에는 캐시된 데이터를 제공. - TTL 설정:
CloudFront는 캐시된 콘텐츠가 얼마나 오래 유지될지를 결정하는 TTL을 설정할 수 있다. TTL이 만료되면 CloudFront는 다시 S3에서 최신 콘텐츠를 가져와서 캐시를 갱신한다. 이 과정이 반복되면서 서버의 부하를 줄이고, 사용자의 요청에 더 빠르게 응답할 수 있다.
이렇게 CloudFront를 적용하면 얻게 되는 이점을 정리해 봤고,
아래는 어떻게 적용하면 되는지 (매우 간단하지만) 이미지와 함께 기록하려고 한다.
우선 AWS CloudFront로 들어가서, 배포 버튼을 눌러 배포를 생성한다.
Origin domain
CloudFront를 적용하고자 하는 원본을 선택한다. S3, ELB, API gateway 등을 선택할 수 있는데, 이번에 적용할 s3 버킷을 선택해준다.
원본 액세스
CloudFront를 연결하는 원본에 어떤 방식으로 접근이 가능하게 할 것인지 설정하는 부분이다.
공개로 설정하면 S3 버킷 객체에 대한 접근이 가능하기 떄문에 우리가 cdn을 적용하는 의미가 없으니 원본 액세스 제어 설정으로 하겠다.
Legacy access identities(OAI)의 확장 버전이 OAC이다.
위와 같이 OAC를 생성해 준다.
그 이후의 항목들도 위와 같이 설정한다.
대체 도메인을 사용하고자 한다면 SSL 인증서를 설정해주어야 한다.
배포를 생성했다면 상단에 정책 복사 버튼이 나온다.
정책을 복사한 후, 아까 설정한 원본(S3 버킷)으로 이동한다.
그 후, S3 버킷의 버킷 정책 편집 버튼을 눌러서, 위에서 복사했던 내용을 붙여넣기 한다.
기존에 버킷 정책이 존재했다면 복사한 정책 내용 중 Statement 내의 중괄호 부분만 복사해서 기존 버킷 정책 Statement의 중괄호 뒤에 ,와 함께 붙여넣기 하면 된다.
그리고 나서 버킷의 권한에 이동하여 퍼블릭 액세스 차단 설정을 해줘야 한다.
CloudFront 배포를 생성하면서 원본 엑세스 제어 설정(OAC)을 했기 때문에, S3 버킷에서 퍼블릭 엑세스 차단을 설정해줘야 한다.
모든 퍼블릭 액세스 차단을 선택하여 외부에서 S3에 접근하지 못하게 설정한다.
만약 POST, PATCH와 같이 버킷 객체에 대한 변경이 제대로 동작하지 않는다면, 새 ACL(엑세스 제어 목록)을 통해 부여된 버킷 및 객체에 대한 퍼블릭 엑세스 차단을 해제하면 된다.
동작 확인
CloudFront의 배포 도메인을 복사한 후, S3 버킷 내에 있는 객체의 키값을 이어 붙인다.
예시 -> https://{CloudFront 도메인 명}.cloudfront.net/profile/33b32-be9-41409-a829-ba94c04587005.jpg
이렇게 만들어진 URl을 접속해서 네트워크 탭을 통해 확인해 보면,
첫 번째 조회했을 때는 위처럼 X-Cache의 값이 Miss from cloudfront인 것을 확인할 수 있다.
응답까지의 시간은 50.6ms가 소요됐다.
여기서 새로고침을 통해 이미지를 다시 요청한다면 CloudFront를 통해 캐싱된 이미지가 응답될 것이고, 그 결과는 아래와 같다.
X-Cache 값을 보면 Hit from cloudfront를 확인할 수 있고, cache hit 되어 캐싱된 이미지가 전달된 것을 이야기 한다.
응답 시간은 위와 같이 8.29ms가 소요된 것을 볼 수 있으며, 이는 약 83.62% 감소된 것을 의미한다!
한번 더 테스트한 결과이다.
마찬가지로 캐싱이 됐고, 약 88.26% 감소됐다.
평균 약 85.94%
이렇게 이미지 최적화 과정은 여기서 끝이 났다.
이후에 더 큰 서비스에서는 어떻게 다루는 지도 궁금하지만, 내가 경험할 수 있는 상황에서는 아직까지는 최선인 것 같다.
비용 최적화는 항상 보람차서 진행하는 내내 지치지 않았던 것 같다.
새롭거나 더 좋은 방법을 알아낸다면, 또 기록하겠다.
참고 자료
'대충 넘어가지 않는 습관을 위한 기록' 카테고리의 다른 글
운영 서버 스웨거 사용 제한 (0) | 2025.02.12 |
---|---|
AWS 해킹 기록.. (0) | 2025.02.12 |
개발·운영 환경 분리 적용기 - GitHub Actions를 활용한 배포 자동화 (개선 과정 포함) (1) | 2025.02.06 |
이미지 업로드 최적화 : 자바 - 코틀린 변환 기록 (0) | 2025.01.23 |
S3 최적화 - 이미지 리사이징 (0) | 2025.01.22 |