로컬-퍼스트 앱이 대중화되지 않은 이유는 무엇인가?
(marcobambini.substack.com)- 로컬-퍼스트 앱은 빠른 반응 속도와 기본적인 프라이버시 보장을 약속하지만 실질적으로 오프라인 지원 구현이 매우 어렵다는 한계가 존재함
- 가장 큰 이유는 동기화의 복잡성 때문이며, 여러 기기에서 동시에 데이터를 변경하면 결과적으로 정확히 동일한 상태로 수렴해야 한다는 문제점이 발생함
- 시간순서 불확실성과 충돌이라는 두 가지 큰 기술적 과제가 있음
- 이 문제를 해결하기 위해 Hybrid Logical Clocks(HLCs) 와 CRDTs와 같은 분산 시스템 설계를 적용하는 방법이 필요함
- SQLite 기반 확장 기능을 활용함으로써 신뢰성 높고 간단한 동기화 아키텍처를 제공할 수 있으며, 이는 모든 플랫폼에서 활용 가능함
오프라인-퍼스트 앱의 약속과 현실
- 오프라인-퍼스트 앱은 즉각적인 반응, 기본 프라이버시 보장, 불안정한 네트워크 환경에서도 로딩 대기 없이 사용 가능함을 표방함
- 실제로는 대부분의 앱들이 오프라인 지원을 제대로 구현하지 못하며, 대다수는 변화를 로컬에 임시 저장한 후 나중에 네트워크 연결 시 전송하는 방식만 채택함
- 이런 구현은 신뢰성이 떨어지며, 결국 "변경사항이 저장되지 않을 수 있음"과 같은 경고 메시지로 이어짐
동기화의 근본적인 어려움
- 로컬-퍼스트 앱을 만들 때는 필연적으로 분산 시스템을 구축하게 됨
- 여러 기기가 오프라인 환경에서 서로 독립적으로 데이터를 변경할 수 있고, 나중에 다시 연결되었을 때 동일한 상태로 정확히 수렴해야 함
- 이를 위해서는 두 가지 큰 도전 과제가 존재함
- 이벤트의 순서 불확실성
- 동일 데이터에 대한 충돌
1. 이벤트 순서 불확실성
- 여러 기기에서 이벤트가 서로 다른 시점에 발생하며, 순서에 따라 상태가 달라질 수 있음
- 예시: A 기기는 x=3으로 설정, B 기기는 x=5로 설정 → 오프라인에서 각각 변경한 후 동기화 시 서로 다른 결과 발생 가능성
- 기존 중앙 집중형 데이터베이스는 강력한 일관성으로 해결하지만, 이는 글로벌 동기화가 필요해 로컬-퍼스트 시스템에는 맞지 않음
- 최종적으로는 이벤트별로 적절한 순서를 동적이고 분산된 환경에서도 확정해야 함, 중앙 시계 없이 순서를 정하는 방법이 필요함
Hybrid Logical Clocks(HLCs)의 도입
- Hybrid Logical Clocks(HLCs) 는 개별 기기 간에 이벤트 순서를 실질적으로 합의할 수 있게 해 주는 단순하면서 효과적인 알고리듬임
- HLC는 물리적 시간 정보와 논리적 카운터를 결합하여 사용함
- 예시로:
- A 기기가 10:00:00.100 시각에 이벤트를 기록, HLC는 (10:00:00.100, 0)
- 메시지를 받은 B 기기는 자신의 시계가 느리더라도, HLC를 (10:00:00.100, 1)로 올림
- 이로 인해 두 기기의 물리적 시계 차이와 상관없이 정확한 이벤트 순서 확정 가능
2. 충돌 문제
- 올바른 순서 적용만으로는 충분하지 않고, 서로 다른 기기에서 동일 데이터를 독립적으로 수정할 경우 충돌이 필연적으로 발생함
- 대부분의 시스템은 개발자가 충돌 해결 코드를 수동으로 작성하도록 요구하지만, 이는 오류 발생 위험과 관리 부담을 초래함
CRDTs의 활용
- Conflict-Free Replicated Data Types(CRDTs) 를 적용하는 것이 가장 좋은 방법임
- CRDTs는 어떤 순서로 동기화해도, 또는 중복 적용해도 각 기기 상태가 최종적으로 항상 동일해짐을 보장함
- 가장 단순한 CRDT 전략은 Last-Write-Wins(LWW) 임
- 각 업데이트에 타임스탬프를 부여
- 동기화 시 더 최신 타임스탬프의 값이 선택됨
SQLite의 장점
- 로컬-퍼스트 앱을 구축할 때는 신뢰성 높고 가벼운 로컬 DB가 필수이며, SQLite가 최적의 선택임
- SQLite 기반 프레임워크 확장으로 동기화 기능을 구현하면 다음과 같은 이점이 있음
- 메시지 적용은 단순: 현재 값 조회 → 신규 타임스탬프가 더 최신이면 덮어쓰기 → 그렇지 않으면 무시
- 이 방식은 동기화 순서와 무관하게 전 기기에서 상태 수렴성 보장
아키텍처의 의의
- 이 구조는 단순하고 신뢰성 높은 동기화를 실현함
- 수 주 동안 오프라인 상태에서도 데이터 유실 없는 신뢰성
- 항상 최종 상태로 수렴하는 결정론적 특성
- 무거운 의존성 없는 경량 SQLite 확장만으로 해결
- iOS, Android, macOS, Windows, Linux, WASM 등 모든 주요 플랫폼 지원
개발자를 위한 제언
- 단순한 요청 큐로 오프라인 모드 지원을 '흉내' 내는 방식을 지양할 필요
- 이벤트얼 컨시스턴시 개념을 받아들이고, HLC 및 CRDT와 같은 입증된 분산시스템 기술을 활용할 필요
- 크고 복잡한 프레임워크 대신 작고 의존성 없는 구조 추구가 바람직함
- 결과적으로 앱은 즉시 실행, 오프라인 사용 가능, 기본 프라이버시 보장 등의 장점을 누릴 수 있음
오픈소스 SQLite-Sync 참고 안내
- 프로덕션에서 즉시 쓸 수 있는, 크로스플랫폼 오프라인-퍼스트 엔진에 관심 있다면, 오픈소스 SQLite-Sync 확장 참고 가능
Hacker News 의견
- CRDT(Conflict-Free Replicated Data Types)를 솔루션이라고 하지만, 실제로 직관적 유저 기대치와 일관된 비즈니스 로직을 맞추는 CRDT 모델을 만드는 건 정말 어렵고, 데이터 모델을 메시지 뭉치로 바꾼 뒤 실제 상태로 계속 재구성해야 해서 엄청난 골칫거리임
- 새로운 웹 표준으로 BRAID라는 이니셔티브가 있음. 이건 웹 상태 동기화 표준을 지향해, 운영 변환(OT)과 CRDT 기술을 HTTP에 적용해 본질적으로 더 인간과 기계 모두에게 친화적인 동기화 웹을 만들려는 것임. Braid는 네트워크 성능을 높이고, 네이티브 P2P‧협업 편집‧로컬-우선 웹앱 개발을 지원함. 관련 링크는 BRAID 미팅, Braid HN 토론, RESTful API 토론, Braid HTTP 설명글임
- CRDT 얘기는 마치 만능 해결책처럼 나오지만, 실제로는 자동 병합이 쉬운 것만은 아님. 기술적으로 마지막 작성자가 승리하는 알고리즘도 CRDT로 볼 수 있지만 복잡한 텍스트 병합에서 유저 의도와 기대치를 모두 존중하려면 거의 불가능에 가까운 난제임. 심지어 일부 상황에서는 CRDT로 병합을 시도하는 게 오히려 잘못된 접근일 수도 있음. 예를 들면 회의실 예약할 때 두 명이 동시에 같은 방에 예약한다면, 알고리즘이 아니라 사용자가 직접 충돌을 인지하고 해결하도록 해야 함
- 겁 많으면 도전하기 힘든 영역임에 동의함. 용기 없는 사람을 위한 “CRDT 없는” 대안도 있는데, 관련 내용은 여기 참고 바람
- 우리 팀은 로컬-우선 앱을 만들면서 충돌 상황을 그냥 무시하는 방법을 씀. 마지막 변경이 이기는 방식임. 대부분의 충돌은 사소하거나(감사 로그 정도로 쉽게 해결 가능), 애초에 자동으로는 풀 수 없는 경우가 많음. 예를 들어 오프라인 지원되는 태스크 트래커에서 두 명이 동시에 같은 작업을 시작하는 경우는 비즈니스 프로세스로 따로 처리해야 함
- 예전에는 거의 모든 소프트웨어가 로컬-우선이었고, 그게 당연했음. 하지만 요즘은 세상이 전적으로 통제와 이윤 최적화로 움직이고, 그 결과 사람들이 더 자주 피해를 입는 구조가 되어버림. 불만이 생겨도 대체제가 딱히 없기 때문임
- 예전에 온프레미스, 직접 호스팅 제품을 만들던 시절, 가장 큰 고객 불만은 클라우드 옵션이 없다는 점이었음. 대부분의 회사는 직접 호스팅을 원치 않고, 차라리 월정액을 내고 다른 곳에 맡기는 걸 선호함. 클라우드 서비스 수요가 실제로 매우 크다는 점을 HN이 과소평가하는 것 같음
- “사람들이 더 당하지 않는 서비스를 원하면 그걸로 돈을 벌 수 있을 것”이란 주장은 경제학적으로 맞지 않음. 문제는 사람들이 실제로 피해를 어느 정도 감내하고 있다는 것임. 만약 교육이나 리스크 인식이 더 높아진다면 달라질 수도 있겠지만, 그건 엄청 풀기 힘든 숙제라고 생각함
- 대안으로는 FOSS(오픈소스 소프트웨어)를 생각할 수 있음
- 앱들이 모든 콘텐츠를 온라인에만 의존하지 않길 바람. Tesla GPS도 이미 받은 타일을 캐시하지 않아 오프라인 시 지도에 아무것도 안 나옴. Peacock, Kanopy 같은 앱 역시 미디어 리스트나 렌더된 객체 자체를 기기에 남겨두지 않음. 디바이스에 이미 95%의 콘텐츠가 있는데, 이를 적극적으로 활용하길 바람. UI를 dirty로 표시하며 비동기 저장 성공을 기다리면 됨. 오프라인 앱 설계에 대해 큰 변화를 요구하지 않아도 더 나은 습관만 있으면 대부분의 문제는 쉽게 해결 가능함
- API 응답에 Cache-Control을 제대로 사용하고 네트워크 계층에서 준수하게 해서 많은 문제를 해결함. 이렇게 하면 서버에서 캐시 수명을 바꿔도 앱 업데이트 없이 바로 적용할 수 있음
- 구글맵은 오프라인 맵을 수동으로 영역 선택해 다운로드할 수 있고, 여러 구역 동시 캐시도 가능함. 국립공원 방문할 때 오프라인으로 잘 써봤음
- “앱 설계 변화를 안 줘도 된다”는 주장에, 업체들은 실제로 더 많은 데이터를 모으는 게 목적이라 생각함. 예를 들어 애플도 오프라인 맵을 제공했지만 일부러 데이터를 만료시켜 유저를 자사에 종속시키려 함. Tesla(혹은 Google) 지도 타일 역시 숨은 의도가 있다고 추측함
- 앱의 로컬-우선성이나 분산성 같은 “정치적으로 핫한” 이슈에 집중하다가 정작 사람들이 정말 원하는 핵심 가치를 놓치는 사례가 많음
- Immich로 전환하며 셀프 호스팅 때문에 포기하는 줄 알았지만, Apple이나 Google보다 훨씬 나음에 놀람. 유니콘처럼 보기 힘든 제품임
- 로컬-우선 앱이 인기 없는 건 결국 경제적인 문제라고 생각함. SaaS나 광고 기반 모델은 확고한데, 로컬-우선 앱은 수익성이 현저히 떨어짐. 이 모델을 선호하는 사람들은 데이터 주권, 종단간 암호화, 오프라인 사용 등 기존 수익모델과 상충하는 특성을 중요하게 여김. 결국 오픈소스 커뮤니티의 열정에 기대는 수밖에 없음
- 이제는 “돈+데이터”를 내거나 “광고 시청”만이 가능한데, 진짜 현금만 내고 데이터는 보호받는 모델은 배제된 현실임
- 나도 Relay라는 로컬-우선 앱을 만들고 있는데, Obsidian에 구글독스식 협업을 붙여줌. 비즈니스 모델이 독특하다고 생각함. 서비스는 “글로벌 아이덴티티 레이어”와 “Relay Server"(오픈소스/셀프호스팅)로 나누어, 사용자가 문서 내용에 대해 완전히 제어할 수 있음. 간단한 싱글사인온 및 권한관리를 제공하고, AI·AI Safety 분야 기업이나 컴플라이언스가 중요한 회사에 특히 관심 받는 중임. 링크는 Relay.md임
- 내가 주변에서 자주 보는 현상은, 살 때 구독제만 제공해서 결국 안 사는 소비자임. 일단 사서 나중에 쓰고 싶은데, 제한 조건(할인 기간, 재방문시 가격 인상 등) 때문에 아예 구매 의욕이 꺾임. 이게 최적의 비즈니스 모델이 아닐 거라 생각함
- 복제 데이터 구조가 문제가 아니라 생각함. 싱글플레이어 게임처럼 완전한 로컬-우선인데도 런처를 통해 인터넷 연결을 요구하는 경우가 많음
- 로컬-우선 앱은 복잡성 문제도 심각함. 온갖 기기, 환경에서 다 돌아가게 해야 하고, 클라우드-우선 앱은 서버에서만 단일 환경에 맞춰 돌리면 되니 상대적으로 쉽고 유지비도 적음
- 과거에는 데스크톱‧모바일 소프트웨어가 오히려 이상한 예외인 듯 다뤄지지만 여전히 매우 흔한 소프트웨어 배포 방식임. 반면 브라우저에서 로컬-우선 기능을 구현하려고 하면, 호스트 시스템과의 연동 문제 등 브라우저의 단점만 떠안게 됨
- 혹시 내가 뭔가 놓친 건지 모르겠지만, 일반적으로 “로컬-우선” 앱이 평범한 게 아닌가 생각함. 대부분 유저들도 오프라인 기반 앱을 많이 씀. 혹시 “로컬-우선 웹 앱"을 뜻한다면 그 말이 더 맞을 것 같음. 사실 “로컬-우선 웹 앱" 자체가 모순적인 컨셉임
- 대부분의 앱이 (직접적으로 비용을 내고 사용하는) 로컬-우선 형태인지 되묻고 싶음. 게임을 빼면 이제는 그런 회사가 거의 없는 것 같고, 심지어 싱글플레이 게임도 DRM, 반부정행위, 업데이트 등 핑계로 인터넷 요구하는 게 현실임
- 여기서 말하는 ‘로컬-우선’이란, 클라우드 저장이 아니라 애초에 로컬 데이터를 기본으로 두고, 클라우드와 동기화를 지원하는 앱을 의미함
- 오프라인-우선 앱도 끊기는 네트워크 연결에서 로딩 스피너가 돈다는 점에서는 다르지 않음. 예를 들어 Google Docs는 문서가 최신인지 확인하려다 붙잡히고, Airplane Mode로 강제로 끊어야만 즉시 열림. Spotify도 저장된 플레이리스트조차 온라인 부가 정보를 받으려다 멈춤. 결국 불안정한 연결은 오프라인 앱 개발에 최대 골칫거리임. 앱들이 항상 한 번이라도 더 클라우드 데이터에 접근하려고 하기 때문임
- 아티클의 솔루션도 클로즈드 클라우드 오퍼링에 잠겨 있음. Firebase처럼 그 자체는 괜찮지만, 그 사실이 명확히 표기되지 않고 “단지 sqlite 확장”이라는 식 표현 뒤에 상업 클라우드만 지원되는 점이 아쉬움. Powersync나 ElectricSQL 같은 벤더는 적어도 이 사실을 투명하게 밝히고, Powersync는 자체 호스팅도 가능하게 해 줌
- 로컬-우선 개념이 개발자 도구에 적용될 수 있는지 헷갈리긴 함. SQLite-sync류의 툴로 현지 저장 모델 기반 소프트웨어를 만드는 게 가능할지 검토 필요성 느낌. ElectricSQL은 셀프호스팅 가능하고, 내 “sqlite sync” 도구 리스트도 계속 업데이트해야 할 듯. 관련 링크는 local-first 원글, SQLSync, SQLiteSync, SQLite-Sync임
- 나는 더 많은 로컬-온리, 셀프호스트 앱이 필요하다고 생각함. 혹은 연합(Federated) 구조도 좋다고 봄. 네트워크 인프라가 그동안 장애물이었다고 느끼는데 Tailscale 같은 솔루션이 등장하면서 이런 앱이 크게 쉬워질 것임
- 프레젠테이션 소프트웨어를 만드는 중인데, 로컬에서 반드시 잘 돌아야 하지만 동시에 어디서든 접속 가능해야 함. 이 두 가지를 동시에 만족시키는 게 생각보다 어려움. 하지만 기술이 발전하면서 direct connection이나 WebRTC 등 P2P 구현이 쉬워지는 중임. 실제 제품에 녹이고 테스트 하는 건 아직 도전임. 그래도 앞으로 로컬-우선이면서 네트워킹도 뛰어난 소프트웨어가 점점 늘어날 것 같음. 오픈소스임. 자세한 정보는 프로필 참고 바람
- 나도 요즘 이쪽을 재밌게 탐구 중임. 자세한 글은 여기에서 볼 수 있음. 새로운 방식의 앱 빌드가 꽤 즐거움