유저 테스트를 끝내고 정식 출시 전에 서버 최적화 및 성능 개선을 하고 있다. 더 할 수 있는 게 뭐가 있을까 생각하던 중 문득 얼마 전에 "가상 면접사례로 배우는 대규모 시스템 설계 기초" 에서 읽은 CDN이 생각나서 사용해 보기로 했다. 마침 우리 어플에서 사진이 늦게 업로드되는 상황이 있어서 아주 적절한 해결책이라 생각했다.
CDN
CDN은 Content Delivery Network의 약자이며 위에 언급한 책에서 "정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크이다. 이미지, 비디오, CSS, JavaScript 파일 등을 캐시할 수 있다."라는 설명을 제공한다. 한마디로 정적 컨텐츠에 대한 캐싱을 담당해 준다고 생각할 수 있다. "지리적으로 분산된"이 나타내는 것은 아래의 예시로 이해할 수 있다.
CDN을 사용하지 않는 경우
- 미국에 있는 사용자가 이미지를 조회한다.
- 이미지가 저장되어 있는 한국 서버에서 데이터를 불러와 미국으로 전달한다.
CDN을 사용하는 경우
- 미국에 있는 사용자가 이미지를 조회한다.
- 지리적으로 분산된 CDN 서버가 여러 나라에 분포되어 있다. (미국, 중국, 등등 사용하는 CDN에서 설정되어 있다.)
- 미국과 가까운 CDN서버에서 이미지를 전달한다.
이처럼 가까운 지역에 있는 서버에서 정적 컨텐츠를 받아볼 수 있기 때문에 속도적으로 이점이 있다. (물론 캐싱 기능이라 했기 때문에 CDN에 데이터가 없으면 origin 서버에서 조회한 후 캐시를 저장한다. -> 일반적인 캐시와 같은 원리)
AWS CloudFront
그래서 내가 고른 CDN 서비스는! AWS의 cloudfront이다. 캐싱하고 싶은 이미지가 저장되어 있는 s3와 연동이 간편하고 프리티어 기준 1TB 데이터, 월 1000만 건의 HTTP/HTTPS 요청을 제공하기 때문에 선택을 안 할 이유가 없었다.
CloudFront 제공 기능
- Edge Location : 전세계에 퍼져있는 CDN 서비스 제공 서버이다. 컨텐츠를 요청한 사용자와 가까운 엣지 로케이션에서 컨텐츠 제공
- 동적 컨텐츠 저장 : CDN은 정적 컨텐츠만 캐싱하지만 cloudfront를 ec2와 연동하여 동적 컨텐츠까지 가능하다.
- 보안 : SSL 암호화 무료 제공하여 HTTPS 설정도 쉽게 할 수 있다. / DDoS 공격 대비, 웹 애플리케이션 방화벽을 제공한다.
- 오리진 보호 : 클라이언트에서 S3 같은 오리진에 직접적인 접근하는 것을 제한할 수 있다.
그래서 나는 어떻게 사용하고 있나?
연결 방법은 아래 내가 참고한 링크를 남겨둘 예정이다. 이 과정에서 발생한 문제상황이 있었다.
우리 데이터베이스에는 이미 S3 URL이 저장되어있다..
사용자가 cloudfront에서 이미지를 접근하기 위해서는 서버에서 return을 cloudfront의 주소 + 파일 이름을 보내줘야 한다. 하지만 나는 s3만 사용하다가 cloudfront를 나중에 적용하는 것이어서 DB에 이미 s3 접근 주소가 저장되어 있었다.. 어쩜 좋지 고민하고 있었는데 생각보다 쉽게 문제를 해결했다.
UPDATE IMAGE_FILE
SET origin_url = REPLACE(origin_url, 's3 버킷 주소 prefix', 'cloudfront 주소 prefix'),
thumbnail_url = REPLACE(thumbnail_url, 's3 버킷 주소 prefix', 'cloudfront 주소 prefix')
WHERE origin_url like '%기존 s3 버킷 주소 + (디렉터리 명)%';
S3에 저장된 이미지의 주소는 동일한 prefix를 갖고 있기 때문에 이것을 cloudfront의 주소 prefix로 REPLACE 해주면 해결~
S3에 있는 원본 접근 제어하기!!
cloudfront를 사용해서 클라이언트가 S3에 직접적으로 접근하지 못하게 하는 것이 장점이었지만 나처럼 테스트를 하는 경우 속도 비교, 혹시 모를 오류를 대비해서 S3에서도 이미지에 접근이 가능하게 해줘야 하는 것이 좋다. 그래야 S3에서 제공하는 주소로 이미지에 접근이 가능하다.
그럴 때는 cloudfront 배포할 때 원본 엑세스 설정을 공개로 하면 된다. (원래는 원본 액세스 제어 설정을 선택하여 S3에 직접 접근하는 것을 막는 것이 권장된다.)
[AWS] S3와 CloudFront 연동하기
S3와 CloudFront 연동하기
velog.io
속도 비교
그래서 얼마나 속도 차이가 나는지 비교해 보았다. 네트워크 속도, 프로세스 등의 환경 변수가 너무 많이 존재해서 어떻게 비교할지 고민하다가 개발자 도구 -> 이미지 파일 클릭 -> Timing에서 Waiting for server response라는 항목을 발견했다. (Request sent, Content Download 등은 인터넷 속도와 다른 프로세스의 영향을 많이 받는다.) 이것을 단순 일회성 비교를 했을 때 각각 36.28ms, 28.36ms로 약 22% 개선되었다.

매번 값이 바뀌기 때문에 10번씩 강력 새로고침 & 캐시삭제로 조회한 평균을 계산해 보니 Cloudfront 사용 시 26.48ms, S3 사용 시 33.64ms의 결과가 나와 Cloudfront를 사용했을 경우 약 23% 정도의 속도 향상이 발생했다.
마무리
비록 ms 단위로 조금 단축된 것 같지만 실제 서비스에는 이미지가 훨씬 많고 우리 어플은 다국어를 지원하며 외국인 소비층을 주요 소비자로 생각하고 있기 때문에 해외에서 비교했을 경우 차이가 더 클 것으로 예상된다. 현재 우리의 S3에 저장되어 있지 않은 이미지도 존재하여 모든 이미지에 적용하지는 못했지만 그래도 나름 의미 있는 성능 개선이라고 생각한다. 오늘도 끝~
'My project > Nanaland in Jeju' 카테고리의 다른 글
| Slack으로 서버 로그 모니터링하기 (Feat. Spring AOP, Logback) (3) | 2024.11.12 |
|---|---|
| 프로젝트 진행 시 엑셀에 작성한 데이터, DB에 저장하는 방법 (0) | 2024.10.17 |
| 스프링 검색어 자동완성 비동기 처리 (Feat. 1만번의 부하테스트 결론은 Over Engineering 이었다고 한다..) (5) | 2024.08.29 |
| 검색어 자동완성 구현하기 with Redis (Feat. Elasticsearch) (3) | 2024.08.01 |
| Stream API 사용 중 .toList()에서 UnsupportedOperationException 발생한 썰 (1) | 2024.07.26 |