본문 바로가기

개발이야기

Rewriting the Messenger codebase for a faster, smaller, and simpler messaging app

 

 

이 글은 Engineering at Meta의 Project LightSpeed: Rewriting the Messenger codebase for a faster, smaller, and simpler messaging app  글을 번역한 글입니다. 

 

- 우리는 iOS용 Messenger의 새 버전을 출시하게 되어 기쁩니다. Messenger iOS앱을 더 빠르고, 더 작고, 단순하게 만들기 위해 아키텍처를 재구축하고 전체 코드베이스를 다시 작성했습니다. 이는 회사 전체에서 매우 드문 일입니다. 

- 이전 iOS 버전에 비해 이 새로운 Messenger는 시작 속도가 2배 빠르며 크기는 1/4입니다. 핵심 메신저 코드를 170만줄에서 36,0000줄로 84% 줄였습니다.

- 우리는 가능한 한 기본 OS를 사용하여 이 작업을 수행했습니다. SQLite에서 제공하는 동적 템플릿으로 UI 재사용, SQLite를 범용 시스템으로 사용 및 Messenger와 해당 서버 기능 간의 범용 게이트웨이로 작동하도록 서버 브로커를 구축하는 단계를 포함합니다. 

 

Messenger는 2011년에 처음으로 독립 실행형 앱이 되었습니다. 당시 우리의 목표는 사용자를 위해 가능한 한 기능이 풍부한 경험을 구축하는 것이었습니다. 그 이후로 결제, 카메라 효과, 스토리, GIF, 영상 채팅기능까지 추가했습니다. 그러나 매월 10억 명이 넘는 사람들이 Messenger를 사용하고 있는 상황에서 모든 기능을 갖춘 메시징 앱은 겉으로는 단순해 보이지만 이면에는 훨씬 더 복잡합니다.

 

이러한 모든 기능을 구축, 테스트 및 관리하는데 필요한 백엔드는 앱을 훨씬 더 복잡하게 만들었습니다. 결국 앱의 바이너리 크기는 130MB 이상이었습니다. 그와 많은 양의 코드로 인해 특히 구형 기기에서 앱의 콜드 스타트가 훨씬 느려졌습니다. 그리고 9개의 다른 탭으로 인해 앱을 사용하는 사람들이 탐색하기가 더 까다로워졌습니다. 

 

2018년에는 Messenger 4 출시와 함께 인터페이스를 재설계하고 간소화했습니다. 하지만 우리는 더 많은 것을 하고 싶었습니다. 우리는 처음부터 시작한다면 오늘날 메시징 앱을 어떻게 구축할 것인지 살펴보았습니다.  약 10년 전에 Messenger 개발을 처음 시작한 이후로 무엇이 바뀌었습니까? 꽤 많이, 바뀌었습니다. 실제로 모바일 앱 작성 방식이 근본적으로 바뀌었습니다. 그래서 작년 F8에서 Messenger의 iOS앱을 더 빠르고, 더 작고, 더 간단하게 만들겠다고 발표했습니다. 우리는 프로젝트 LightSpeed라고 불렀습니다.

 

이 새 버전의 Messenger를 빌드하려면 아키텍처를 처음부터 다시 빌드하고 전체 코드베이스를 다시 작성해야 했습니다. 이 재작성을 통해 2011년에 원래 앱이 출시된 이후로 모바일 앱 공간에서 상당한 발전을 이룰 수 있었습니다. 또한, 우리는 그 사이에 우리가 개발한 최첨단 기술을 활용할 수 있었습니다. 오늘부터 앞으로 몇 주에 걸쳐 iOS용 Messenger의 새 버전을 전 세계적으로 출시하게 되어 기쁩니다. 이전 iOS 버전과 비교하여 Messenger는 시작 속도가 2배, 크기는 1/4입니다. 

 

이 새로운 반복을 통해 우리는 Messenger가 앱 구축에 대해 어떻게 생각하는지 재구상하고 새로운 클라이언트 코어와 새로운 서버 프레임워크로 처음부터 시작했습니다. 이 작업은 우리의 최첨단 기술을 발전시키는데 도움이 되었으며 새로운 코드베이스는 향후 10년 동안 지속 가능하고 확장 가능하도록 설계되어 개인 메시징 및 앱 전반의 상호 운용성을 위한 토대를 마련했습니다. 

 

Smaller and Faster

우리는 Messenger가 단순하고 가벼운 유틸리티여야 한다는 전제에서 시작했습니다. 일부 앱은 몰입형입니다. (비디오 스트리밍, 게임). 사람들은 그것을 사용하는데 몇 시간을 보냅니다. 이러한 앱은 많은 저장공간, 배터리 시간등을 차지하며 절충안이 합리적입니다. 그러나 메시지는 보내는 데 1초도 채 걸리지 않는 작은 텍스트 조각일 뿐입니다. 기본적으로 메시징 앱은 휴대전화에서 가장 작고 가벼운 앱 중 하나여야 합니다. 그 원칙을 염두에 두고 우리는 iOS 앱을 훨씬 더 작게 만드는 올바른 방법을 찾기 시작했습니다. 

 

장치 유형이나 네트워크 조건에 관계없이 작은 응용 프로그램을 사용하는 사람이 더 빠르게 다운로드, 설치, 업데이트 및 시작합니다. 작은 앱은 관리, 업데이트, 테스트 및 최적화도 더 쉽습니다. 이 새 버전에 대해 생각하기 시작했을 때 Messenger의 핵심 코드베이스는 170만 라인 이상의 코드로 성장했습니다. 코드의 일부 섹션을 편집하는 것만으로는 충분하지 않습니다.

 

더 작은 앱을 얻는 가장 간단한 방법은 우리가 수년 동안 추가한 많은 기능을 제거하는 것이지만 그룹 화상 통화와 같이 가장 많이 사용되는 모든 기능을 유지하는 것이 중요했습니다.  그래서 우리는 한발 물러서서 지난 10년동안 배운 것과 오늘날 우리 앱에서 사람들이 요구 사항에 대해 알고 있는 것을 어떻게 적용할 수 있는지 살펴보았습니다. 옵션을 살펴본 후 인터페이스를 살펴보고 앱 자체의 인프라를 파헤쳐야 한다고 결정했습니다. 

 

코드베이스를 완전히 다시 작성하는 것은 매우 드문 일입니다. 대부분의 경우 앱을 다시 작성하는 데 필요한 엄청난 노력으로 인해 효율성이 실제로 향상되는 경우는 거의 없습니다. 그러나 이 경우 초기 프로토타이핑을 통해 상당한 이점을 얻을 수 있음을 보여주었고, 이는 우리가 이 크기의 앱으로 이전에 몇 번만 수행했던 일을 시도하도록 동기를 부여했습니다. 작은 사업이 아니었습니다. 소수의 엔지니어에 의해 시작되었지만 Project LightSpeed는 최종 제품을 완성하고 전달하는데 궁극적으로 100명 이상의 엔지니어가 필요했습니다. 

 

결국 핵심 메신저 코드를 170만 줄에서 360,000줄로 84% 줄였습니다. 우리는 단순화된 아키텍처와 디자인에 맞게 기능을 재구축하여 이를 달성했습니다. 우리는 대부분의 기능을 유지했지만 시간이 지남에 따라 계속해서 더 많은 기능을 도입할 것입니다. 더 적은 수의 코드 라인은 앱을 더 가볍고 빠르게 만들고 간소화된 코드 기반은 엔지니어가 더 빠르게 혁신할 수 있음을 의미합니다.

 

Simpler

우리의 주요 목표 중 하나는 코드 복잡성을 최소화하고 중복을 제거하는 것이었습니다. 우리는 통합 아키텍처가 전역 최적화를 허용하고 코드를 스마트한 방식으로 재사용할 수 있다는 것을 알고 있습니다. 이 통합 아키텍처를 구축하기 위해 우리는 OS 사용, UI 재사용, SQLite 데이터베이스 활용, 서버로 푸시라는 4가지 원칙을 수립했습니다.

 

Use the OS

모바일 운영 체제는 계속해서 빠르고 극적으로 발전하고 있습니다. 사용자 요구와 경쟁 압력으로 인해 새로운 기능과 혁신이 지속적으로 추가되고 있습니다. 새로운 기능을 구축할 때 OS 위에 추상화를 구축하여 기능 간극을 메우고, 엔지니어링 유연성을 추가하거나, 플랫폼 간 사용자 경험을 만들고 싶은 유혹을 느끼는 경우가 많습니다. 그러나 기존 OS는 종종 필요한 것의 많은 부분을 수행합니다. 렌더링, 트랜스코딩, 스레딩 및 로깅과 같은 작업은 모두 OS에서 처리할 수 있습니다. 로컬 메트릭에 대해 더 빠를 수 있는 사용자 지정 솔루션이 있는 경우에도 OS를 사용하여 글로벌 메트릭에 대해 최적화합니다.

 

UI 프레임워크는 강력하고 개발자 생산성을 높일 수 있지만 끊임없이 변화하는 모바일 OS 환경에 발 맞추기 위해서는 지속적인 유지 관리가 필요합니다. 바퀴를 재발명하는 대신 장치의 기본 OS에서 사용할 수 있는 UI 프레임워크를 사용하여 더 다양한 애플리케이션 기능 요구 사항을 지원했습니다. 이렇게 하면 대규모 맞춤형 프레임워크를 캐시/로드할 필요가 없어져 크기가 줄어들 뿐만 아니라 복잡성도 줄어듭니다. 기본 프레임워크는 하위 프레임워크로 변환될 필요가 없습니다. 또한 코드베이스에 자체 라이브러리를 구축하고 저장하는 대신 JSON 처리 라이브러리를 비롯한 OS 라이브러리를 꽤 많이 사용했습니다

전반적으로 우리의 접근 방식은 간단했습니다. OS가 뭔가를 잘했다면 우리는 그것을 사용했습니다. 프레임워크가 해당 기능을 노출할 때까지 기다릴 필요 없이 OS의 전체 기능을 활용했습니다. OS가 뭔가를 하지 않는다면, 우리는 특정 요구를 해결하기 위해 가능한 가장 작은 라이브러리 코드를 찾거나 작성할 것입니다. 또한 플랫폼 종속 UI 및 관련 도구를 수용했습니다. 모든 플랫폼 간 로직에 대해 우리는 이식성이 높고 효율적이며 빠른 네이티브 C 코드에 내장된 운영 확장을 사용했습니다. 우리는 이 확장을 OS와 같이 전체적으로 차선책이거나 OS에서 다루지 않는 모든 것에 사용합니다. 예를 들어, 모든 Facebook관련 네트워킹은 우리의 확장프로그램에서 C로 수행됩니다. 

Reuse the UI

Messenger에는 동일한 UI 경험의 여러 버전이 있었습니다. 예를 들어, 이 프로젝트 초기에는 40개 이상의 연락처 목록 화면이 있었습니다. 각 화면은 전화 렌더링과 같은 요인에 따라 약간의 디자인 차이가 있었고 가로 모드, 어두운 모드 및 접근성과 같은 기능을 지원하려면 각 화면을 개선해야 했습니다. 이는 우리가 지원하는 수의 두배였습니다. 이것은 많은 뷰의 수를 의미했고 뷰의 수는 Messenger와 같은 앱 크기의 큰 비율을 차지했습니다. 중복을 단순화하고 제거하기 위해 다른 뷰에 대해 동일한 구조를 강제로 재사용하도록 설계를 제한했습니다. 따라서 우리는 기본 뷰의 몇 가지 범주만 필요했으며 다른 SQLite 테이블에 의해 구동될 수 있었습니다.

 

오늘날 메신저에서 연락처 목록은 단일 동적 템플릿입니다. 추가 코드 없이 화면 모양을 변경할 수 있습니다. 누군가가 화면을 로드할 때마다(그룹에 메시지 보내기, 새 메시지 읽기 등) 앱은 적절한 이름, 사진 등을 로드하기 위해 데이터베이스와 대화해야 합니다. 앱 스토어(40) 화면 디자인을 갖는 대신, 데이터베이스는 로드되는 다양한 하위 기능에 따라 다른 빌딩 블록 표시하는 방법에 대한 지침을 보유합니다. 이 단일 연락처 목록 화면은 연락처 관리, 그룹 생성, 사용자 검색, 메시징 보안, 스토리 보안, 공유, 스토리 공유 등과 같은 많은 기능을 지원하도록 확장할 수 있습니다. iOS 세계에서 이것은 이러한 모든 요구를 지원할 수 있는 적절한 유연성을 갖춘 단일 뷰 컨트롤러입니다. 우리의 모든 디자인에서 이 우아한 솔루션을 사용하여 상당한 양의 코드를 제거할 수 있었습니다. 

Use SQLite

대부분의 모바일 애플리케이션은 SQLite를 스토리지 데이터베이스로 사용합니다. 그러나 기능이 유기적으로 성장함에 따라 각 기능은 고유한 저장, 데이터 엑세스 및 관련 비즈니스 로직 구현 방식을 갖게 됩니다. 범용 시스템을 구축하기 위해 데스크탑 세계에서 아이디어를 얻었습니다. 수십 개의 독립적인 기능을 관리하고 각각의 정보를 가져와 앱에 자체 캐시를 구축하는 대신 SQLite 데이터베이스를 모든 기능을 지원하는 범용 시스템으로 활용했습니다. 

 

역사적으로 기능 간에 데이터 공유를 조정하려면 복잡한 맞춤형 메모리 내 데이터 캐싱 및 트랜잭션 하위 시스템을 개발했습니다. 데이터베이스와 UI 간에 이 논리를 전송하면 앱 속도가 느려집니다. 우리는 단순히 SQLite를 사용하고 동시성, 캐싱 및 트랜잰션을 처리하도록 하는 것을 포기하기로 결정했습니다. 이제 어떤 친구가 활성 상태인지 업데이트하는 하나의 시스템을 지원하는 대신 연락처 목록의 프로필 사진 변경 사항을 업데이트하는 다른 시스템을 지원합니다.  수신한 메시지를 검색하기 위한 다른 하나는 데이터베이스의 데이터 요청이 자체적으로 포함됩니다. 모든 캐싱, 필터링, 트랜잭션 및 쿼리는 모두 SQLite에서 수행됩니다. UI는 데이터베이스의 테이블만 반영합니다.

 

이는 로직을 단순화하고 기능적으로 유지하고 앱의 나머지 부분에 대한 영향을 제한합니다. 그러나 우리는 더 멀리 나아갔습니다. 모든 기능에 대해 단일 통합 스키마를 개발했습니다. 메신저 기능 개발자가 이식 가능한 데이터베이스 지향 비즈니스 로직을 작성할 수 있도록 저장 프로시저 기능으로 SQLite를 확장했으며 마지막으로 데이터베이스에 대한 모든 엑세스를 조정하는 플랫폼(MSYS)를 구축했습니다. 대기중인 변경사항, 지연되거나 재시도 가능한 작업, 데이터 동기화 지원을 포함합니다. 

 

MSYS는 우리가 필요로하는 모든 것들을 운영하는 C로 구축된 크로스 플랫폼 라이브러리입니다. 코드를 모두 하나의 라이브러리로 통합하면 모든 것을 훨씬 쉽게 관리할 수 있습니다. 그것은 더 중앙 집중화되고 더 집중적입니다.