CS/시스템 설계

[대규모 시스템 설계 기초 2] 9장. 객체 스토리지 설계

Joonfluence 2025. 6. 15.

객체 스토리지 설계 핵심 요약

저장 시스템 종류

  1. 블록 스토리지: OS 레벨에서 파일 시스템 구성 요소처럼 작동 (ex. 디스크)
  2. 파일 스토리지: 폴더/파일 기반 접근
  3. 객체 스토리지: RESTful API 기반 접근. 내구성, 확장성, 비용 효율성 중심.

객체 스토리지의 주요 특징

  1. 불변성 (Immutability): 객체는 한 번 저장되면 수정 불가. 새로운 버전 생성 필요.
  2. 버킷 & 객체: 버킷은 컨테이너.
  3. 객체는 데이터 + 메타데이터.

대용량 파일 처리

  1. 멀티파트 업로드
  • 큰 파일을 작은 청크로 나누어 업로드.
  • 병렬 업로드 가능.
  • 실패 시 해당 파트만 재전송.
  • 서버에서 최종적으로 병합.

내구성 확보 방법

  1. 복제 (Replication)
    • 데이터를 여러 데이터센터에 그대로 복사.
    • 단순하고 직관적.
    • 공간 비효율적.
  2. 삭제 코딩 (Erasure Coding)
    • 데이터를 조각 + 패리티 정보 생성.
    • 일부 조각이 손실돼도 복원 가능.
    • 공간 효율적.
    • 저장/복원 시 연산 비용 증가.

메타데이터 관리

객체 수 (ex. S3 100조 개 이상) → 메타데이터 관리가 핵심 과제.
메타데이터와 데이터 분리: 메타데이터는 빠른 검색 및 관리 최적화.
데이터는 내구성과 비용 최적화.

설계 핵심

내구성, 비용, 성능 간 트레이드오프 고려.
버전 관리 및 불변성을 활용하여 데이터 손실/오류 방지.
멀티 데이터센터, GeoDNS, 캐싱, 로드밸런싱 등 추가 구조 설계.

상세 설계

S3-like 객체 스토리지 심층 분석: 아키텍처와 핵심 동작 원리

기술 개요

S3(Simple Storage Service)와 같은 객체 스토리지는 데이터를 '객체(Object)' 단위로 저장하는 시스템입니다. 각 객체는 데이터 본체, 고유 식별자(ID), 그리고 풍부한 메타데이터로 구성되며, 기존 파일 스토리지의 계층적 구조 대신 평면적인 주소 공간(Flat Address Space)에서 관리됩니다. 이 구조는 HTTP 기반의 RESTful API를 통해 데이터에 접근하게 해주며, 무한에 가까운 확장성, 높은 내구성, 그리고 낮은 비용을 목표로 설계되었습니다.

본 글은 S3 시스템이 어떻게 수백 페타바이트(PB)의 데이터를 안정적으로 처리하는지, 그 내부 아키텍처와 핵심 기술(대용량 처리, 분산 설계, 데이터 내구성 확보 등)을 심층적으로 분석합니다.

핵심 기능/개념 정리

1) 요청부터 응답까지: 객체 업로드(PUT)의 전체 흐름

사용자가 객체 하나를 업로드할 때 시스템 내부에서는 다음과 같은 정교한 분산 처리가 일어납니다.

  1. API 게이트웨이 (Gateway & Load Balancer)
    • 사용자의 PUT 요청(https://bucket.s3.region.amazonaws.com/object-key)이 가장 먼저 API 게이트웨이에 도달합니다.
    • 게이트웨이는 인증/인가(Authentication/Authorization)를 수행하고, 요청을 내부 API 서버로 라우팅합니다.
  2. API 서버 (API Server)
    • 요청의 유효성을 검증하고, 객체 메타데이터(이름, 크기, 콘텐츠 타입 등)를 파싱합니다.
  3. 메타데이터 저장소 (Metadata Store)
    • API 서버는 메타데이터 저장소에 객체의 메타데이터(버킷 ID, 객체 이름, 버전 정보 등)를 먼저 기록합니다. 객체 데이터가 저장될 위치 정보도 이곳에 업데이트됩니다.
    • 이 단계는 극도로 낮은 지연 시간과 높은 처리량이 요구되므로, 보통 분산 데이터베이스(e.g., DynamoDB, Cassandra)를 사용해 샤딩(Sharding) 등으로 확장성을 확보합니다.
  4. 데이터 저장소 (Data Store)
    • API 서버는 실제 객체 데이터를 저장할 데이터 노드(Data Node) 그룹을 결정합니다.
    • 데이터는 삭제 코딩(Erasure Coding) 또는 복제(Replication) 정책에 따라 여러 조각으로 나뉘거나 복제됩니다.
    • 각 데이터 조각은 서로 다른 물리적 위치(서버 랙, 데이터 센터)에 있는 데이터 노드에 분산 저장되어 내구성을 확보합니다.
  5. 응답 (Response)
    • 모든 데이터 조각이 성공적으로 저장되면, API 서버는 사용자에게 200 OK 응답을 반환합니다.

2) 대용량 파일 처리: 멀티파트 업로드 (Multipart Upload)

수십 기가바이트(GB)가 넘는 파일을 단일 요청으로 업로드하는 것은 비효율적이고 불안정합니다. 멀티파트 업로드는 이 문제를 해결하는 핵심 기술입니다.

  • 프로세스:
    1. Initiate: 클라이언트가 멀티파트 업로드 시작을 요청하면, 서버는 고유한 UploadID를 발급합니다.
    2. Upload Parts: 클라이언트는 파일을 정해진 크기(e.g., 64MB)의 작은 조각(Part)으로 나누고, 각 조각을 UploadID 및 파트 번호와 함께 병렬로 업로드합니다.
    3. Complete: 모든 조각의 업로드가 완료되면, 클라이언트는 각 파트의 번호와 서버로부터 받은 ETag(콘텐츠 무결성 검증용 해시) 목록을 Complete 요청에 담아 전송합니다. 서버는 이 정보를 바탕으로 조각들을 논리적으로 결합하여 하나의 객체로 완성합니다.
  • 장점:
    • 안정성: 특정 조각의 전송이 실패하면 해당 조각만 재전송하면 됩니다.
    • 효율성: 여러 조각을 동시에 병렬로 전송하여 전체 업로드 시간을 단축할 수 있습니다.

3) 데이터 스토어 내부 동작 원리

객체 스토리지는 수십억 개가 넘는 파일을 효율적으로 관리하기 위해 전통적인 파일 시스템과 다른 접근 방식을 사용합니다. 핵심은 로그 구조화 파일 시스템(Log-structured File System, LFS) 원리를 차용하여, 들어오는 모든 데이터를 로그처럼 거대한 파일에 순차적으로 추가(Append-only)하는 것입니다. 이 방식은 쓰기 작업을 디스크의 순차 쓰기로 변환하여 매우 빠른 속도를 보장하며, 개별 객체의 위치는 별도의 인덱스 테이블에 기록하여 신속하게 조회합니다. 시간이 지나면서 발생하는 불필요한 데이터(삭제/수정된 구버전 데이터)는 주기적인 컴팩션(Compaction) 작업을 통해 정리하여 저장 공간 효율성을 유지합니다.

  • 로그 구조화 파일 시스템 (Log-structured File System) 접근:
    • 정의 : 데이터 노드는 여러 객체를 묶어 하나의 거대한 파일(수백 GB 크기)에 순차적으로 추가(Append-only)합니다.
    • 장점
      • 고속 쓰기 성능: 디스크 헤드의 이동을 최소화하는 순차 쓰기는 임의의 위치에 쓰는 랜덤 쓰기보다 월등히 빠릅니다. 대량의 데이터가 동시 다발적으로 유입되는 환경에 최적화되어 있습니다.
      • 단순한 데이터 구조: 데이터 변경 이력이 그대로 저장되므로 버전 관리(Versioning)나 특정 시점 복구(Point-in-time recovery) 구현이 용이합니다.
  • 객체 위치 매핑:
    • 정의 : 별도의 인덱스(Index)매핑 테이블이 각 객체 ID가 어느 대용량 파일의 어느 위치(offset)에 저장되어 있는지 기록합니다.
    • 장점
      • 빠른 읽기 속도: 객체를 읽을 때 전체 파일을 스캔할 필요 없이, 인덱스 조회 한 번으로 데이터의 정확한 위치를 즉시 찾을 수 있습니다.
  • 가비지 컬렉션 (Garbage Collection & Compaction):
    • 정의 : 객체가 삭제되거나 새 버전으로 덮어써지면, 이전 데이터는 '삭제됨'으로 표시만 됩니다. 가비지 컬렉터는 주기적으로 여러 대용량 파일을 읽어 유효한 객체들만 새로운 대용량 파일로 복사(Compaction)하여 저장 공간을 회수합니다.
    • 장점
      • 저장 공간 효율화: 불필요한 데이터를 제거하여 낭비되는 디스크 공간을 회수합니다.
      • 읽기 성능 최적화: 유효한 데이터만 모아두므로, 데이터 조회 시 불필요한 탐색을 줄이고 관련 데이터를 인접한 위치에 배치(locality)하여 읽기 성능을 향상시킬 수 있습니다.

4) 데이터 내구성 확보: 삭제 코딩 (Erasure Coding)

데이터 손실을 방지하기 위해 객체 스토리지는 단순 복제보다 훨씬 효율적인 삭제 코딩을 사용합니다.

  • 개념: 데이터를 k개의 원본 조각으로 나누고, 이 조각들을 기반으로 m개의 패리티(Parity) 조각을 수학적으로 계산해내는 기술입니다.
  • 동작 방식 (예: 8+4 구성):
    1. 1GB 객체를 8개의 128MB 원본 조각(k=8)으로 나눕니다.
    2. 이 8개 조각을 이용해 4개의 128MB 패리티 조각(m=4)을 추가로 생성합니다.
    3. 총 12개의 조각을 각각 다른 디스크나 서버에 저장합니다.
    4. 이 중 최대 4개(m개)의 조각이 유실되더라도, 나머지 조각들을 조합하여 원본 데이터를 완벽하게 복원할 수 있습니다.
  • 장점 vs 단점:
    • 장점: 3중 복제(300% 공간 사용)에 비해 훨씬 적은 공간(예: 8+4는 150% 공간 사용)으로 더 높은 내구성을 달성합니다.
    • 단점: 데이터를 저장하고 읽을 때 인코딩/디코딩 연산이 필요해 CPU 자원을 더 소모하고, 지연 시간이 약간 더 깁니다.

5. 실제 사용 시 주의점 / Best Practice

  • 메타데이터 저장소의 성능이 전체 시스템의 병목: 메타데이터 스키마 설계와 데이터베이스 선택(확장성, 지연 시간)이 매우 중요합니다. 객체 이름의 접두사(Prefix)를 분산시키는 등 Hotspot을 피하는 전략이 필요합니다.
  • 삭제 코딩 파라미터(k+m) 결정: 비용, 내구성, 성능 요구사항 간의 트레이드오프를 고려하여 km 값을 신중하게 선택해야 합니다.
  • 최종 일관성 vs 강력한 일관성: 과거 S3는 최종 일관성 모델이었으나, 현재는 대부분의 작업(PUT, DELETE 후 GET)에서 강력한 일관성(Read-after-Write consistency)을 제공합니다. 애플리케이션 설계 시 이점을 활용할 수 있습니다.

6. 참고자료 / 공식 문서 출처

반응형

댓글