온디맨드 영상 변환 시스템 구축기

온디맨드 이미지/영상 변환 시스템을 구축하여 전송/저장 비용을 절반 가까이 줄인 효과를 얻었습니다. 게다가 이미지/영상 스펙이 추가되어도 서버 코드를 수정할 필요가 없어졌어요!

온디맨드 영상 변환 시스템 구축기
Photo by Glenn Carstens-Peters / Unsplash

기존 방식의 문제점

브이리뷰 서비스에는 다양한 영상과 이미지가 리뷰로 등록되고 있습니다. 기존에는 이 미디어들이 등록되자마자 서비스에 최적화된 형태로 리사이징 혹은 트랜스코딩하고 있었는데요. 여기엔 두 가지 문제점이 있었습니다.

자원 낭비

기존에는 미디어가 생성된 직후에 리사이징, 트랜스코딩 작업을 거쳐 S3에 저장하고 있었는데요. 이 경우 실제로는 소비되지 않을 미디어도 미리 변환함으로써 컴퓨팅 자원과 저장 공간을 낭비하게 됩니다. 비용이 발생한다는 말이죠.

새로운 최적화 형태를 추가하기가 어려움

최적화된 미디어 형태가 애플리케이션 코드에 고정되어 있기 때문에, 새로운 형태를 시도해보기가 불편합니다. 새 형태를 추가할 때면 기존에 존재하는 모든 미디어에 대해 인코딩 과정을 추가해야 하는 번거로움도 발생하고요. (이 역시 비용이 발생하겠고요.)

이러한 한계점을 해결하고자 이미지부터 온디맨드 방식을 도입해보기로 했습니다.

온디맨드 이미지 변환 시스템

온디맨드?

미디어 서비스에서의 온디맨드(On-Demand)란 최적화된 미디어를 미리 만들지 않고, 사용자가 요청한 시점에 생성하는 방식을 말합니다. 리뷰의 특성상 사용자가 한 번도 요청하지 않을 미디어가 존재하기 때문에, 기존 방식에 비해 효과가 있으리라 생각했죠.

요구조건

온디맨드로 이미지를 생성하려면 크게 두 가지 조건이 해결되어야 했습니다.

1. 응답 속도

최적화된 이미지를 처음 요청한 경우, 이미지를 생성하고 나서 응답을 주기 때문에 사용자는 응답 속도가 느리다고 느낄 수 있습니다. 다행히 브이리뷰의 이미지는 대부분 200ms 내에 처리되어 큰 문제를 겪지 않았습니다.

2. 갑작스런 요청 증가에 대한 안정적인 처리

이커머스에서는 '오후 3시 선착순 할인 행사' 같이 트래픽이 몰리는 일이 잦습니다. 따라서 최적화 이미지를 한꺼번에 여러 개 생성해야 하는 경우에도 안정적으로 작동해야 하는데요. 브이리뷰에서는 AWS의 람다를 활용하여 이를 안정적으로 처리하였습니다.

시스템 아키텍처

이를 종합하여 만든 온디맨드 이미지 변환 시스템의 아키텍처는 다음과 같습니다.

온디맨드 이미지 변환 시스템의 아키텍처
  1. 챗봇 사용자의 리뷰 이미지가 브이리뷰 서버를 거쳐 S3에 저장됩니다.
  2. 쇼핑몰 사용자가 특정 크기로 리뷰 이미지를 요청합니다.
  3. CloudFront에서는 캐싱된 이미지를 찾아보고, 없으면 API Gateway를 거쳐 이미지 변환 람다를 실행합니다.
  4. CloudFront가 캐싱된 이미지를 쇼핑몰 사용자에게 전달합니다.

온디맨드 영상 변환 시스템

이미지 변환과 달리 영상을 온디맨드로 변환하려니 다른 문제가 따랐습니다.

API Gateway의 특성 중 응답의 크기가 15MB를 넘지 못함

이를 극복하고자 이런 저런 PoC를 진행해보았습니다.

1차 시도 S3 오브젝트 람다

처음엔 다음과 같은 장점 때문에 S3 오브젝트 람다를 사용해보기로 했습니다.

  1. 응답 크기에 제한이 없음
  2. S3와 (거의 똑같이) 호환됨

하지만 실패했는데요. 이유는 두 번째 장점에 적힌 '거의 똑같이'에 숨어 있었습니다. S3 오브젝트 람다는 S3 엑세스 포인트를 통해서만 접근할 수 있었는데요. CloudFront에서는 S3 엑세스 포인트를 지원하지 않았습니다.

게다가 마침 영상을 HLS 형태로 서비스하는 작업도 실험 중이었는데, S3 오브젝트 람다는 한 번의 요청에 대해 여러 파일을 생성하기가 까다로워 보였습니다.

2차 시도 HLS + API Gateway

HLS 스펙을 살펴보니 기존 API Gateway 방식을 살릴 수 있겠다는 생각이 들었는데요. 바로 HLS 스펙의 구조 덕분입니다. HLS 전송 방식에서 최초로 전달되는 *.m3u8 파일은 영상 자체가 아닌, 여러 개로 쪼개진 영상 목록을 적은 텍스트 파일입니다. 만약 화질을 다양하게 제공한다면, 화질별 *.m3u8 파일을 한 데 모아 마스터 *.m3u8 파일로 제공합니다. 그림으로 그려보면 다음과 같습니다.

HLS 파일은 마스터 파일과 미디어 파일, 실제 영상 파일로 구분됩니다

게다가 영상을 처음 재생하는 시점에는 실제 영상 파일인 *.ts 파일들이 모두 존재할 필요도 없었습니다.

플레이리스트는 텍스트 파일이므로 API Gateway의 15MB 제한을 피해갈 수 있었고, 여러 개로 쪼갠 영상 중 첫 번째 부분만 트랜스코딩하는 지연 시간은 영상 전체를 트랜스코딩하는 시간에 비해 굉장히 짧았습니다.

온디맨드 영상 변환 시스템 아키텍처

이를 종합하여 다음과 같은 아키텍처를 구성하였습니다.

온디맨드 영상 변환 시스템의 아키텍처
  1. 쇼핑몰 사용자가 특정 화질로 리뷰 영상을 요청합니다.
  2. CloudFront에서는 캐시된 m3u8 파일을 찾아보고,
  3. 없으면 API Gateway를 거쳐 m3u8 트랜스코딩 요청을 SQS에 보냅니다.
  4. 이와 동시에 플레이리스트를 담은 m3u8 파일 생성용 람다를 실행하여 결과를 반환합니다.
  5. SQS에 쌓인 트랜스코딩 요청은 트랜스코딩 람다를 실행하고, 해당 화질의 영상을 S3에 저장합니다.

개선 효과

작업 도중 이미지 크기와 영상 화질을 조금 수정한 터라, 이전과 정확히 비교하기는 힘들었지만 대략 다음과 같은 개선 효과를 얻었습니다.

  1. CloudFront 전송 비용 40% 절감
  2. S3 저장 용량 60% 절감
  3. 최적화 영상을 다양한 화질로 실험해 볼 수 있는 기반 환경 구축

비용 절감도 좋았지만 마지막 개선 효과가 굉장히 마음에 들었습니다. 사용자에게 제공하는 영상 종류를 바꾸고 싶을 때나 새 영상 종류를 실험해보고 싶을 때마다 서버 코드를 수정하지 않아도 된다는 장점 덕에, 브이리뷰 서비스가 더 빨리 개선될 수 있으니까요. (저도 덜 피곤하겠고요. 😀)