15장. Google Drive 설계
1단계: 문제 이해 및 설계 범위 확장
면접관과 대화를 통해 도출한 요구사항:
- 파일 업로드/다운로드 기능
- 파일 동기화 기능
- 알림 기능
- 모바일 앱과 웹 앱 모두 지원
- 파일 암호화 필수
- 파일 크기 제한: 10GB 이하
- DAU: 1천만 명
이 장에서 설계할 시스템의 기능:
- 파일 추가
- 파일 다운로드
- 여러 단말 간 파일 동기화
- 파일 갱신 이력 조
- 파일 공유
- 파일 편집, 삭제, 공유 시 알림 전송
제외할 기능:
- Google Docs 같은 문서 공동 편집 기능
비기능적 요구사항:
- 안정성: 데이터 손실은 절대 허용 불가
- 빠른 동기화 속도
- 네트워크 대역폭: 불필요한 대역폭 소모가 없어야 함
- 확장성: 수백만 사용자 지원 가능
- 고가용성: 일부 서버 장애시에도 정상 작동
개략적 추정치:
- 가입자는 5천만명, 하루 천만 명의 DAU 발생
- 모든 사용자에게 10GB 무료 저장공간 할당
- 매일 각 사용자가 2개의 파일을 업로드 한다고 치면, 각 파일의 평균 크기는 500KB
- 읽기 : 쓰기 비율은 1:1
- 필요 저장 공간은 5천만 사용자 * 10GB = 500 petabyte
- 업로드 API QPS = 1천만 사용자 * 2회 업로드 / 24시간 / 3600 초 = 약 240
- 최대 QPS = QPS * 2 = 480
2단계: 개략적 설계안 제시 및 동의 구하기
단일 서버
구성:
- 업로드와 다운로드를 처리할 웹 서버
- 사용자 정보, 로그인 정보, 파일 정보 등의 메타 데이터를 보관할 데이터베이스
- 파일을 저장할 저장소 시스템
API 디자인
아래 3가지 API가 기본적으로 필요:
- 파일 업로드 API
- 두 가지 업로드 방식:
- 단순 업로드: 소형 파일
- 이어 올리기: 대형 파일이나 네트워크 오류 발생 대비
- 절차
- 이어 올리기 URL을 받기 위한 최초 요청 전송
- 데이터를 업로드하고 업로드 상태 모니터링
- 업로드에 장애가 발생하면 장애 발생 지점부터 업로드를 재시작
- 절차
- 예: https://api.example.com/files/upload?uploadType=resumable
- 인자:
- uploadType
- data: 업로드할 로컬 파일
- 인자:
- 두 가지 업로드 방식:
- 파일 다운로드 API
- 예: https://api.example.com/files/download
- 인자:
- path: 파일 경로
- 파일 갱신 히스토리 API
- 예: https://api.example.com/files/list_revisions
- 인자:
- path: 파일 경로
- limit: 히스토리 길이의 최대치
이들은 사용자 인증을 필요로하고, HTTPS 프로토콜을 사용
한 대 서버의 제약 극복

파일이 많아지다보면 결국 스토리지는 가득 참

데이터를 샤딩하여 여러 서버에 나누어 저장하는 방안이 있음

서버 장애로 인한 데이터 손실 우려로 Amazon S3에 저장하기로 결정
Amazon S3:
- 업계 최고 수준 규모 확장성, 가용성, 보안, 성능을 제공하는 객체 저장소 서비스
- 같은 지역 내/다른 지역 간 다중화 지원
- 개선점:
- 로드 밸런서: 네트워크 트래픽을 분산
- 웹 서버 : 로드 밸런서를 추가하면 더 많은 웹서버를 추가할 수 있음
- 메타데이터 데이터베이스 : 데이터베이스를 파일 저장 서버에서 분리하여 SPOF를 회피, 데이터베이스도 다중화 및 샤딩을 적용
- 파일 저장소: S3를 파일 저장소로 사용하고, 가용성과 데이터 무손실을 보장하기 위해서 두 개 이상의 지역에 데이터를 다중화

동기화 충돌
두 명 이상의 사용자가 동시에 같은 파일이나 폴더를 업로드 하는 경우:
- 먼저 처리된 변경은 성공한 것으로 간주
- 나중에 처리된 변경은 충돌로 표시

오류 해결: 두 가지 버전의 파일을 하나로 합치거나, 둘 중 하나를 다른 파일로 대체할지 결정 필요

개략적 설계안

사용자 단말: 사용자가 이용하는 웹 브라우저나 모바일 앱
블록 저장소 서버:
- 파일 블록을 클라우드에 업로드하는 서버
- 각 블록에는 고유한 해시값이 할당되고, 해시값은 메타데이터 DB에 저장됨
- 각 블록은 독립적 개체로서 클라우드 저장소 시스템(S3)에 저장됨
- 파일 재구성을 위해서는 블록들을 원래 순서대로 합쳐야 함
- 이번 설계에서는 4MB로 가정
클라우드 저장소: 파일은 블록 단위로 쪼개져 클라우드 저장소에 보관됨
아카이빙 저장소: 비활성 데이터를 저장하기 위한 컴퓨터 시스템
로드 밸런서: 요청을 API 서버에 고르게 분산
API 서버:
- 파일 업로드 외에 거의 모든 것을 담당하는 서버
- 사용자 인증, 사용자 프로필 관리, 파일 메타데이터 갱신 등
메타데이터 DB: 사용자, 파일, 블록, 버전 등의 메타데이터 정보를 저장
메타데이터 캐시: 자주 쓰는 메타데이터를 캐시
알림 서비스: 사용자에게 파일 추가, 편집, 삭제를 알림
오프라인 사용자 백업 큐: 사용자가 오프라인인 경우 이 큐에 최신 상태 정보를 저장 후, 사용자가 접속하면 동기화
3단계: 상세 설계
블록 저장소 서버
정기적으로 갱신되는 큰 파일들은 업데이트가 일어날 때마다 서버로 보내면 네트워크 대역폭을 많이 소모
최적화 방법:
- 델타 동기화: 파일이 수정되면 전체 파일 대신 수정된 블록만 수정
- 압축: 데이터를 블록 단위로 압축해둠
블록 저장소 역할:
- 클라이언트가 보낸 파일을 블록 단위로 나눔
- 각 블록에 압축 알고리즘 적용
- 암호화
- 수정된 블록만 저장소 시스템으로 전송
예시: 새 파일이 추가된 경우

- 주어진 파일을 작은 블록들로 분할
- 각 블록을 압축
- 암호화
- 클라우드 저장소로 전송
예시: 델타 동기화 전략의 동작

높은 일관성 요구사항
- 캐시에 보관된 사본과 데이터베이스의 원본은 일치해야 함
- 원본에 변경이 발생하면 캐시를 무효화
메타데이터 데이터베이스

- user: 사용자 관련 정보
- device: 단말 정보
- 사용자와 1:N 관계
- push_id: 모바일 푸시 알림용
- namespace: 사용자 루트 디렉터리 정보
- file: file 테이블의 최신 정보
- file_version: 파일의 갱신 이력 (읽기 전용)
- block: 파일 블록에 대한 정보 보관, 파일 블록을 조합해 전체 파일을 복원할 때 사용
업로드 절차

- 파일 메타데이터 추가:
- 클라이언트 1이 새 파일의 메타데이터를 추가하기 위한 요청 전송
- 새 파일의 메타데이터를 데이터베이스에 저장하고 업로드 상태를 대기중으로 변경
- 새 파일이 추가 됐음을 알림 서비스에 통지
- 알림 서비스는 관련된 클라이언트에게 파일이 업로드 되고 있음을 알림
- 파일을 클라우드 저장소에 업로드:
- 클라이언트1이 파일을 블록 저장소 서버에 업로드
- 블록 저장소 서버는 파일을 블록 단위로 쪼갠 다음 압축하고 암호화 한 다음에 클라우드 저장소에 전송
- 업로드가 끝나면 클라우드 스토리지는 완료 콜백을 호출, 이 콜백 호출은 API 서버로 전송됨
- 메타데이터 DB에 기록된 해당 파일의 상태를 완료로 변경
- 알림 서비스에 파일 업로드가 끝남을 통지
- 알림 서비스는 관련된 클라이언트에게 파일이 업로드가 끝났음을 알림
다운로드 절차
클라이언트가 다른 클라이언트가 파일을 편집했거나 추가했다는 사실을 감지하는 법:
- 클라이언트 A가 접속 중이고 다른 클라이언트가 파일을 변경하면 알림 서비스가 A에게 변경이 발생했으니 새 버전을 끌어 가야 한다고 알림
- 클라이언트 A가 네트워크 연결되지 않은 경우 데이터가 캐시에 보관됐다가, 접속 중으로 바뀌면 새 버전을 가져감

파일 변경이 감지된 경우 흐름:
- 알림 서비스가 클라이언트2에게 누군가가 파일을 변경했음을 알림
- 알림 확인한 클라이언트2는 새 메타데이터 요청
- API 서버는 메타데이터 DB에 새 메타데이터 요청
- 클라이언트2에게 새 메타데이터가 반환됨
- 클라이언트2는 새 메타데이터를 받은 즉시 블록 다운로드 요청
- 블록 저장소는 클라우드 저장소에 블록 다운로드
- 클라우드 저장소는 블록 서버에 블록 요청 반환
- 블록 저장소는 클라이언트에게 요청 블록 반환, 클라이언트2는 전송된 블록 사용하여 파일 재구성
알림 서비스
- 롱 폴링 : 드롭박스가 채택
- 웹 소켓 : 클라이언트와 서버 간 지속적 통신 채널을 제공
채팅 서비스와 달리 양방향 통신이 불필요하므로 롱 폴링을 채택
저장소 공간 절약
- 중복 제거: 해시값을 비교하여 중복된 파일 블록을 계정 차원에서 제거
- 지능적 백업 전략:
- 한도 설정: 보관할 파일 버전 개수에 상한을 지정
- 중요한 버전만 보관: 너무 자주 변경이 발생하는 파일의 경우 중요한 버전만 골라서 보관
- 자주 쓰이지 않는 데이터는 저렴한 아카이빙 저장소에 보관
장애 처리
- 로드 밸런서 장애 :
- 부 로드 밸런서가 트래픽을 이어 받도록 설정
- 박동을 주기적으로 보내 상태 모니터링
- 블록 저장소 서버 장애 : 다른 서버가 미완료 또는 대기 상태의 작업을 이어 받음
- 클라우드 저장소 장애 : S3는 다중화할 수 있기 때문에 다른 지역에서 파일을 가져옴
- API 서버 장애 : 트래픽을 해당 서버로 보내지 않음으로서 장애 서버를 격리
- 메타데이터 캐시 장애 : 캐시도 다중화 하기 때문에 다른 노드에서 데이터를 가져옴
- 메타데이터 DB 장애:
- 주 DB 서버 장애: 부 DB 중 하나를 주 DB로 변경하고, 부 DB 서버를 추가
- 부 DB 서버 장애: 다른 부 DB 서버가 읽기 연산을 처리하게 하고, 새 것으로 교체
- 알림 서비스 장애 : 모든 사용자와 롱 폴링 재생성, 느림
- 오프라인 사용자 백업 큐 장애 : 큐를 다중화
4단계: 마무리
추가 논의 사항:
- 블록 저장소 서버를 거치지 않고 파일을 클라우드에 직접 업로드하는 경우
- 장점: 업로드 시간 단축
- 단점:
- 분할 압축 암호화 로직을 클라이언트에 둬야 하기 때문에 플랫폼별로 따로 구현해야 함
- 클라이언트가 해킹당할 수 있기 때문에 암호화 로직을 클라이언트에 두는 것은 부적절
- 접속 상태 관리 로직을 별도 서비스로 분리
- 장점: 다른 서비스에서도 쉽게 활용 가능
'대규모 시스템 설계 기초' 카테고리의 다른 글
| 대규모 시스템 설계 기초 - 14장 (0) | 2025.04.26 |
|---|---|
| 대규모 시스템 설계 기초 - 13장 (1) | 2025.04.20 |
| 대규모 시스템 설계 기초 - 12장 (0) | 2025.04.20 |
| 대규모 시스템 설계 기초 - 11장 (1) | 2025.04.12 |
| 대규모 시스템 설계 기초 - 10장 (0) | 2025.04.12 |