티스토리 뷰
배경
행동대장 서비스에 영수증 이미지를 최적화하면서 궁금한 점이 생겼다. 행동대장 서비스에서 사용자는 CloudFront를 통해 S3에 저장된 이미지를 조회한다. 용량이 큰 이미지를 여러 장 조회하면 응답 시간이 얼마나 느릴까? 이미지를 최적화하면서 응답 시간의 차이를 느껴보자.
추측
사용자가 크롬 브라우저를 사용한다고 가정하자. 크롬 브라우저가 생성하는 기본 최대 커넥션 수는 6개다. 행동대장 서비스에 업로드할 수 있는 이미지의 최대 사이즈는 5mb이고 한 행사에 첨부되는 영수증은 평균 10개다. 사용자가 행사의 모든 영수증을 조회하면 5mb*10개 = 50mb 이미지를 한 번에 요청한다.
이것이 실제로 어떻게 요청될까? 6개의 커넥션을 사용해서 받아올 거라 예상한다. 유후 상태의 6개의 커넥션을 사용해서 6개의 이미지를 다운로드하고 나머지 4장은 순차적으로 커넥션을 받아서 사용할 것 같다. 그럼, 대략 하나의 커넥션으로 5mb 이미지 2장을 순차적으로 받아오는 정도의 시간이 소요되지 않을까?
실제
html에서 img 태그를 사용해서 5mb 이미지 10개를 s3에서 요청하게 구현해서 테스트했다. s3에 직접 요청하는 것은 아니고, CloudFront를 거친다.
다음은 5mb jpg 이미지 10장을 요청한 결과다. 총 응답 시간은 1200ms 정도이다. 여러 번 반복했을 때, 평균적으로 1000ms 이상 소요된다. 그런데, 예상과 다르게 1개의 커넥션을 사용했다.
왜 1개의 커넥션을 사용할까? 바로 http2를 사용해서 하나의 커넥션으로 요청을 병렬로 처리하기 때문이다. 간단하게 설명하면, http2에서 각 요청은 스트림을 생성하고 멀티플렉싱을 통해 하나의 커넥션으로 병렬처리된다. 요청은 프레임 단위로 잘려서 네트워크를 이동한다. 덕분에 하나의 커넥션만 사용해서 빠르게 응답받을 수 있었다.
여기서 한 가지 더 궁금한 게 생겼다. 커넥션은 (클라이언트 ip, 클라이언트 port, 서버 ip, 서버 port)로 구성된다. 커넥션은 4가지 파라미터로 유일성을 보장한다. http2가 하나의 커넥션을 사용해서 병렬 처리하는 것은 동일한 서버로의 요청에만 해당하지 않을까?
실제로 다른 서버로의 요청은 서로 다른 커넥션을 사용한다. 다음 그림을 보면 image*.jpg 요청은 CloudFront로 64410384 요청은 Github의 서버로 향한다. 그림 상단의 waterfall을 보면 2줄을 확인할 수 있고 이것은 2개의 커넥션을 사용했다는 의미다.
포맷에 따른 응답 시간 측정
이렇게 끝내기 아쉬우니까 이미지 포맷에 따른 응답 시간을 측정해 보자. http2에서 5mb jpeg 10장은 1000ms 이상의 응답 시간이 소요됐다. 현재 행동대장에서 다루고 있는 .webp와 .avif도 테스트해 보자.
5mb .jpeg 이미지를 .webp로 변환했다. 이미지 크기는 5.3mb(jpeg) 에서 2.9mb(webp)로 감소했다. 아래 10장의 webp를 요청했을 때 응답 시간이 600ms 내외로 감소한 것을 확인할 수 있다. jpeg에 비해 약 40%정도 감소했다.
이번에는 avif를 해보자. 5mb .jpeg 이미지를 .avif로 변환하니까 이미지 크기는 5.3mb(jpeg) 에서 1.7mb(avif)로 감소했다. 아래 10장의 avif 이미지를 요청했을 때 응답 시간이 350ms 내외로 감소한 것을 확인할 수 있다. jpeg에 비해 약 65%정도 감소했다.
마무리
작업하다가 테스트해본 결과를 간단하게 정리했다. 너무 간단해서 남길까 고민했지만, 금붕어인 나를 위해 남긴다.
'프로젝트 - 행동대장' 카테고리의 다른 글
정말 무중단 배포일까? (0) | 2024.10.20 |
---|---|
영수증 이미지 최적화 방법과 여러 구현 방식 (1) | 2024.10.09 |
8인의 협업, 갈등 상황에서 찾은 나의 역할 (1) | 2024.09.21 |