작년 9월, 우리는 iOS 및 Android용 Proton Mail의 주요 업데이트를 출시했습니다.

표면적으로 새로운 앱은 현대적인 디자인, 더 나은 성능, 오프라인 기능을 제공하지만, 눈에 보이는 것보다 훨씬 더 많은 것이 있습니다. 이면에서 이 앱들은 새로운 기술 스택 위에서 Proton Mail을 완전히 새로 작성한 것으로, 내부적으로 엔지니어링 트랜스포메이션(Engineering Transformation)이라는 이름으로 불리는 프로젝트입니다. 새로운(novel)이라는 용어는 의도적인 것입니다. 우리가 아는 한, 선택된 기술이 기존 프로덕션 어플리케이션의 맥락에서 사용된 것은 이번이 처음이기 때문입니다.

이 기사는 우리 팀이 이 혁신을 이루기 위해 겪은 매혹적인 여정을 조명하고, 그 과정에서 커뮤니티가 우리에게 물었던 몇 가지 질문에 답하는 것을 목표로 합니다. 무엇보다도, 그 배경에는 현상 유지를 바꿔야 한다는 필요성이 있었습니다.

모든 것이 시작된 계기

상황이 변해야 한다는 깨달음은 2023년 10월 어느 금요일 저녁에 찾아왔습니다. 놀라울 정도로 명확하게 구체화되었지만, 갑작스러운 것은 아니었습니다. 이는 사용자의 Mail 및 캘린더 모바일 제품 경험에 영향을 미치는, 겉보기에 관련 없어 보이는 문제들의 공통분모를 찾기 위해 보낸 몇 달간의 정점이었습니다.

지나치게 단순화할 위험이 있지만, 불만 사항을 세 가지 영역으로 요약할 수 있습니다:

  • 품질: Mail iOS 및 Mail Android를 개별적으로 보았을 때, 품질과 성능 면에서 기대에 미치지 못했습니다.
  • iOS와 Android 간의 기능 격차: 일부 기능은 한 플랫폼에서만 사용할 수 있었고, 다른 플랫폼에서 언제 따라잡을 수 있을지 불투명했습니다.
  • 엔지니어링 속도: 주요 업데이트와 오랫동안 기다려온 기능이 두 플랫폼 모두에 적시에 제공되지 않았습니다.

일부 문제는 모바일 너머로 확장되었으며, 이에 답하려면 기술 도메인에서 조직적 확장, 특히 빠르게 성장하는 기술 전원이 켜질 때의 매혹적인 문제 공간으로 이야기를 돌려야 합니다. 그러나 모바일 생태계의 취약성은 기술과 아키텍처에 깊이 뿌리를 두고 있었습니다.

모바일 엔지니어링 확장

모바일 엔지니어링을 확장하는 것은 백엔드 및 웹 팀을 확장하는 것과는 의미 있게 다른 고유한 과제들을 수반합니다. 이러한 차이는 플랫폼 파편화와 모바일 생태계의 운영 현실에서 비롯됩니다. 모바일 팀은 일반적으로 다양한 운영 체제와 기기(전화, 태블릿, 때로는 웨어러블)에 걸쳐 여러 플랫폼을 지원해야 합니다. iOS와 Android는 각각의 프로그래밍 언어, 프레임워크, 도구를 가지고 있어, 여러 팀, 중복된 코드베이스, 플랫폼별 작업과 제품 관련 작업 간의 끊임없는 절충 등 많은 중복 노력이 발생합니다. 제품 제공 사항을 동기화하여 유지하려면 막대한 양의 조정이 필요합니다.

업계 전반의 도전 과제는 Proton에게 특히 심각했습니다. Mail 및 캘린더와 같은 기능성 앱은 본질적으로 시장에 나와 있는 대부분의 모바일 어플리케이션보다 더 복잡합니다. 여기에 종단간 암호화를 처리하는(handle) 데 필요한 클라이언트 로직의 추가 계층을 더하면, 특히 “두꺼운” 클라이언트가 됩니다. 과거에 Android 팀은 더 나은 품질 표준을 위해 Mail을 재작성하느라 바빴는데, 이는 18개월의 대부분을 소요한 투자였습니다. iOS 또한 캘린더는 말할 것도 없고 아키텍처 재설계가 절실했습니다. 중복 비용은 우리의 모든 엔지니어링 자원을 잠식하고 있었고, 같은 방식을 반복해서는 성공할 수 없다는 것이 명확해졌습니다(clear).

갇혀 있다는 것을 인식하는 것의 가장 좋은 점은 현재의 현상 유지라는 제약에서 벗어나 생각하게 만드는 강제 요인이 된다는 것입니다. 우리를 여기까지 오게 한 선택과 약속의 부담에서 벗어나 새로 시작할 수 있다면 무엇을 할 것인가? 성공적인 기업들이 지난 10년 동안 이 문제를 어떻게 해결했는지(close??) 자세히 살펴보면, 그들이 가능한 두 가지 전략 중 하나만 따랐다는 것을 알게 됩니다:

  1. 그들은 문제에 돈을 쏟아부었습니다. 높은 운영 비용을 끝없는 투자와/또는 막대한 수익의 조합으로 상쇄하며 더 큰 팀을 구축했습니다. 이는 Proton의 VC 없는 비즈니스 모델에서는 선택 사항이 아니었습니다. 우리는 광고 기반, 투자자 지원 경쟁업체의 지출과 경쟁할 수 없습니다.
  2. 그들은 낭비를 없애기 위해 앱을 리엔지니어링했습니다. 즉, 가능한 한 공유(shared) 코드베이스를 사용하여 앱을 구축했습니다.

옵션 1은 시작조차 할 수 없었기에, 앞으로의 경로(path)는 정해졌습니다.

목적을 위한 수단: 올바른 기술 스택 선택

다음 단계는 실제로 작업을 수행할 수 있는 기술 스택을 선택하는 것이었습니다.

지난 15년 동안 크로스 플랫폼 모바일 개발은 HTML5, Xamarin, React Native, Flutter, Kotlin Multiplatform 등 “천편일률적인” 솔루션들로 넘쳐났습니다. 각각은 네이티브 개발을 완전히 대체하겠다는 동일한 약속을 가지고 도착했습니다. 실제로 대부분은 완전히 실패하거나 좁게 제한된 문제 공간 내에서만 성공했습니다. 플랫폼 차이를 사라지게 만드는 보편적인 추상화는 없습니다. 대규모 모바일 어플리케이션을 출시하고 유지 관리해 본 사람이라면 누구나 이를 알고 있습니다. 유일하게 신뢰할 수 있는 전달(forward) 방법은 도구 트렌드에서 앞(forward)으로가 아니라 구체적인 요구 사항에서 역으로 작업하는 것입니다.

우리는 그 최종 목표를 선택된 솔루션이 충족해야 하는 일련의 타협할 수 없는 요구 사항(1)으로 변환하고, 평가 과정 전반에 걸쳐 이를 지침 프레임워크로 사용했습니다:

  1. 비용 및 일정: 스택은 iOS 및 Android 전반에 걸쳐 Proton Mail을 출시, 유지 관리 및 발전시키는 데 필요한 비용과 시간을 실질적으로 줄여야 했습니다.
  2. 사용자 경험: 네이티브에 가까운 성능과 상호 작용 품질을 보존해야 했습니다. 그 미만은 시작조차 할 수 없습니다.
  3. 전략적 미래 대비: 솔루션은 수명이 길어야 했습니다. 우리는 로드맵을 다른 공급업체의 지속적인 지원(support)에 의존하게 만드는 제3자(third-party) 프레임워크를 피하려고 의도적으로 노력했습니다.

처음 두 제약 조건 사이의 긴장은 업계 버전의 성배입니다: “네이티브 어플리케이션의 성능과 사용자 경험을 제공하는 크로스 플랫폼 솔루션.”

우리는 당시 지배적인 크로스 플랫폼 프레임워크였던 React Native나 Flutter가 이 기준을 충족할 수 있을지에 대해 처음부터 회의적이었습니다. 그럼에도 불구하고 우리는 Mail의 메시지 목록 보기의 개념 증명 구현을 구축하여 그 회의론을 검증했습니다.

React Native는 빠르게 한계를 드러냈습니다. 대규모 데이터세트를 스크롤할 때 인터프리터 실행 모델의 비용이 고통스러울 정도로 분명했습니다. Flutter는 더 나은 성능을 보였지만, UI는 특히 iOS에서 눈에 띄게 비네이티브(non-native)로 남아있었습니다. 더 중요한 것은 Flutter가 Google이 통제하는 독점 프레임워크라는 점인데, Google은 사내 기술을 포기한 이력(새 창)이 있고 최근 Flutter 팀의 상당 부분을 해고했습니다. 장기적인 보안 및 신뢰성 보장이 필요한 제품의 경우, 그러한 수준의 외부 의존성은 용납할 수 없었습니다.

Kotlin Multiplatform이 다음 후보였습니다. 이는 특히 깊은 Android 전문 지식을 보유한 조직(organizations)에 매력적인 옵션이지만, 궁극적으로 우리의 사용 사례에는 미치지 못했습니다. 공유(shared) UI 계층의 부재, 성숙도에 대한 의문, 실행 모델로 인한 추가적인 오버헤드가 이점보다 컸습니다.

이 시점에서 결론은 명확(clear)했고 우리의 초기 직관과 일치했습니다. 원하는 결과에 지속적으로 근접하는 유일한 아키텍처는 의도적으로 혼합된 스택입니다. 각 플랫폼의 네이티브 UI – Android의 Jetpack Compose, iOS의 SwiftUI – 와 고성능 저수준 언어로 작성된 공유(shared) 비즈니스 로직 계층의 지원을 받는 것입니다. 이 접근 방식은 실적이 있습니다: Dropbox는 언어의 운영 및 인지 비용으로 인해 2019년에 포기하기 전까지 C++를 사용하여 모바일 플랫폼 간에 비즈니스 로직을 공유(share)한 것으로 유명합니다.

2023년 말까지 Rust는 시스템 프로그래밍 언어 계보의 후계자로 분명하게 떠올랐습니다.

Rust는 C++와 동일한 성능 영역을 차지하지만 역사적 부채가 없습니다. 가비지 컬렉션 없이 강력한 메모리 안전 보장을 제공하고, 컴파일 타임에 스레드 안전 동시성을 강제하며, 크고 유능한 오픈 소스 생태계의 지원(support)을 받습니다. 또한 Rust는 네이티브 모바일 언어인 iOS의 Swift 및 SwiftUI, Android의 Kotlin 및 Jetpack Compose와 깔끔하게 통합되어 UI 계층을 유출(compromise)하지 않고 핵심 로직을 공유(sharing)할 수 있는 실용적인 선택이 됩니다.

이는 위험이 없는 결정은 아니었습니다. 당시에는 Rust 중심 아키텍처로 구축된 대규모 소비자 대면 모바일 어플리케이션(applications)의 사례가 거의 없었고, 팀 내 Rust 경험도 제한적이었습니다.

하지만 의미 있는 혁신은 위험이 낮은 영역에서는 거의 일어나지 않습니다. 진짜 과제는 Rust 자체가 아니라 조직적 관성이었습니다. 입증되고 보수적인 접근 방식에서 명확한(clear) 제약 조건과 엔지니어링 판단에 따른 의도적인 실험으로 전환하는 것이었습니다.

새로운 Proton Mail: 결과 및 배운 점

오늘로 빨리 감기하여 도박이 어떻게 전개되었는지 봅시다.

아래 다이어그램은 Mail 모바일의 아키텍처를 나타냅니다. Rust 코어는 어플리케이션(application)의 비즈니스 로직 전체를 담당합니다. 우리는 Rust의 사용을 일반적인 어플리케이션(네트워킹, 저장공간(storage), 알고리즘 계산)을 넘어 복잡한 탐색 로직 처리까지 확장했습니다. 적절한 예는 메시지(message) 목록의 무한 스크롤을 관리하는 로직입니다. 파격적이지만, 이는 코드(code) 재사용을 최대화(maximizing)한다는 우리의 목표를 달성하는 데 핵심적인 것으로 입증되었습니다. 그 결과, 현재 코드베이스의 거의 80%가 iOS와 Android 간에 공유(shared)됩니다.

아키텍처 다이어그램 제공: Leander Beernaert, 2026
아키텍처 다이어그램 제공: Leander Beernaert, 2026

이것이 더 빠르고 높은 품질의 출시 시간으로 이어졌을까요? 최종 평결을 내리기에는 아직 이르지만, 초기 징후는 매우 고무적이었습니다:

  • 출시 후 2개월 동안 팀은 두 플랫폼(platforms) 모두에서 주간(weekly) 기능(feature) 업데이트(updates) 주기를 관리(maintain)할 수 있었습니다(총 12회의 기능 릴리스).
  • 우리는 플랫폼 간의 기능 격차를 닫기(closed)하여, 방해금지(snooze), 캘린더 RSVP, 다음 메시지로 스와이프와 같이 오랫동안 기다려온 기능을 Android에 가져왔습니다.
  • 이 초기 단계에서도 새로운 코드베이스는 두 플랫폼 모두에서 이전 세대보다 더 안정적인 것으로 입증되었습니다. iOS 충돌률은 0.05%(0.12%에서 감소)인 반면, Android는 역사적 기준선(0.19%)으로 돌아왔습니다. 이는 Rust의 런타임 안정성에 대한 강력한 지지입니다.

지원(Support) 또한 이 접근 방식 하에서 더 효과적으로 확장됩니다. 두 개의 독립적인 코드베이스에 흩어진 약간 다른 로직 결함에서 발생하는 겉보기에 유사한 문제(issues)를 추적하는 것보다 단일 공유 근본 원인을 식별하고 해결하는 것이 종종 더 빠릅니다. 우리는 앱(app)의 오프라인(offline) 기능을 뒷받침하는 로직에 영향을 미치는 범주의 카테고리 동기화 문제를 수정하면서 이전에 작업 가설이었던 것에 대한 경험적 확인을 발견했습니다: 하나의 근본 원인, 하나의 솔루션 — 위 다이어그램에서 버전 7.6.2와 함께 제공된 Rebasing 모듈로 표시됨.

동전의 다른 면?

  • 버그(Bugs)와 회귀는 더 넓은 영향을 미치고 두 플랫폼의 사용자(users)에게 영향을 미칠 가능성이 높습니다. 모든 것을 가질 수는 없지만 종단간(E2E) 테스트에 과도하게 투자하여 위험을 확실히 완화할 수 있습니다.
  • 수평적 기술 분할을 따르는 사용자(user) 대면 솔루션의 경우와 마찬가지로, 지식 사일로를 생성하고 종단간(end-to-end) 사용자 경험에 대한 엔지니어링 집중력을 잃을 위험이 있습니다. 이를 인지하고 의도적으로 위험을 완화해야 합니다. 가장 효과적인 조치는 다음과 같습니다:
    • 기술 계층보다는 기능(features)을 제공하도록 하위 팀을 정렬하십시오.
    • 모바일 엔지니어가 Rust 코드베이스와 네이티브 플랫폼 모두에서 디버그, 지원 및 엔지니어링을 수행할 수 있는 “풀스택”이 되도록 교육합니다.

엔지니어링 트랜스포메이션의 다음 단계

이 프로젝트의 시작부터, 이해관계가 Proton Mail 하나에만 국한되지 않는다는 것이 명확(clear)했습니다. 이 기술 스택을 Proton의 주력 어플리케이션(application)에 성공적으로 적용(applying)하는 것은 항상 더 긴 여정의 첫 번째 단계로 의도되었습니다. 궁극적으로 이 접근 방식이 나머지 모바일 생태계 전체에 배포되는 것을 볼 수 있을 것입니다.

그 시나리오가 이제 펼쳐지고 있습니다. 이 기사를 쓰는 지금, 계정(Account) 및 결제 SDK, 그리고 차세대 Proton Calendar 모바일 앱(apps)이 이 새로운 기술 방향에 맞춰 재작성되고 있습니다.

이는 엔지니어링 트랜스포메이션의 두 번째 물결의 시작을 표시(marks)합니다. 플랫폼(platforms)뿐만 아니라 제품 간에도 구성 요소 재사용을 더 쉽게 만들기 위해 설계된 아키텍처 프레임워크로 기술 청사진을 확장하는 진화입니다. 이 전환은 하루아침에 이루어지지는 않겠지만, 고객이 Proton에 기대하는 원활하게 통합되고 개인정보를 우선시하는 생태계를 구축하는 데 필수적입니다.

(1): Simon Lewis,“다양한 플랫폼에서의 어플리케이션 구현 전략”, 2023.