클라우드 없이, 여러 기기에서 독서 기록을 동기화하는 방법

by DD
2개월 전
조회수 16

로컬 우선(Local-first) 동기화를 통해 클라우드 의존성을 제거하고, 데이터 미저장 정책(Zero-Retention Policy)을 구현함

mDNS(Multicast DNS)를 활용한 기기 간 자동 검색 및 QR 코드 기반 페어링(Pairing)을 통해 보안을 강화함

Hybrid Logical Clock(HLC)CRDT(Conflict-free Replicated Data Type)를 사용하여 충돌 해결 및 데이터 일관성을 유지함

아웃박스 패턴(Outbox Pattern)mTLS(Mutual TLS)를 적용하여 안정적인 데이터 동기화 및 보안을 확보함

데이터 동기화 아키텍처: 듀얼 레인(Dual Lane) 방식

Merrilin은 데이터 격리 아키텍처(Data Isolation Architecture)를 위해 두 가지 동기화 레인(Sync Lane)을 사용한다. 게스트-피어 레인(Guest-Peer Lane)은 계정 없이 로컬 네트워크에서 직접 동기화를 수행하며, 로컬 SQLite 데이터베이스를 신뢰한다. 반면, 계정-클라우드 레인(Account-Cloud Lane)은 클라우드 PostgreSQL 인스턴스를 중심으로, 아웃박스 패턴(Outbox Pattern)을 통해 안정적인 데이터 전송을 보장한다. 이러한 이중 구조는 데이터 미저장 정책(Zero-Retention Policy)을 유지하면서도 다양한 환경에서 유연한 동기화를 가능하게 한다.

기기 검색 및 페어링: mDNS와 QR 코드

Merrilin은 mDNS(Multicast DNS)를 사용하여 로컬 네트워크에서 기기를 자동으로 검색한다. 기기들은 _merrilin-sync._tcp 서비스 유형으로 자신을 알리고, 다른 기기들의 공고를 수신한다. 페어링 과정은 QR 코드와 6자리 키를 통해 이루어지며, Trust-On-First-Use(TOFU) 방식을 따른다. 이 과정에서 각 기기는 서로의 지문(Fingerprint)과 공유 비밀을 교환하여, IP 주소가 변경되어도 안전하게 연결을 유지한다. 이는 SSH 연결과 유사한 방식으로, 보안을 강화한다.

충돌 해결 전략: HLC와 CRDT

게스트-피어 레인에서는 Hybrid Logical Clock(HLC)을 사용하여 충돌을 해결한다. HLC는 시간 기반의 충돌 해결을 가능하게 하며, 읽기 위치, 주석, 읽기 이벤트, 책 메타데이터, 컬렉션 등 다양한 데이터 유형에 적용된다. 계정-클라우드 레인에서는 Compare-and-Swap(CAS)를 사용하여 버전 기반의 충돌 해결을 수행하며, 서버는 의도를 파악하여 자동 리베이스(Rebase)를 시도한다. 이러한 CRDT(Conflict-free Replicated Data Type) 기반의 충돌 해결은 데이터 일관성을 보장한다.

보안 강화: mTLS와 공유 비밀

게스트-피어 레인에서는 mTLS(Mutual TLS)를 사용하여 기기 간의 안전한 통신을 구현한다. 각 기기는 자체 서명된 X.509 인증서를 생성하고, 페어링 과정에서 서로의 인증서 지문을 저장한다. 모든 동기화 요청은 페어링 시 생성된 공유 비밀로 서명되어, 중간자 공격(Man-in-the-Middle Attack)을 방지한다. 이와 더불어, 요청에는 HTTP 메서드, 경로, 타임스탬프, 논스(Nonce), 요청 본문의 해시가 포함되어, 데이터 변조를 어렵게 만든다.

아웃박스 패턴(Outbox Pattern)을 활용한 안정적인 데이터 전송

Merrilin은 아웃박스 패턴(Outbox Pattern)을 사용하여 클라우드 레인에서 데이터 전송의 안정성을 확보한다. 모든 변경 사항은 로컬 아웃박스에 먼저 저장된 후, 백그라운드 프로세스에 의해 서버로 전송된다. 읽기 위치 업데이트와 같은 우선순위가 높은 데이터는 즉시 처리되며, 페이지 넘김과 같은 빈번한 이벤트는 디바운스(Debounce)를 통해 최적화된다. 네트워크 연결이 불안정할 경우, 아웃박스는 데이터를 보존하고, 앱 재시작 시에도 데이터 전송을 보장한다.

Tracking reading position across devices with local-first sync (no cloud)