Skip to main content
← 블로그

모바일과 데스크톱, 실시간으로 동기화검토

VauDium ·

같은 API를 공유하는 두 클라이언트를 SSE로 연결하기까지의 고민 과정.

모바일과 데스크톱, 실시간으로 동기화검토

Fecit은 모바일 앱으로 시작했습니다. 그리고 얼마 전 데스크톱 앱을 만들었습니다. Tauri v2 위에 React + Vite를 올리고, 모바일과 같은 API 서버를 바라보게 했습니다.

앱이 두 개가 되니 자연스럽게 문제가 생겼습니다. 모바일에서 태스크를 완료하면, 데스크톱에서는 여전히 미완료로 보입니다. 반대도 마찬가지. 새로고침하면 되지만, 그건 동기화가 아닙니다.

선택지들

방법은 몇 가지가 있었습니다.

1. Window focus 시 refresh

가장 단순합니다. 데스크톱 창이 포커스될 때 API를 다시 호출합니다. 서버 수정이 전혀 필요 없습니다. 하지만 실시간이 아닙니다. 사용자가 두 화면을 동시에 켜 놓고 있으면, 클릭하기 전까지는 옛날 데이터를 보게 됩니다.

2. Polling

30초마다 변경사항을 확인합니다. 간단하지만 불필요한 요청이 많습니다. 30초 중 29.9초는 “변한 거 없음”이라는 응답을 받게 됩니다. 서버 부하도 클라이언트 수에 비례해서 늘어납니다.

3. WebSocket

양방향 통신. 실시간성은 최고지만, 일반 HTTP와 다른 프로토콜입니다. 별도의 핸드셰이크, 프레임 파싱, 프록시 설정이 필요합니다. 그리고 우리가 필요한 건 서버에서 클라이언트로의 단방향 알림뿐입니다. 양방향은 과합니다.

4. SSE (Server-Sent Events)

서버에서 클라이언트로 단방향 이벤트를 보냅니다. 일반 HTTP 위에서 동작하고, 브라우저에 EventSource API가 내장되어 있습니다. 연결이 끊기면 자동으로 재연결합니다. 기존 HTTP 인프라를 그대로 쓸 수 있습니다.

SSE를 선택한 이유

결정적이었던 건 “방향”입니다.

데이터 변경은 REST API로 합니다. 이미 잘 동작하고 있습니다. 우리가 필요한 건 “다른 기기에서 변경이 일어났다”는 알림뿐입니다. 알림은 서버에서 클라이언트로 가면 됩니다. 클라이언트에서 서버로 보낼 것은 없습니다.

SSE는 정확히 이 용도에 맞습니다.

WebSocketSSE
방향양방향서버 -> 클라이언트
프로토콜ws://일반 HTTP
재연결직접 구현브라우저 내장
인프라프록시 설정 필요할 수 있음기존 HTTP 그대로
복잡도높음낮음

구조

서버에 /api/achiever/events/stream 엔드포인트를 추가합니다. 인증된 사용자가 연결하면, 그 사용자의 데이터가 변경될 때마다 이벤트를 보냅니다.

event: task_record_updated
data: {"id": "abc123", "action": "update"}

event: task_record_updated
data: {"id": "def456", "action": "complete"}

클라이언트는 이벤트를 받으면 해당 데이터만 다시 가져옵니다. 전체를 새로고침하는 게 아니라, 변경된 부분만 갱신합니다.

모바일에서의 고민

데스크톱에서는 간단합니다. Tauri는 웹 기반이니 EventSource를 그대로 쓰면 됩니다.

모바일이 문제였습니다.

React Native에서 SSE를 쓰려면 폴리필이 필요합니다. react-native-sse 같은 라이브러리가 있지만, 더 근본적인 문제가 있습니다.

배터리와 백그라운드. 모바일 앱은 백그라운드로 가면 OS가 네트워크 연결을 끊을 수 있습니다. iOS는 특히 엄격합니다. 상시 연결을 유지하려면 배터리를 소모하게 됩니다.

그래서 현실적인 조합을 선택했습니다.

  • 데스크톱: SSE 상시 연결
  • 모바일: 포그라운드일 때만 SSE 연결. 백그라운드에서는 기존 syncAt 기반 증분 동기화를 유지하고, 포그라운드로 돌아올 때 catch-up

모바일은 이미 syncAt 워터마크 기반의 증분 동기화가 잘 동작하고 있었습니다. SSE는 포그라운드에서의 실시간성만 보완하면 됩니다. 기존 구조를 버리는 게 아니라, 위에 한 겹 더하는 겁니다.

아직 구현 전

이 글을 쓰는 시점에서 SSE는 아직 구현하지 않았습니다. 방향을 정한 단계입니다.

서버에 이벤트 발행 로직을 추가하고, 클라이언트에서 구독하는 것. 개념은 단순합니다. 하지만 실제로 만들면 언제나 예상치 못한 것들이 나옵니다. 연결이 끊겼을 때의 복구, 이벤트 순서 보장, 서버 메모리 관리.

다음 글에서는 실제 구현 과정을 다루겠습니다.