
2억 4천만 유저 커버치는 비법?
요약
트위치가 폭발적인 성장 과정에서 겪은 모놀리식 아키텍처의 한계를 극복하고, Ruby on Rails에서 Go 언어 기반의 마이크로서비스로 전환한 기술적 여정을 다룹니다. 대규모 채팅 트래픽을 처리하기 위해 언어와 아키텍처를 어떻게 변경했는지 상세히 설명합니다.
핵심 포인트
- 모놀리식 아키텍처의 한계와 확장성 문제 해결 과정
- Ruby on Rails에서 Go 언어로의 대대적인 마이그레이션 사례
- Nginx 리버스 프록시를 활용한 점진적 트래픽 전환 전략
- 실시간 채팅 서비스의 성능 최적화를 위한 기술적 선택
Video: 2억 4천만 유저 커버치는 비법?
Channel: 노마드 코더 Nomad Coders
Duration: 9m 4s
Source: subtitle (auto, ko)
Transcript:
오늘은 트위치가 어떻게 수백만 명의 사용자에게 거의 실시간으로 영상을 스트리밍하는지, 왜 루비에서 Goang으로 마이그레이션했는지, 그리고 여러분도 파산하지 않고 라이브 스트리밍 경험을 구축하는 방법을 알아보겠습니다. 처음 오신 분이라면, 제 이름은 니콜라스이고 대한민국 서울에 사는 소프트웨어 개발자입니다. 저는 무언가를 만들고 다른 사람들에게 만드는 방법을 가르치는 것을 좋아합니다. 저스틴 KH와 그의 공동 창업자들은 저스틴의 일상을 24시간 내내 생중계하는 Justin TV를 시작했습니다. 이후 누구나 다양한 카테고리에서 자신만의 라이브 스트림을 만들 수 있도록 확장했습니다. Justin TV의 게임 섹션이 큰 인기를 얻으면서 게임 콘텐츠에만 집중하는 스핀오프 플랫폼인 Twitch TV가 2011년에 탄생했습니다. 초기 트위치는 Ruby on Rails를 사용한 모놀리식 아키텍처로 구축되었습니다. 모놀리 식 아키텍처란 애플리케이션의 모든 부분이 상호 연결되어 단일 서비스로 실행되는 것을 의미합니다.
모놀리식 아키텍처는 빠른 개발과 반복이 가능하기 때문에 스타트업에 매우 적합 하지만, 트위치가 폭발적으로 성장하면서 이러한 아키텍처의 한계가 드러나기 시작했습니다. 트위치에서 채팅은 모든 것이며, 트위치를 성공으로 이끄는 핵심 요소입니다. 재밌게 시청하는 것, 즉 스트리머와 시청자가 채팅 없이 서로 소통하는 방식이 바로 트위치입니다. 트위치는 기본적으로 유튜브와 같은 역할을 합니다. 초기에는 8대의 컴퓨터를 사용하여 채팅 서비스를 원활하게 운영했지만, 채널 규모가 커지고 게임 이벤트가 인기를 얻으면서 하나의 대형 채널이 전체 시스템의 속도를 저하시켜 다른 채널의 채팅에도 영향을 미치는 문제가 발생했습니다. 8대의 컴퓨터에 분산된 채팅 시스템 중 한 대의 속도가 느려지면 전체 채팅의 1/8이 영향을 받게 되는 것입니다. 트위치는 이 문제를 해결하기 위해 Node.js를 사용하여 별도의 채팅 서비스를 구축하려 했지만, Node.js에서 버그를 발견했습니다. 당시 개발자 B는 매우 어렸기 때문에 결국 파이썬 실시간 프레임워크인 Tornado를 사용하여 새로운 채팅 서비스를 개발하게 되었습니다.
2012년에는 Go 프로그래밍 언어 버전 1.0이 출시되었고, 트위치 엔지니어들은 Go 언어가 실제 운영 환경에 적합한지 확인하기 위해 시스템 성능 한계를 시험하는 스트레스 테스트 도구를 Go로 개발했습니다. 이 실험을 통해 Go 언어가 실제 운영 환경에 적합하다는 것이 입증되었고, 동시에 파이썬 Tornado 채팅 시스템의 취약점도 발견되었습니다. 트위치가 실제 운영 환경에서 처음으로 사용한 Go 프로그램은 메시지 교환 서버였습니다. 이 서버는 단 100줄의 코드로 모든 트위치 메시지를 처리했습니다. 트위치 홈페이지에 실시간으로 인기 라이브 스트림 목록을 제공하는 Jax라는 새로운 서비스가 Go 언어로 처음부터 개발 되었습니다. 트위치 직원 들은 Go 언어에 매료되어 2015년에 모든 것을 Go로 재구축하기로 결정했습니다. 완전히 새로운 코드를 작성하는 대대적인 작업이었죠. 기존 Ruby on Rails API의 모든 엔드포인트를 Go 마이크로서비스로 재구축하고, 백엔드 API 앞에 있는 새로운 Go 마이크로서비스로 트래픽을 점진적으로 리디렉션했습니다.
이를 위해 NgX 리버스 프록시를 사용하여 트래픽을 분산시켰습니다. 이 트래픽 분산 시스템은 기존 코드에서 새로운 코드로 트래픽을 천천히 리디렉션하면서 문제가 발생하지 않는지 확인하는 역할을 했습니다. 이렇게 해서 새로운 코드로의 트래픽이 100% 안정될 때까지 작업을 진행했습니다. 2015년에 시작된 이 작업은 2018년 말, 기존 서버가 트래픽 수신을 중단하고 트위치가 AWS 계정의 모든 EC2 인스턴스를 종료하면서 완료되었습니다. 마이크로서비스는 완벽한 해결책은 아니지만, 시스템 의 복잡성을 증가시킵니다. 모놀리식 시스템에서는 파일을 가져와 메서드를 호출할 수 있지만, 마이크로서비스에서는 서비스 간 네트워크 호출이 필요하기 때문입니다. 서비스라는 것은 네트워크 데이터 장애, 로드 밸런싱, 지연 문제, 오류 처리, 모니터링, 로깅 등을 처리해야 한다는 것을 의미합니다. 심지어 Go 언어로 작성된 Twerp라는 서비스 통신 프레임워크를 만들기도 했습니다. 또한 2017년과 2019년에 걸쳐 프런트엔드 전체를 jQuery와 Emberjs에서 React 앱으로 재작성했습니다.
이러한 모든 마이그레이션이 진행되는 동안 다른 팀은 비디오 스트리밍을 최대한 실시간으로 느끼도록 만드는 데 매진했습니다. 비디오 스트리밍은 그 자체로도 어렵지만, 저 지연 비디오 스트리밍은 훨씬 더 어렵습니다. 저지연이란 스트리머 와 시청자가 거의 실시간으로 상호 작용할 수 있음을 의미합니다. 30~50초의 지연이 있는 스트림은 5초 이하의 지연이 있는 스트림만큼 재미있고 상호 작용적이지 않습니다. 스트림을 시작하면 비디오는 Twitch 서버로 직접 전송되는 것이 아니라 Twitch의 여러 PoP(Point of Presence, PoP) 중 하나에 업로드됩니다. 그런 다음 PoP에서 Twitch 서버(원본 데이터 센터라고도 함)로 업로드됩니다. PoP는 Twitch가 전 세계 ISP(인터넷 서비스 제공업체)의 데이터 센터에 배포하는 장비입니다. 트위치의 전용 네트워크( 백본 네트워크라고도 함)에 연결되어 있어 공용 인터넷을 사용하는 것보다 훨씬 빠른 속도로 동영상을 업로드할 수 있습니다. 동영상이 오리진 서버에 도착하면 트랜스코딩 과정을 거치는데, 이는 C, C++, Go 언어로 구현되는 매우 연산 집약적인 작업입니다.
트랜스 코딩이란 동영상을 다양한 형식과 화질로 변환하여 모든 종류의 기기와 연결 환경에서 재생할 수 있도록 하는 것을 의미합니다. 트랜스코딩이 완료되면 다양한 형식과 화질의 동영상이 백본 네트워크를 통해 PO PCE(오리진 서버 센터)로 다시 전송됩니다. 전 세계 사용자는 PO PCE에서 동영상을 다운로드하여 시청할 수 있습니다. 초기에는 실리콘 밸리에 있는 단 하나의 오리진 데이터 센터가 전 세계의 모든 동영상 스트림을 처리했지만, 현재 트위치는 모든 대륙에 오리진 서버를 보유하고 있습니다. 서버 수가 늘어남에 따라 발생하는 복잡성을 처리하기 위해 인텔리전스라는 시스템을 개발했습니다. 스트리머가 PO에 동영상을 업로드하면 먼저 모든 PO PCE에서 실행되는 인텔리전스 미디어 프록시 프로그램에 도달합니다. 인텔리전스 미디어 프록시는 인텔리전스 라우팅 서비스라는 다른 프로그램에 스트림을 어떤 오리진 데이터 센터로 보내 처리해야 하는지 문의하여 답변을 받습니다. 지능형 라우팅 서비스는 Capacitor라는 다른 프로그램을 사용하여 어떤 데이터 센터가 온라인 상태이고 정상적으로 작동하는지 확인합니다.
또한 다른 프로그램을 사용하여 백본 네트워크와 링크의 가용성 및 사용 가능 여부를 확인합니다. 어떤 Origin이 온라인 상태이고 과부하가 걸리지 않았는지, 그리고 백본 네트워크의 상태를 파악하여 라우팅 서비스는 비디오 처리에 가장 적합한 대기 데이터 센터를 선택합니다. 이 모든 것은 AWS에서 실행됩니다. Twitch 비디오 스트리밍, Twitter Spaces 오디오 룸 또는 Zo와 같은 화상 통화 서비스를 구축하려는 개인 개발자나 소규모 스타트업 팀에게 적합합니다. POP를 배포하고 ISP와 협상해야 한다는 생각은 다소 부담스러울 수 있습니다. 그래서 저는 팀원이 5명 미만이고 월 매출이 1만 달러 미만인 스타트업이라면 완전히 무료로 사용할 수 있는 새로운 Stream 비디오 및 오디오 SDK 사용 방법에 대한 간단한 튜토리얼을 제공하고자 합니다. 이전에 멕시코에 있을 때 Streams 채팅 SDK에 대한 영상을 제작했는데, 당시 Streams의 사전 구축된 UI 실시간 구성 요소를 사용하여 Slack과 같은 서비스를 얼마나 쉽게 복제할 수 있는지 보여드렸습니다.
이제 Streams에서 사전 구축된 UI 구성 요소가 포함된 비디오 및 오디오 SDK를 출시했습니다. Streams SDK는 거의 복잡한 과정 없이 실시간 오디오 및 비디오 환경을 구축하는 데 사용됩니다. React, iOS, Android, React Native, Flutter, JavaScript, 심지어 Unity에서도 사용 가능하며, Streams 백엔드는 Go 언어로도 실행됩니다. 참고로 Streams SDK를 사용하여 Twitch와 같은 서비스를 구현하는 방법은 다음과 같습니다. 먼저 API 키와 시크릿을 사용하여 스트림 클라이언트를 초기화합니다. 그런 다음 ID와 이름만으로 사용자를 등록합니다. ID와 이름은 일반적으로 데이터베이스에서 가져옵니다. 사용자 ID를 사용하여 토큰을 생성하고, 통화 유형( 기본값인 1: 1 통화, 그룹 통화, 오디오 룸, 라이브 스트림 등)과 스트림 이름을 선택하여 통화를 초기화합니다. 통화를 생성하고 스트리머 사용자가 통화를 생성했음을 알린 후, go live 메서드를 호출하여 스트림을 공개합니다.
마지막으로 스트림의 RTMP URL을 가져와 토큰과 함께 사용자에게 제공합니다. 스트리머는 해당 URL과 토큰을 복사하여 사용하는 스트리밍 소프트웨어에 붙여넣고 스트리밍을 시작하여 다른 사용자에게 스트림을 보여줄 수 있습니다. React와 미리 만들어진 컴포넌트를 사용하는 방법도 있습니다. 컴포넌트와 기본 CSS를 가져오기만 하면 됩니다. 익명 사용자를 사용하여 스트림 클라이언트를 초기화하고 미리 만들어진 컴포넌트를 사용하여 화면을 렌더링합니다. Coe를 사용하면 다음과 같은 결과가 나옵니다. UI는 이미 시청자 카운터, 시간 표시, 전체 화면 버튼 등 다양한 기능을 갖추고 있습니다. 또한, 미리 만들어진 구성 요소를 활용하여 통화 참여자 표시, 통화 제어, 통화 레이아웃 변경, 권한 알림, 반응, 권한 요청 등 더 많은 기능을 추가할 수 있습니다. 이보다 더 쉬울 순 없습니다! 아래 링크를 클릭하여 Stream에 가입하고 매달 100 크레딧을 무료로 받으세요. 항상 시청해 주셔서 감사합니다. 이 영상을 후원해 주신 Stream과 이 영상 제작에 참고 자료로 사용한 다섯 개의 기사를 작성해 주신 Twitch 엔지니어분들께도 감사드립니다.
구독 부탁드립니다. 안녕히 계세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 YouTube 노마드 코더 (개발)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기