웹뷰 이후를 위한 레일 깔기: 당근이 Lynx를 선택한 이유
핵심 내용
당근은 웹뷰의 초기 로딩 한계를 줄이기 위해 Lynx를 화면 단위 렌더링 계층으로 도입했다.
자세히 보기
당근은 웹뷰 화면의 초기 로딩 문제를 해결하기 위해 전체 앱을 새 프레임워크로 교체하는 대신, 기존 네이티브 앱에 점진적으로 결합할 수 있는 Lynx를 선택했다. SSR이나 캐싱으로 로딩을 줄일 수 있지만, 웹 문서와 초기 데이터를 네트워크에서 가져와야 하는 경로 자체는 남기 때문에 사용자가 로딩을 느끼지 않는 실행 환경이 필요했다.
당근이 새로운 기술에 요구한 조건은 다음과 같다.
- 첫 프레임부터 임시 화면이 아닌 실제 제품 UI를 표시할 것
- 기존 네이티브 앱을 유지하면서 화면 단위로 적용할 것
- 프론트엔드 번들을 앱 바이너리와 독립적으로 배포할 것
- 프론트엔드·iOS·Android 엔지니어 각 1명 수준으로 시작할 수 있을 것
- 문제가 생기면 기존 웹뷰로 되돌릴 수 있을 것
당근은 홈 피드와 채팅처럼 핵심 비즈니스 경험을 네이티브 스택으로 유지하고, 웹뷰가 맡아온 일부 화면을 더 빠르게 최적화할 렌더링 계층을 찾았다. Lynx는 React·CSS에 가까운 개발 모델을 제공하면서도 전체 앱 또는 기존 네이티브 화면의 일부 영역에 선택적으로 삽입할 수 있다.
가장 중요한 판단 기준은 JavaScript 실행 성능의 최대 처리량보다 런타임 초기화 비용과 첫 화면 렌더링 과정이었다. Lynx의 메인 스레드 런타임인 **PrimJS(QuickJS)**는 작고 임베드하기 쉬우며 초기화 비용이 낮아, 화면 진입 시 런타임을 준비하고 첫 UI를 표시해야 하는 모바일 환경에 적합했다.
Lynx의 Dual-Thread Architecture에서는 메인 스레드가 첫 화면과 UI 변경을 처리하고, 백그라운드 스레드가 React 컴포넌트 생명주기와 부수 효과를 담당한다. 번들과 초기 데이터가 준비돼 있다면 백그라운드 작업이 끝나기를 기다리지 않고 메인 스레드에서 제품 UI를 바로 그리는 **IFR(Instant First-Frame Rendering)**을 사용할 수 있다.
IFR은 번들과 첫 화면의 핵심 데이터가 동기적으로 준비돼야 한다는 조건을 갖는다. 당근은 이 제약을 바탕으로 번들 사전 다운로드, 초기 데이터의 네이티브 주입, 첫 프레임에 포함할 UI를 제품과 플랫폼 차원에서 설계할 수 있었다.
개발과 배포 측면에서는 Rspeedy를 사용한다. Rspack과 Rsbuild를 기반으로 HMR을 지원해 기존 프론트엔드 도구와 개념을 활용할 수 있으며, Lynx 번들은 CDN에서 제공하고 네이티브 앱이 URL로 가져오도록 구성해 앱 바이너리와 독립적으로 배포한다.
또한 LynxView를 네이티브 View Hierarchy에 화면 전체로 배치하거나 특정 영역에만 삽입할 수 있다. 기존 앱을 다시 작성하지 않고 필요한 영역부터 도입하는 Brownfield 방식이며, 문제 발생 시 기존 웹뷰로 되돌릴 수 있는 점도 선택의 중요한 배경이 됐다.
React Native와 Flutter도 기존 네이티브 앱에 점진적으로 도입할 수 있지만, 당근이 원한 것은 새로운 앱 개발 프레임워크가 아니라 제한된 역할을 수행하는 렌더링 계층이었다. Lynx는 생태계의 범위를 넓히기보다 호스트 앱이 제공할 기능과 운영 책임을 명시적으로 통제할 수 있다는 점에서 당근의 요구에 더 가까웠다.
이 한국어 요약은 AI가 자동으로 만들었습니다. 원문의 주장과 맥락은 원문에서 확인해 주세요. 저작권은 원저작자에게 있습니다.