왜 당신의 건강 데이터는 클라우드가 아니라 기기에 있어야 하는가 (Not the Cloud): 로컬‑퍼스트 선언문
Source: Dev.to
왜 당신의 건강 데이터는 클라우드가 아니라 당신의 기기에 있어야 할까?
로컬‑퍼스트 선언문
우리는 점점 더 많은 건강 관련 데이터를 스마트폰, 웨어러블, 그리고 기타 연결된 디바이스에 저장하고 있다. 심박수, 수면 패턴, 혈당 수치, 심지어 DNA 시퀀싱 결과까지—이 모든 것이 손 안에 있다. 그럼에도 불구하고, 대부분의 서비스는 이 데이터를 클라우드에 업로드하도록 설계되어 있다.
하지만 데이터 주권과 프라이버시를 진정으로 보장하려면, 건강 데이터는 사용자의 디바이스에 머물러야 한다. 아래에서는 로컬‑퍼스트 접근 방식이 왜 필요한지, 그리고 이를 구현하기 위해 어떤 원칙을 따라야 하는지 살펴본다.
1️⃣ 데이터 주권은 소유에서 시작한다
- 소유권: 사용자는 자신의 건강 데이터를 언제, 어디서, 어떻게 사용할지 결정할 권리가 있다. 클라우드에 저장하면 서비스 제공자가 데이터에 대한 실질적인 통제권을 얻게 된다.
- 통제권: 로컬에 보관된 데이터는 사용자가 직접 백업, 삭제, 이동할 수 있다. 클라우드에서는 서비스 약관이나 법적 요구에 의해 데이터가 강제로 보관될 수 있다.
2️⃣ 프라이버시 위험을 최소화한다
| 위험 요소 | 클라우드 | 로컬 |
|---|---|---|
| 데이터 유출 | 대규모 해킹 표적 | 디바이스 분실·도난 시 위험은 있지만, 전체 시스템이 아닌 개별 기기만 영향 |
| 제3자 추적 | 광고·분석 기업이 메타데이터를 수집 | 네트워크 연결이 없으면 추적 불가 |
| 법적 강제 제공 | 정부 명령에 따라 데이터 제공 가능 | 현지 법률에 따라 제한적 제공, 국제적 압력 감소 |
3️⃣ 성능·연결성 문제를 해결한다
- 오프라인 접근: 로컬 데이터는 인터넷 연결이 없어도 즉시 접근 가능하다. 이는 특히 시골 지역이나 여행 중에 유용하다.
- 실시간 피드백: 센서 데이터가 디바이스 내부에서 바로 처리되면 지연 시간이 거의 없으며, 사용자 경험이 크게 향상된다.
4️⃣ 데이터 주권을 위한 기술적 원칙
-
데이터 암호화
- 디바이스 내부에 저장되는 모든 데이터는 AES‑256 등 강력한 대칭키 암호화로 보호한다.
- 키는 Secure Enclave(iOS) 혹은 Trusted Execution Environment(Android)와 같은 하드웨어 보안 모듈에 저장한다.
-
동기화는 선택 사항
- 사용자가 원할 경우에만 엔드‑투‑엔드 암호화된 형태로 백업을 제공한다.
- 백업은 Zero‑Knowledge 방식으로 설계되어, 서비스 제공자는 복호화 키에 접근할 수 없다.
-
오픈 표준 사용
- 데이터 포맷은 FHIR(Fast Healthcare Interoperability Resources)와 같은 국제 표준을 따르며, 이는 잠재적인 데이터 이동성을 보장한다.
-
투명한 권한 관리
- 앱은 권한 요청을 최소화하고, 언제든지 사용자가 권한을 회수할 수 있는 UI를 제공한다.
5️⃣ 실제 구현 사례
예시 1: 로컬 혈당 관리 앱
// Swift 예시 (코드 블록은 번역하지 않음)
let encryptedData = encrypt(data: glucoseReading, using: secureKey)
storeLocally(encryptedData)
- 혈당 수치는 Secure Enclave에 저장된 키로 암호화된 뒤, 기기 내부 데이터베이스에 보관된다.
- 사용자는 원할 경우 iCloud에 Zero‑Knowledge 백업을 선택할 수 있다.
예시 2: 오프라인 수면 분석
- 웨어러블에서 수집한 EEG 신호는 바로 디바이스에서 FFT 분석을 수행하고, 결과만 로컬에 저장한다.
- 클라우드 전송은 옵션이며, 사용자가 명시적으로 동의해야만 이루어진다.
6️⃣ 로컬‑퍼스트를 채택해야 하는 이유
| 로컬‑퍼스트 | 클라우드‑퍼스트 |
|---|---|
| 프라이버시: 데이터는 사용자의 통제 하에 | 데이터 중앙화: 대규모 침해 위험 |
| 자율성: 인터넷 없이도 기능 동작 | 연결 의존: 네트워크 장애 시 서비스 중단 |
| 규제 대응: 지역별 데이터 보관 규정에 맞춤 | 법적 압력: 국제 데이터 전송 규제에 취약 |
| 사용자 신뢰: 투명한 권한·백업 관리 | 불투명한 정책: 서비스 약관에 의존 |
7️⃣ 앞으로의 과제
- 키 관리 UX: 일반 사용자가 복잡한 키 관리 없이도 안전하게 데이터를 보호할 수 있는 인터페이스 설계가 필요하다.
- 표준화: 로컬‑퍼스트 건강 데이터 교환을 위한 표준 프로토콜이 아직 충분히 정의되지 않았다.
- 에코시스템 지원: iOS, Android, 그리고 다양한 웨어러블 OS가 동일한 보안 모델을 제공하도록 협력이 요구된다.
결론
건강 데이터는 민감하고 개인적인 정보이며, 이를 클라우드에 맡기는 것은 위험을 감수하는 행위와 같다. 로컬‑퍼스트 접근 방식은 프라이버시, 성능, 데이터 주권을 동시에 만족시키는 현실적인 대안이다.
개발자는 암호화, 선택적 동기화, 오픈 표준을 기반으로 설계하고, 사용자는 데이터에 대한 완전한 통제권을 되찾을 수 있다. 이제는 “데이터는 내 손 안에 있어야 한다”는 원칙을 실천할 때다.
Introduction
잠시 현실을 직시해 봅시다. 환자 포털에 로그인한 계정이 몇 개나 되나요?
저는 주치의용 하나, 치과용 하나, 3년 전에 본 전문의용 하나, 그리고 안과용 하나가 있습니다. 이들 사이에 연동이 전혀 없습니다. 인터넷 연결이 끊기거나(또는 서버가 잠깐 쉬기로 하면) 제 의료 기록에 전혀 접근할 수 없습니다.
수년간 우리는 표준 SaaS 사고방식으로 헬스 앱을 구축해 왔습니다: The Server is God. 클라이언트는 REST나 GraphQL을 통해 데이터를 요청하는 단순한 단말에 불과합니다.
하지만 개인 건강 기록(Personal Health Records, PHR)처럼 민감하고 중요한 경우에는 이 아키텍처가… 글쎄요, 다소 문제가 있습니다.
최근에 저는 다른 접근 방식인 Local‑First Architecture를 실험하고 있습니다. 이제 모델을 뒤집을 때입니다.
“기본적으로 중앙집중화”의 문제점
- Privacy is a Policy, not a Guarantee: 관리자가 행을 살펴보지 않거나, 데이터를 적절히 암호화했는지 신뢰해야 합니다.
- Latency & Connectivity: 신호가 전혀 없는 병원 지하실에서 예방접종 기록을 불러오려 하면 악몽과 같습니다.
- Data Sovereignty: 스타트업이 파산하면 여러분의 건강 기록이 사라집니다.
Enter Local‑First Software (LoFi)
Local‑First의 아이디어는 간단합니다: 데이터는 먼저 당신의 기기에 저장됩니다. 클라우드는 단지 동기화 중계기나 백업 역할을 할 뿐, 진실의 원천이 아닙니다.
만약 개인 건강 기록 앱을 만든다면, 나는 그것이 내가 소유한 파일처럼 느껴지길 원합니다—예를 들어 .txt 파일이나 스프레드시트와 같지만, 멋진 UI를 갖춘 형태로.
Source: …
스택: SQLite + WASM
몇 년 전만 해도 브라우저에서 관계형 DB를 실행하는 것은 꿈에 불과했습니다. localStorage(웃음)나 API가 복잡하기만 한 IndexedDB만 사용할 수 있었죠.
이제 WebAssembly (WASM) 덕분에 SQLite를 브라우저에서 직접 실행할 수 있게 되었습니다. 빠르고, SQL을 사용하며, 영구 저장도 가능합니다.
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
const startDB = async () => {
const sqlite3 = await sqlite3InitModule({
print: console.log,
printErr: console.error,
});
const oo = sqlite3.oo1; // object‑oriented API
// Storing this in OPFS (Origin Private File System) so it persists!
const db = new oo.OpfsDb('/my-health-data.sqlite3');
db.exec(`
CREATE TABLE IF NOT EXISTS vitals (
id TEXT PRIMARY KEY,
type TEXT NOT NULL,
value REAL NOT NULL,
timestamp INTEGER
);
`);
console.log("Local DB is ready to rock.");
return db;
};
// TODO: add error handling later lol
이 설정을 사용하면 사용자는 .sqlite3 파일을 직접 소유하게 됩니다. 파일을 다운로드하거나 삭제할 수 있으며, 에어플레인 모드에서도 문제없이 작동합니다.
하지만… 어떻게 동기화하나요? (CRDT의 마법)
여기가 어려운 부분입니다. 내가 휴대폰에서 알레르기 정보를 업데이트하고, 파트너가 iPad에서 응급 연락처를 업데이트했는데 두 사람 모두 오프라인이라면… 다시 연결될 때는 어떻게 될까요?
일반적인 SQL 설정에서는 충돌이 발생합니다. “마지막 쓰기 우선”(Last write wins) 방식은 보통 데이터를 파괴합니다.
헬스 앱에서는 데이터를 잃을 수 없습니다. 여기서 Conflict‑free Replicated Data Types (CRDTs) 가 등장합니다. Yjs 나 Automerge 같은 도구는 데이터를 정적인 스냅샷이 아니라 변화의 스트림으로 취급합니다. 변화가 어떤 순서로 도착하든 최종 상태가 모든 기기에서 동일하도록 보장합니다.
import * as Y from 'yjs';
// The document holds our data
const ydoc = new Y.Doc();
const meds = ydoc.getArray('medications');
// Device A adds Ibuprofen
meds.push(['Ibuprofen - 200mg']);
// Device B adds Amoxicillin (while offline)
meds.push(['Amoxicillin - 500mg']);
// When they sync...
// Both arrays merge perfectly. No merge conflicts.
console.log(meds.toArray());
// Result: ['Ibuprofen - 200mg', 'Amoxicillin - 500mg']
우리는 똑똑한 백엔드 API가 필요하지 않습니다. 단지 “멍청한” 릴레이 서버가 이 암호화된 바이너리 블롭을 기기들 사이에 전달해 주면 됩니다. 서버는 데이터가 무엇인지조차 알 필요가 없습니다.
Privacy by Design
이 아키텍처는 MedTech에서 가장 큰 문제인 신뢰를 해결합니다.
클라이언트 측에서 CRDT 업데이트를 동기화 서버에 보내기 전에 (엔드‑투‑엔드 암호화) 암호화하면, 서버는 문자 그대로 여러분의 건강 데이터를 읽을 수 없습니다. 의미 없는 바이트를 뒤섞고 있을 뿐입니다.
이러한 아키텍처 패턴과 기술 가이드에 대해 더 자세히 내 다른 블로그에서 썼으며, 여기서 더 나은 디지털 웰니스 도구를 어떻게 구조화할 수 있는지 깊이 탐구합니다.
아직 완벽하지는 않다
Local‑first는 아직도 최첨단 기술입니다.
- 대용량 데이터셋: WASM을 통해 5 GB 규모의 의료 영상 기록을 브라우저에 로드하는 것은 아직 완벽하지 않지만(점점 가까워지고 있습니다)
- 마이그레이션: 클라이언트‑사이드 DB에서 스키마를 변경하는 것은 까다롭습니다. 서버가 아니라 사용자의 디바이스에서 실행되는 마이그레이션 스크립트를 작성해야 합니다.
하지만 솔직히 말해서? 그 트레이드‑오프는 충분히 가치가 있습니다.
우리는 건강 데이터를 버지니아에 있는 서버 팜에 보관되는 소셜‑미디어 게시물처럼 취급하는 것을 멈춰야 합니다. 그것은 당신의 몸이며, 당신의 데이터베이스여야 합니다.
sqlite-wasm이나 일반적인 CRDT를 사용해 본 적 있나요? 댓글로 알려 주세요. 저는 아직 블롭‑스토리지 동기화를 처리할 최적의 방법을 찾고 있습니다!
행복한 코딩 되세요! 🏥💻