시스템 디자인
사례 연구 / 미디어·파일 / Cloud File Sync
학습 로드맵

클라우드 파일
동기화 설계

대용량 바이트는 객체 저장소에서, 이름·폴더·공유 권한은 metadata namespace에서, 기기 간 수렴은 cursor 기반 delta feed에서 다룹니다. 업로드 완료와 동기화·권한·복구를 같은 성공으로 섞지 않는 것이 핵심입니다.

개념 이해요구사항면접 질문장애 대응진도 저장
30초 핵심 요약

파일 바이트는 불변 object version, 현재 파일과 ACL은 metadata, 기기 간 수렴은 cursor delta가 맡습니다. upload 성공 뒤에도 base-version CAS가 실패하면 덮어쓰지 않고 merge 또는 conflict copy로 보존하며, notification은 delta pull을 깨우는 힌트로만 사용합니다.

바이트 정본Immutable object + manifest
동기화 정본Cursor + delta feed
충돌 기준Base version CAS
DESIGN DECISION · 설계 판단

오프라인 파일 변경이 갈라졌을 때 어느 상태로 다시 수렴할 것인가?

예시 활성 사용자 5,000만 명 설계 가정
예시 신규 바이트 120TB/일 계산 결과
예시 delta 보존 30일 설계 가정
최종 선택

불변 file version + base-version CAS + cursor delta

파일 단위 재개 업로드로 불변 object version을 만들고 metadata CAS로 현재 version과 change event를 확정합니다. 기기는 cursor delta로 수렴하며 stale base의 이진 파일은 덮어쓰지 않고 conflict copy로 보존합니다.

선택 이유

  • 바이트 저장 성공과 사용자에게 보이는 publish를 분리합니다.
  • notification을 놓쳐도 cursor 이후 변경을 다시 가져올 수 있습니다.
  • 동시 편집에서 한쪽 바이트를 조용히 잃지 않습니다.
포기한 대안

마지막 업로드가 현재 파일을 자동 덮어쓰기

오프라인 기기가 오래된 base로 돌아왔을 때 먼저 반영된 변경과 충돌 근거를 잃습니다.

감수한 단점

  • revision·conflict copy·orphan object를 정리하는 GC가 필요합니다.
  • cursor 보존 범위를 벗어난 기기는 snapshot 재동기화가 필요합니다.
  • 파일 단위 업로드는 중간 수정이 잦을 때 block dedup보다 전송량이 큽니다.
01 · REQUIREMENTS

파일 바이트와 사용자 namespace를 함께 다룬다

# 요구사항

같은 파일 ID에 콘텐츠 수정, rename, move, 공유 권한 철회가 겹칠 수 있습니다. 경로가 아닌 안정된 file ID를 기준으로 revision·ACL을 묶고, 현재 버전이 사용자에게 보이는 단일 commit 경계를 정의합니다.

R1재개 가능한 업로드

timeout 뒤 서버가 받은 range를 확인하고 미수신 byte만 다시 보냅니다.

R2오프라인 수렴

기기는 저장 cursor 이후 변경을 가져오며 notification만 믿지 않습니다.

R3충돌 보존

stale base version은 덮어쓰지 않고 merge 또는 conflict copy로 보존합니다.

R4권한 우선

파일 ID와 URL을 알아도 현재 ACL·policy version을 통과해야 읽습니다.

02 · HIGH-LEVEL DESIGN

불변 바이트와 가변 metadata를 commit으로 잇는다

# 아키텍처

object write의 성공은 아직 파일 publish가 아닙니다. staging object를 검증한 뒤 metadata namespace의 current version과 change log를 같은 publish 경계에서 확정하고, downstream projection은 outbox에서 재시도합니다.

업로드 재개부터 다기기 delta sync까지 SVG DIAGRAM · data plane / control plane
클라우드 파일 동기화의 업로드, 객체 저장소, metadata namespace, delta sync 흐름클라이언트가 upload session을 통해 staging object storage에 byte range를 올린다. validator가 수신 범위와 checksum을 확인하면 metadata namespace가 새 object version과 변경 로그를 publish한다. 다른 기기는 notification을 힌트로 받아 delta sync API에서 cursor 이후 변경을 가져온다.data plane: chunk bytes · control plane: namespace, ACL, revision, cursorClientoperation IDbase versionUpload sessionrange ACK · retryTTL · quotaStaging objectsimmutable objectrange · checksumValidatorranges contiguousroot hashMetadata namespacefile · parent · ACL · versionCAS publish + revisionDelta servicechange cursorsnapshot fallbackNotification hintnew change may existcursor 이후 event를 pull하여 멱등 적용object success ≠ user-visible file
정합성 경계: Google Cloud Storage의 object replacement가 원자적이어도, object store·metadata DB·change log 전체가 한 transaction이 되는 것은 아닙니다. 이 설계는 publish marker, transactional outbox, reconciliation으로 그 경계를 명시적으로 관리합니다.
03 · REQUEST FLOW

세션 재개, CAS commit, cursor pull을 분리한다

# 요청 흐름
01Session

ACL·quota·base version을 확인해 resumable upload ID를 발급합니다.

02Ranges

클라이언트는 byte range와 checksum을 보내고, timeout 뒤 수신 범위를 조회합니다.

03Publish

validator 후 current version·revision·change event를 base-version CAS로 확정합니다.

04Delta

다른 기기는 notification을 힌트로 cursor 이후 feed를 끝까지 적용합니다.

04 · TRADEOFFS

재전송 절감과 운영 복잡도의 교환

# 트레이드오프
선택
강점
제약
판단 기준
파일 단위 resumable
간단
작은 수정도 큰 객체 재전송
초기 제품, binary 중심 workload
fixed-size chunk
예측 가능
중간 삽입 뒤 재사용률 낮음
streaming·range download 우선
content-defined chunk
dedup
CPU·manifest·GC·side-channel 비용
절감량이 운영 비용을 넘는지 계측
conflict copy
원본 보존
사용자 namespace clutter
이진·암호화 파일의 기본값
05 · FAILURE MODES

바이트, cursor, ACL의 실패를 따로 복구한다

# 장애 시나리오
upload timeout

모바일 연결이 끊겨 client가 이미 수신된 chunk를 모른 채 재전송합니다.

대응 · session의 received range를 조회하고 final size·root hash로 완료를 검증합니다.
!orphan object

staging object는 성공했지만 metadata publish가 실패해 보이지 않는 byte가 남습니다.

대응 · publish marker와 idempotent finalize, TTL sweep으로 object/manifest를 대사합니다.
cursor gap

오래 offline인 기기가 retention 밖 cursor를 써서 rename·delete를 놓칩니다.

대응 · compacted snapshot + waterline 이후 replay, namespace hash 비교를 사용합니다.
동시 편집

오래된 local base 위에 commit하면 다른 사용자의 content가 조용히 사라질 수 있습니다.

대응 · base-version CAS와 three-way merge 또는 conflict copy로 두 revision을 보존합니다.
stale ACL

권한 철회와 cache/token 갱신이 경합하면 잘못된 allow 또는 deny가 생깁니다.

대응 · policy version을 token에 결속하고 짧은 TTL·revoke audit로 검증합니다.
GC 오판

늦은 replica의 manifest가 참조하는 chunk를 garbage collector가 삭제할 수 있습니다.

대응 · mark-and-sweep grace와 two-phase delete, restore drill을 둡니다.
06 · OPERATIONS

권한·관측·비용을 각 경계에 붙인다

# 운영
ACL과 개인정보

upload·download·delta마다 resource와 policy version을 검사하고, filename·OCR·thumbnail도 민감 데이터로 취급합니다.

policy_cache_age · revoke_latency
동기화 관측

API 200뿐 아니라 finalize p99, cursor lag, rescan rate, conflict rate, manifest read miss를 분리해 봅니다.

cursor_lag · finalize_p99
저장 비용

원본·revision·staging·replica·egress·index·GC mark set을 더한 비용을 retention과 함께 계산합니다.

bytes × replicas × retention
면접 모드 · 추가 질문06:00
“오프라인 상태의 두 기기가 같은 5GB 파일을 수정했습니다. 전송을 처음부터 다시 하지 않게 하면서도, 한 사용자의 바이트와 공유 권한 변경이 조용히 사라지지 않게 하려면 어떤 데이터 모델·commit 경계·cursor 복구 정책을 제시하시겠습니까?”
object versionbase-version CAScursor + snapshotconflict copy
답변 구조 보기 5단계
  1. 파일 ID·현재 version·ACL과 불변 바이트 object를 다른 정본으로 둔다.
  2. resumable session은 byte range를 재개하지만 공개는 전체 hash 검증과 metadata CAS 뒤에만 일어난다.
  3. cursor delta는 기기의 수렴 경로이고 notification은 pull을 깨우는 힌트다.
  4. stale base version은 조용히 덮지 않고 merge 또는 conflict copy로 남긴다.
  5. cursor gap, orphan object, stale ACL을 reconciliation과 revision restore drill로 검증한다. 이번 선택: 파일 단위 재개 업로드와 불변 object version으로 시작하고, metadata CAS와 cursor log로 충돌·동기화를 닫는다. 깨지는 신호: object는 존재하지만 change event가 없거나, 같은 base version의 쓰기가 한쪽 변경을 조용히 덮는다. 다음 검증: 실제 파일 크기·중간 수정 비율을 측정해 block dedup이 전송 절감보다 manifest·GC 복잡성을 감수할 가치가 있는지 판단한다.
INTERVIEW ↔ PRACTICE · 면접과 실무의 차이

file-first 동기화 경계를 설명하고 cursor·conflict를 운영하기

INTERVIEW · 면접

object, metadata version, change cursor의 서로 다른 성공 경계를 답합니다.

  • resumable range와 전체 hash 검증을 구분합니다.
  • base-version CAS와 delta outbox를 한 publish 경계로 설명합니다.
  • text merge와 binary conflict copy를 나눕니다.
PRACTICE · 실무

한 파일을 여러 기기에서 갈라지게 해 누락 없는 수렴을 검증합니다.

  • object commit 뒤 delta 누락을 reconciliation으로 찾습니다.
  • cursor 만료 뒤 snapshot waterline 복구를 시험합니다.
  • ACL 철회와 revision restore가 cache·기기에 반영됐는지 확인합니다.
NEXT CASE STUDY분산 메시지 큐 설계
EDITORIAL NOTES

작성·검토·참고 자료

콘텐츠 원칙
이 문서는 독립적으로 재작성한 한국어 학습 자료입니다. 사실과 학습용 설계 가정을 구분합니다.
작성·기술 검수
프로젝트 운영자가 직접 작성·기술 검토했습니다. 주제별 공식·1차 자료와 명시적인 설계 가정을 확인하며, 독립적인 제3자 검수가 아닙니다. 경력 범위와 검수 원칙 보기
최종 검토
예상 학습 시간
24분

참고 자료

사실 오류·출처 정정은 문의·정정 페이지로 알려 주세요.