유튜브 시스템을 설계하는 방식은 넷플릭스나 훌루 같은 비디오 플랫폼을 설계하는 문제에도 적용 가능하다.
유튜브 시스템에서 제공하는 기능들은 단순해보이지만, 엄청난 트래픽으로 인해 매우 복잡한 수많은 기술들이 숨어있다.
- MAU: 20억
- 매일 재생되는 비디오 수: 50억
- 5천만명의 창작자
- 광고 수입은 2019년 기중 150억 달러
- 전체 모바일 트래픽 중 37%는 유튜브
- 80개 언어로 사용 가능
1단계: 문제 이해 및 설계 범위 확정
유튜브에서는 비디오를 보는 것 말고도 많은 일을 할 수 있다.
- 댓글
- 비디오 공유
- 좋아요
- 재생 목록 저장
- 구독
모든 내용을 설계 면접 동안 만들 수 없으므로, 요구하는 핵심 기능만을 찾아 범위를 제한해야한다.
- Q. 가장 중요한 기능은?
- A. 비디오를 올리는 기능과 시청하는 기능
- Q. 지원 클라이언트는?
- A. 모바일 앱, 웹 브라우저, 스마트 TV
- Q. 일간 능동 사용자 수?
- A. 5백만
- Q. 이 제품에 평균적으로 소비하는 시간
- A. 30분
- Q. 다국어 지원?
- A. 어떤 언어로도 사용 가능해야함
- Q. 비디오 해상도 지원 범위?
- A. 현존하는 비디오 종류와 해상도를 대부분 지원해야함
- Q. 암호화?
- A. Y
- Q. 비디오 파일 크기에 제한?
- A. 1GB
- Q. 클라우드 서비스 사용 가능 여부?
- A. Y
위 질문을 통해 찾아낸 요구사항과 비디오 스트리밍 서비스에 필요한 항목들을 정리하면 아래와 같다.
- 빠른 비디오 업로드
- 원활한 비디오 재생
- 재생 품질 선택 가능(대부분의 종류와 해상도 지원)
- 낮은 인프라 비용
- 높은 가용성과 규모 확장성, 안정성(DAU 5백만)
- 지원 클라이언트(모바일 앱, 브라우저, 스마트 TV)
개략적 규모 추정
시스템이 처리해야하는 트래픽 규모를 추정하여 어떤 기술들을 어디까지 활용해야야하는지 파악한다.
도메인에 대해 정확히 파악할 수 없을 때는 상식적인 범위 내에서 조건을 가정한다.
- DAU 5백만
- 한 사용자가 하루 평균 5개 비디오 시청
- 10%의 사용자가 하루에 비디오 1개 업로드
- 비디오의 평균 크기는 300MB
- 비디오 저장을 위해 매일 새로 요구되는 저장 용량
500만 * 10% * 300MB = 150TB
- CDN 비용
- 클라우드 CDN 사용시 나가는 데이터의 양에 따라 과금된다.
- 아마존 클라우드 프론트를 사용할 경우, 미국 기준 1GB당 $0.02
- 비디오 스트리밍 기준
5백만 * 5 비디오 * 0.3GB * $0.02 = $150,000
추정 결과에 따르면 CDN을 통해 비디오를 서비스할 경우 비용이 엄청나다.
따라서 CDN으로 인한 비용을 줄이는 방법들까지 고민해야한다.
2단계: 개략적 설계안 제시 및 동의 구하기
이번 설계안은 CDN과 BLOB 스토리지의 경우 기존 클라우드 서비스를 활용한다.
- 시스템 설계 면접은 모든 것을 밑바닥부터 만드는 것과는 큰 관계는 없다.
- 주어진 시간 안에 적절한 기술을 골라 설계를 마치는 것이 핵심
- 모든 세부 컴포넌트에 대해 설계를 제시하는 것은 지나치다.
- 규모 확장이 쉬운 BLOB 저장소, CDN을 만드는 것은 복잡하며, 비용이 많이 든다.
- 넷플릭스, 페이스북 같은 회사들도 클라우드 서비스를 이용할 정도로
개략적으로 보면 이 시스템은 세가지 컴포넌트로 구성된다.
- 사용자 단말
- CDN
- 비디오가 저장되며 재생 버튼을 누르면 CDN으로부터 스트리밍이 이루어진다.
- API 서버
- 비디오 스트리밍을 제외한 모든 요청은 API 서버가 처리한다.
- 피드 추천, 비디오 업로드 URL 생성, 메타데이터 데이터베이스와 캐시 갱신, 사용자 가입 등
핵심 영역인 비디오 업로드 절차와 비디오 스트리밍 절차를 설계한다.
비디오 업로드 절차
- API 서버
- 비디오 스트리밍을 제외한 모든 요청 처리
- 메타데이터 DB
- 비디오의 메타데이터 보관
- 샤딩과 다중화를 적용하여 성능 및 가용성 요구사항을 충족시킨다고 가정
- 메타데이터 캐시
- 비디오 메타데이터와 사용자 객체를 캐싱
- 원본 저장소
- 원본 비디오를 보관할 대형 이진 파일 저장소
- BLOB(Binary Large Object storage)
- 이진 데이터를 하나의 개체로 보관하는 데이터베이스 관리 시스템
- 트랜스코딩 서버
- 비디오의 포맷을 변호나하는 절차를 수행하는 서버
- 단말, 대역폭 요구사항에 맞는 최적의 비디오 스트림을 제공하기 위해
- 트랜스코딩 비디오 저장소
- 트랜스코딩이 완료된 비디오를 저장하는 BLOB 저장소
- CDN
- 비디오를 캐싱
- 비디오 스트리밍은 CDN을 통해 이루어짐
- 트랜스코딩 완료 큐
- 비디오 트랜스코딩 완료 이벤트를 보관할 메시지 큐
- 트랜스코딩 완료 핸들러
- 트랜스코딩 완료 큐에서 이벤트 데이터를 꺼내어 메타데이터 캐시와 데이터베이스를 갱신할 작업 서버들
비디오 업로드는 비디오 업로드와 비디오 메타데이터 갱신이 병렬적으로 수행된다.
프로세스 a: 비디오 업로드
- 비디오를 원본 저장소에 업로드
- 트랜스 코딩 서버가 원본 저장소에서 해당 비디오를 가져와 트랜스코딩을 시작
- 완료 후 아래 절차가 병렬적으로 수행
- 트랜스코딩 비디오 저장소로 업로드
- 트랜스코딩 완료 이벤트를 트랜스코딩 완료 큐에 넣음
- 트랜스코딩이 끝난 비디오를 CDN에 올림
- 완료 핸들러가 이벤트 데이터를 큐에서 꺼냄
- 완료 핸들러가 메타데이터 데이터베이스와 캐시를 갱신
- 비디오 업로드가 끝나 스트리밍 준비가 되었음을 알림
프로세스 b: 메타데이터 갱신
원본 저장소에 파일이 업로드 되는 동안, 병렬적으로 비디오 메타데이터 갱신 요청을 API 서버에 보내 처리한다.
- 파일 이름, 크기, 포맷 등
비디오 스트리밍 절차
스트리밍은 사용자의 장치가 원격지의 비디오로부터 지속적으로 비디오 스트림을 전송받아 영상을 재생하는 것을 말한다.
스트리밍 프로토콜
비디오 스트리밍을 위해 데이터를 전송할 때 쓰이는 표준화된 통신 방법
- MPEG-DASH(Moving Picture Experts Group-Dynamic Adaptive Streaming over HTTP)
- Apple HLS(HTTP Live Streaming)
- MS Smooth Streaming
- 어도비 HDS(HTTP Dynamic Streaming) 등
프로토콜마다 지원하는 비디오 인코딩이 다르기 때문에 플레이어도 다르다.
따라서 비디오 스트리밍 서비스를 설계할 때는 서비스 용례에 맞는 프로토콜을 잘 골라 사용한다.
비디오는 CDN에서 바로 스트리밍된다. 사용자의 단말에 가장 가까운 CDN 에지 서버가 비디오 전송을 담당할 것이다.
3단계: 상세 설계
비디오 업로드를 담당하는 부분과 비디오 스트리밍을 담당하는 부분을 최적화 방안을 통해 다듬고, 요류 처리 매커니즘을 반영한다.
비디오 트랜스코딩
비디오를 녹화하면 특정 포맷으로 저장되는데, 다른 단말에서도 잘 재생되려면 호환되는 비트레이트 포맷으로 저장되어야 한다.
비디오 트랜스코딩은 다음과 같은 이유로 중요하다.
- 원본 비디오는 저장 공간을 많이 차지한다.
- 대부분 클라이언트는 특정 종류의 비디오 포맷만 지원한다.
- 하나의 비디오를 여러 포맷으로 인코딩 해놓아야한다.
- 끊김 없는 재생을 보장하기위해 사용자에게 맞는 화질의 비디오를 제공하는 것이 좋다.
- 대역폭 등
- 모바일의 경우 네트워크 상황이 실시간으로 달라질 수 있는데 이에 맞추어 화질이 자동으로 변경되거나 변경할 수 있게 해야한다.
인코딩 포멧
대부분의 인코딩 포멧은 다음 두 부분으로 구성되어있다.
- 컨테이너
- 비디오 파일, 오디오, 메타데이터를 담는 바구니
- 컨테이너 포맷은 확장자를 통해 확인할 수 있다(.avi, .mov, .mp4 등)
- 코덱
- 비디오 화질을 보존하며 파일 크기를 줄일 목적으로 고안된 압축 및 해제 알고리즘
- H.264, VP9, HEVC 등
유향 비순환 그래프(DAG) 모델
비디오를 트랜스코딩하는 것은 컴퓨터 자원을 많이 소모할 뿐 아니라 시간도 많이 든다.
또한 콘텐츠 창작자가 각자 가기만의 비디오 프로세싱 요구사항을 가지고있다.
- 워터마크
- 커스텀 섬네일 이미지
- 화질 등
이러한 각기 다른 유형의 비디오 프로세싱 파이프라인을 지원하는 한편 처리 과정의 병렬성을 높히기 위해 적절한 수준의 추상화를 도입하여 클라이언트 프로그래머로 하여금 실행할 작업을 손수 정의할 수 있도록 해야한다.
페이스북의 스트리밍 비디오 엔진은 DAG 프로그래밍 모델을 도입하여 해당 작업들이 순차적, 병렬적으로 실행될 수 있도록 하고있다.
- DAG 모델을 도입하면 유연성과 병렬성을 달성할 수 있다.
원본 비디오는 비디오, 오디오, 메타데이터 세 부분으로 나뉘어 처리된다.
비디오
- 검사(inspection)
- 좋은 품질의 비디오인지, 손상은 없는지 확인한다.
- 비디오 인코딩(video encoding)
- 비디오를 다양한 해상도, 코덱, 비트레이트 조함으로 인코딩한다.
- 섬네일(thumbnail)
- 사용자가 업로드한 이미지나 비디오에서 자동으로 추출된 이미지로 섬네일을 만든다.
- 워터마크(watermark)
- 비디오데 대한 식별정보를 이미지 위에 오버레이 형태로 띄워 표시한다.
비디오 트랜스코딩 아키텍처
클라우드 서비스를 활용한 비디오 트랜스코딩 아키텍처는 다섯 개의 주요 컴포넌트로 구성된다.
- 전처리기(preprocessor)
- DAG 스케줄러
- 자원 관리자(resource manager)
- 작업 실행 서버(resource worker)
- 임시 저장소(temporary storage)
전처리기
전처리기는 3가지 작업을 수행한다.
- 비디오 분할(video spliting)
- 비디오 스트림을 GOP(Group of Pictures)라고 불리는 단위로 쪼갠다.
- 오래된 단말이나 브라우저는 GOP 단위의 비디오 분할을 제공하지 않기 때문에 전처리기가 대신 수행한다.
GOP
특정 순서로 배열된 프레임(frame) 그룹으로 하나의 GOP는 독립적으로 재생 가능하며, 길이는 보통 몇 초 정도다.
- DAG 생성
- 작성한 설정 파일에 따라 DAG를 만들어낸다.
- 작성한 설정 파일에 따라 DAG를 만들어낸다.
- 데이터 캐시
- 전처리기는 분할된 비디오의 캐시 역할도 수행한다.
- 안정성을 높이기 위해 GOP와 메타데이터를 임시 저장소에 보관한다.
- 인코딩 실패시 보관된 데이터를 활용해 인코딩을 재개한다.
DAG 스케줄러
DAG 그래프를 몇 개 단계(stage)로 분할한 다음 그 각각을 자원 관리자의 작업 큐에 집어넣는다.
하나의 DAG를 2개 작업 단계로 쪼갠 사례이다.
- 비디오, 오디오, 메타데이터를 분리
- 비디오 파일을 인코딩, 섬네일을 추출, 오디오 파일 인코딩
자원 관리자
자원 배분을 효과적으로 수행하는 역할을 담당한다.
세 개의 큐와 작업 스케줄러(Task scheduler)로 구성된다.
- 작업 큐(task queue)
- 실행할 작업이 보관되어 있는 우선순위 큐
- 작업 서버 큐(worker queue)
- 작업 서버의 가용 상태 정보가 보관되어 있는 우선순위 큐
- 실행 큐(runner quere)
- 현재 실행 중인 작업 및 작업 서버 정보가 보관되어 있는 뷰
- 작업 스케줄러
- 최적의 작업/서버 조합을 골라 해당 작업 서버가 작업을 수행하도록 지시한다.
작업 관리자는 다음과 같이 동작한다.
- 작업 큐에서 가장 높은 우선순위의 작업을 꺼낸다.
- 해당 작업을 실행하기 적합한 작업 서버를 고른다.
- 해당 작업 서버에게 작업 실행을 지시한다.
- 해당 작업이 어떤 서버에게 할당되었는지에 관한 정보를 실행 큐에 넣는다.
- 작업이 완료되면 해당 작업을 생행 큐에서 제거한다.
작업 서버
DAG에 정의된 작업을 수행한다.
작업 종류에 따라 작업 서버도 구분하여 관리한다.
임시 저장소
임시 저장소 구현에는 여러 저장소 시스템을 활용할 수 있으며, 저장할 데이터의 유형, 크기, 이용 빈도, 데이터 유효기간 등에 따라 선택한다.
- 메타데이터
- 작업 서버가 빈번히 참조하는 정보, 크기가 작으므로 메모리에 캐시
- 비디오/오디오
- BLOB
임시 저장소에 보관한 데이터는 비디오 프로세싱이 완료되면 삭제한다.
인코딩된 비디오
인코딩 파이프라인의 초종 결과물이다.
funny_720p.mp4
와 같은 이름을 짓는다.
시스템 최적화
속도, 안정성 비용 측면에서 시스템을 최적화한다.
속도 최적화
비디오 병렬 업로드
비디오 전부를 한 번의 업로드로 올리는 것은 비효율적이다.
하나의 비디오는 작은 GOP로 분할할 수 있으며, 분할한 GOP를 병렬적으로 업로드하면 일부가 식패해도 빠르게 업로드를 재개할 수 있다.
따라서 비디오를 GOP 경계에 맞춰 분할하는 작업을 단말이 수행하면 업로드 속도를 높일 수 있다.
업로드 센터를 사용자 근거리에 지정
업로드 센터를 여로 곳에 두고 가까운 센터로 업로드 하도록 한다.
- 이를 위해 이번 설계안은 CDN을 업로드 센터로 이용한다.
모든 절차를 병렬화
느슨하게 결합된 시스템을 만들어서 병렬성을 높이면 낮은 응답지연에 도움이된다.
기존 설계안의 비디오를 원본 저장소에서 CDN으로 옮기는 절차를 보면, 어떤 단계의 결과물은 이전 단계의 결과물을 입력으로 사용하여 만들어지는데, 이러한 의존성이 있다면 병렬성을 높이기 어렵다.
이러한 결합은 메시지 큐를 도입하여 개선할 수 있다.
- 메시지 큐를 도입하기 전
- 인코딩 모듈은 다운로드 모듈의 작업이 끝나기를 기다려야한다.
- 메시지 큐를 도입한 후
- 인코딩 모듈은 다운로드 모듈의 작업이 끝나기를 기다리는 것이 아닌, 메시지 큐에 보관된 이벤트 각각을 인코딩 모듈이 병렬적으로 처리할 수 있게된다.
안전성 최적화
미리 사인된 업로드 URL
미리 사인된 URL?
아마존 S3에서 쓰이는 용어로, 접근 공유 시그니처 라고도 부른다.
허가받은 사용자만이 올바른 장소에 비디오를 업로드할 수 있도록 하기 위해 미리 사인된(pre-signed) 업로드 URL을 이용한다.
- 클라이언트는 HTTP 서버에 POST 요청을 통해 미리 사인된 URL을 받는다.
- 해당 URL이 가르키는 객체에 대한 접근 권한이 이미 주어져 있는 상태
- 미리 사인된 URL을 돌려준다.
- 클라이언트는 해당 URL이 가리키는 위치에 비디오를 업로드한다.
비디오 보호
많은 콘텐츠 제작자가 비디오 원본을 도난당할까 우려하여 인터넷에 비디오를 업로드하기를 주저한다.
이러한 저작권 보호를 위해 다음 세가지 선택지 중 하나를 채택할 수 있다.
- 디지털 저작권 관리(DRM: Digital Rights Management) 시스템 도입
- 애플의 페어플레이, 구글 와이드바인, MS의 플레이레디 등
- AES 암호화
- 비디오를 암호화하고 접근 권한을 설정하는 방식
- 재생 시에만 복호화하며, 허락된 사용자만 암호화된 비디오를 시청할 수 있다.
- 워터마크
- 비디오 위에 소유자 정보를 포함하는 이미지 오베리이를 올린다.
- 회사 로고, 이름 등
비용 최적화
비디오 데이터 제공을 위한 CDN은 이번 설계한 시스템의 핵심이다.
하지만 CDN은 비싸고, 데이터 크기가 클 수록 더욱 비싸다.
연구 결과에 따르면, 유트브의 비디오 스트리밍은 롱테일 분포를 따른다.
- 인기 있는 비디오가 대부분 재생의 대부분을 차지한다.
이러한 점을 이용하여 몇 가지 최적화를 시도할 수 있다.
- 인기 비디오는 CDN으로 재생하되 다른 비디오는 비디오 서버를 통해 재생한다.
- 비인기 비디오는 인코딩 할 필요가 없을 수 있으며, 짧은 비디오라면 필요할 때 인코딩하여 재생할 수 있다.
- 특정 비디오는 특정 지역에서만 인기가 높다. 이런 비디오는 다른 지역으로 옮길 필요가 없다.
- CDN을 직접 구축하고 인터넷 서비스 제공자와 제유한다.
- CDN을 직접 구축하는 것은 초대형 프로젝트이지만 대규모 스트리밍 사업자라면, 비용을 줄이고 사용자 경험을 향상시킬 수 있어 시도할 수 있다.
이러한 최적화는 콘텐츠의 인기도, 이용 패턴, 비디오 크기 등 데이터에 근거한 것으로, 최적화를 시도하기 전 시청 패턴을 분석하는 것이 매우 중요하다.
오류처리
대형 시스템에서 오류는 불가피하다.
장애를 아주 잘 감내하는(highly fault-tolerant) 시스템을 만들려면 오류들을 우아하게 처리하고 빠르게 회복해야한다.
- 회복 불가능 오류(recoverable error)
- 특정 비디오 세그먼트 트랜스코딩 실패 같은 오류는 회복 가능한 오류이다.
- 몇 번 재시도하면 해결되는 경우가 많다.
- 계속해서 실패하고, 복구가 어렵다 판단되면 클라이언트에게 적절한 오류 코드를 반환해야한다.
- 회복 불가능 오류(non-recoverable error)
- 비디오 포맷이 잘못되었다거나 하는 회복 불가능한 오류가 발견되면 해당 비디오에 대한 작업을 중단하고 클라이언트에게 적절한 오류를 반환해야한다.
시스템 컴포넌트 각각에 발생할 수 있는 오류에 대한 전형적 해결 방법 요약하면 아래와 같다.
- 업로드 오류
- 몇 회 재시도
- 비디오 분할 오류
- 클라이언트가 분할하지 못하는 경우라면, 전체 비디오를 서버로 전송하고 서버가 해당 비디오 분할을 처리하도록 한다.
- 트랜스코딩 오류
- 재시도
- 전처리 오류
- DAG 그래프 재생성
- DAG 스케줄러 오류
- 작업을 다시 스케줄링
- 자원 관리자 큐에 장애 발생
- 사본을 이용
- 작업 서버 장애
- 다른 서버에서 해당 작업 재시도
- API 서버 장애
- API를 무상태로 관리하여 신규 요청을 다른 API로 우회
- 메타데이터 캐시 서버 장애
- 데이터 다중화를 통해 다른 노드에서 데이터를 가져올 수 있다.
- 장애가 난 캐시 서버는 새로운 것으로 교체
- 메타데이터 데이터베이스 장애
- 주 서버: 부 서버 가운데 하나를 주 서버로 교체
- 부 서버: 다른 부 서버를 통해 읽기 연산 처리 및 죽은 서버 교체
4단계: 마무리
이외에 중요할 수 있는 내용들은 다음과 같다.
- API 계층 규모 확정성 확보 방안
- 무상태 서버이므로 수평 규모 확장이 가능하다는 사실을 언급하면 좋다.
- 데이터베이스 계층의 규모 확장성 확보 방안
- 다중화와 샤딩 방법에 대해 언급
- 라이브 스트리밍
- 라이브 스트리밍은 비디오를 실시간으로 녹화하고 방송하는 절차를 말한다.
- 가장 중요한 차이는 다음과 같다.
- 응답지연이 좀 더 낮아야 한다.
- 스트리밍 프로토콜 선정에 유의해야한다.
- 작은 단위의 데이터를 실시간으로 빨리 처리해야하므로 병렬화 필요성은 떨어진다.
- 너무 많은 시간이 걸리는 오류 처리 방안은 활용할 수 없다.
- 응답지연이 좀 더 낮아야 한다.
- 비디오 삭제
- 저작권 위반, 선정성, 불법 행위에 관계된 비디오는 내려야한다.
- 업로드 과정에서 식별
- 사용자의 신고 절차 활용