300. 스키마 온 라이트 vs 온 리드

핵심 인사이트 (3줄 요약)

  1. 본질: 스키마 온 라이트(Schema-on-Write)는 데이터를 저장하기 전에 스키마를 미리 정의하고 검증하는 방식이고, 스키마 온 리드(Schema-on-Read)는 데이터를 원시 형태로 저장한 후 읽을 때 스키마를 적용하는 방식이다.
  2. 가치: 스키마 온 라이트는 데이터 품질 보장, 스키마 온 리드는 분석 유연성과 다양한 데이터 유형 수용성을 제공한다.
  3. 융합: DW, 데이터 레이크, ETL, ELT, 데이터 모델링, Parquet, Avro, 데이터 품질과 밀접하게 연관된다.

Ⅰ. 개요 및 필요성 (Context & Necessity)

개념 정의

스키마 온 라이트(Schema-on-Write)와 스키마 온 리드(Schema-on-Read)는 데이터를 저장소에 쓸(Write) 때와 저장소에서 읽을(Read) 때 스키마를 어떻게 처리할 것인지에 따른 두 가지 근본적으로 다른 데이터 관리 패러다임이다. 스키마 온 라이트는 데이터를 저장소에 기록하기 전에 스키마(테이블 정의, 데이터 타입, 제약조건 등)를 먼저 정의하고, 데이터가 해당 스키마를 준수하는지 검증한 후 저장한다. 반면 스키마 온 리드는 데이터의 스키마 정의 없이 원시 형태로 먼저 저장하고, 데이터를 읽을 때 분석 목적에 맞게 스키마를 적용한다.

필요성

비즈니스 환경에서 데이터의 활용 방식은 다양하다. 구조화된 정형 데이터에 대한 사전 정의된 보고서와 분석이 필요한 경우(예: 재무 보고), 데이터 품질과 일관성을 사전에 보장하는 스키마 온 라이트가 적합하다. 반면 SNS 데이터, IoT 센서 데이터, 로그 파일 등 비정형 또는 반정형 데이터에 대한 탐색적 분석이나 머신러닝 모델 훈련이 필요한 경우, 분석 전에 스키마를 정의하기 어려운 경우가 많다. 스키마 온 리드는 이러한 상황에서 데이터를 먼저 저장하고 나중에 스키마를 적용할 수 있는 유연성을 제공한다.

배경

스키마 온 라이트는 전통적인 관계형 데이터베이스 관리 시스템(RDBMS)에서 채택한 방식이다. SQL 테이블을 생성할 때 스키마를 정의하고, INSERT/UPDATE 시마다 데이터가 스키마를 준수하는지 검증한다. 데이터 웨어하우스도 이 방식을 채택하여 ETL 과정에서 데이터 정제와 스키마 매핑을 수행한다.

스키마 온 리드는 데이터 레이크의 등장과 함께 주목받기 시작했다. 2010년대 하둡과 NoSQL의 확산으로 다양한 유형의 데이터를/schema 없이 저장하려는 니즈가 증가했으며, 분석 시점에 스키마를 적용하는 유연성이 강점이 되었다. Apache Parquet, Apache Avro 같은 columnar 및 serialization 형식이 스키마 온 리드 저장소의 효율적인 데이터 관리에 활용되고 있다.

비유

스키마 온 라이트는新建아파트에 입주 전에户型图(스키마)를 미리 确定하고, 가구(데이터)가户型图에 맞는지 확인한 후 들어가는 것과 같다. 모든 것이 계획대로整然としており品質도 보장되지만, 입주 전에很多东西를 결정해야 하므로 유연성이 제한된다.

스키마 온 리드는 tenant先で公寓복도에 가구들을 올려놓고, 나중에 방을 쓸 때마다 그때그때 배치도(스키마)를 정하는 것과 같다. 어떤 가구든 일단 저장할 수 있어서 유연하지만, 나중에 방을 쓸 때 가구가 서로 안 맞거나 (스키마 불일치) 찾기 어려울 수 있다.

📢 섹션 요약: 스키마 온 라이트는 저장 시 스키마를 검증하여 데이터 품질을 보장하고, 스키마 온 리드는 읽기 시 스키마를 적용하여 다양한 데이터 유형과 분석 유연성을 제공한다.


Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)

두 방식의 동작 비교

┌─────────────────────────────────────────────────────────────────────────────┐
│                    스키마 온 라이트 vs 스키마 온 리드 동작 비교                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  [스키마 온 라이트 (Schema-on-Write)]                                        │
│  ─────────────────────────────────────                                      │
│                                                                             │
│  ① 스키마 정의 (Schema Creation)                                            │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  CREATE TABLE customers (                                             │ │
│  │    customer_id INT PRIMARY KEY,                                       │ │
│  │    name VARCHAR(100),                                                 │ │
│  │    email VARCHAR(255),                                                │ │
│  │    created_at TIMESTAMP                                               │ │
│  │  );                                                                  │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                              │                                                │
│                              ▼                                                │
│  ② 데이터 적재 시 검증 (Write Validation)                                    │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  INSERT INTO customers VALUES (1, '김철수', 'a@example.com', now()); │ │
│  │  → email이 VARCHAR(255) 범위内? → YES → 저장 ✓                       │ │
│  │                                                                       │ │
│  │  INSERT INTO customers VALUES (2, NULL, 'b@example.com', now());    │ │
│  │  → name이 NOT NULL 위반 → NO → 오류 발생 ✗                           │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                              │                                                │
│                              ▼                                                │
│  ③ 읽기 (Read - 이미 검증된 데이터)                                         │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  SELECT * FROM customers;                                            │ │
│  │  → 저장 시 검증 완료 → 빠른 읽기 가능                                  │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  [스키마 온 리드 (Schema-on-Read)]                                          │
│  ─────────────────────────────────────                                      │
│                                                                             │
│  ① 원시 데이터 저장 (Raw Storage - 스키마 없이)                              │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  // 파일 형식: JSON Lines, Parquet, Avro 등                          │ │
│  │  {customer_id: 1, name: "김철수", email: "a@example.com"}         │ │
│  │  {customer_id: 2, name: "이영희", email: "b@example.com", phone: "010..."}| │
│  │  {customer_id: 3, nickname: "영희", email: "c@example.com"}       │ │
│  │  //phone, nickname 등 schema 없는 필드도 그냥 저장됨                  │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                              │                                                │
│                              ▼                                                │
│  ② 읽기 시 스키마 정의 (Read-time Schema Definition)                        │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  // 분석 1: email만 필요할 때                                        │ │
│  │  SELECT customer_id, email FROM raw_customers;                       │ │
│  │                                                                       │ │
│  │  // 분석 2: phone도 필요할 때                                        │ │
│  │  SELECT customer_id, COALESCE(name, nickname) as name, email, phone  │ │
│  │  FROM raw_customers;                                                 │ │
│  │  // →COALESCE로 name/nickname 통합, phone이 없으면 NULL 처리        │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                              │                                                │
│                              ▼                                                │
│  ③ 스키마 불일치 handling                                                │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  // customer_id 3은 nickname 필드만 있어 name이 없음                 │ │
│  │  → 스키마 온 리드는 이를 오류로 처리하지 않고 NULL로 취급             │ │
│  │  → 데이터 손실 없이 모든 레코드 조회 가능                              │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

데이터 포맷과 스키마 온 리드

┌─────────────────────────────────────────────────────────────────────────────┐
│                    스키마 온 리드友善 데이터 포맷                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  [Parquet 형식]                                                            │
│  ─────────────                                                              │
│  • Columnar 저장 형식 (열 기반 저장)                                          │
│  • 파일 헤더에 스키마를 내장 (self-describing)                              │
│  • 읽기 시 스키마 정보를 활용 가능                                           │
│  • 분석 查询에 최적 (열 단위 압축, 스킵)                                    │
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  // Parquet 파일 구조                                                 │ │
│  │  ┌─────────────────────────────────────────────────────────────┐   │ │
│  │  │  File Header: Schema (customer_id:INT, name:STRING, ...)  │   │ │
│  │  ├─────────────────────────────────────────────────────────────┤   │ │
│  │  │  Row Group 1                                                │   │ │
│  │  │    Column Chunk: customer_id (INT)                         │   │ │
│  │  │    Column Chunk: name (STRING)                             │   │ │
│  │  │    Column Chunk: email (STRING)                            │   │ │
│  │  ├─────────────────────────────────────────────────────────────┤   │ │
│  │  │  Row Group 2                                                │   │ │
│  │  │    ...                                                      │   │ │
│  │  └─────────────────────────────────────────────────────────────┘   │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  [Avro 형식]                                                               │
│  ──────────                                                                │
│  • 행 기반 저장 형식 (Row-based)                                             │
│  • JSON 또는 binary 형태로 스키마를 별도 파일로 관리                         │
│  • 스키마 evolution (호환 가능한 스키마 변경) 지원                           │
│  • Kafka, streaming 데이터에 적합                                           │
│                                                                             │
│  [데이터 레이크에서의 스키마 온 리드 메타데이터 관리]                         │
│  ────────────────────────────────────────────                               │
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  Apache Hive Metastore / AWS Glue Data Catalog                      │ │
│  │  ────────────────────────────────────────────────────────────────│ │
│  │                                                                       │ │
│  │  Table Metadata:                                                      │ │
│  │  ┌───────────────────────────────────────────────────────────────┐ │ │
│  │  │  Table Name: raw_customers                                    │ │ │
│  │  │  Location: s3://datalake/raw/bronze/customers/               │ │ │
│  │  │  Format: Parquet                                              │ │ │
│  │  │  Schema:                                                      │ │ │
│  │  │    customer_id: int (nullable)                                 │ │ │
│  │  │    name: string (nullable)                                     │ │ │
│  │  │    email: string (nullable)                                     │ │ │
│  │  │    _partition_date: string (generated)                         │ │ │
│  │  │  Partitioned by: _partition_date                               │ │ │
│  │  └───────────────────────────────────────────────────────────────┘ │ │
│  │                                                                       │ │
│  │  ※ 파티션, location, format 등 메타데이터로 데이터Discovery 지원         │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

비교 결정 트리

┌─────────────────────────────────────────────────────────────────────────────┐
│                    스키마 온 라이트 vs 온 리드 선택 결정 트리                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│           ┌─────────────────────────────────────┐                          │
│           │  데이터 분석 방식이 무엇인가?           │                          │
│           └───────────────┬─────────────────────┘                          │
│                   사전 정의된 분석 │  │  분석 시점不确定/다양함              │
│                    (보고서, OLAP) │  │  (탐색적 분석, ML)                  │
│                           ▼        │  ▼                                    │
│                  ┌────────────────┴────────────────┐                      │
│                  │     스키마 온 라이트            │                      │
│                  │  ✅ 사전 검증으로 품질 보장     │                      │
│                  │  ✅ 일관된 데이터 구조         │                      │
│                  │  ✅ 빠른 읽기 성능             │                      │
│                  │  ❌ 유연성 제한                │                      │
│                  │  ❌ ETL 사전 처리 시간         │                      │
│                  └─────────────────────────────────┘                      │
│                                                                             │
│                  ┌────────────────────────────────┐                      │
│                  │     스키마 온 리드              │                      │
│                  │  ✅ 다양한 데이터 수용         │                      │
│                  │  ✅ 분석 시점 유연성            │                      │
│                  │  ✅ 데이터 수집 속도 빠름       │                      │
│                  │  ❌ 사후 스키마 관리 필요       │                      │
│                  │  ❌ 데이터 품질 위험           │                      │
│                  └────────────────────────────────┘                      │
│                                                                             │
│  [실무 활용: Hybrid 접근]                                                  │
│  ───────────────────────────                                              │
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  데이터 레이크에서 Bronze(Raw) → Silver(Cleansed) → Gold(Analysis) │ │
│  │                                                                       │ │
│  │  Bronze Zone: 스키마 온 리드 (원시 데이터 저장)                        │ │
│  │  Silver Zone: 스키마 온 라이트-ish (정제 후 검증된 데이터)             │ │
│  │  Gold Zone: 분석 가능 상태 ( schema 적용된 데이터)                    │ │
│  │                                                                       │ │
│  │  → 수집 단계에서는 유연성(온 리드), 분석 단계에서는 품질(온 라이트)     │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

[다이어그램 해설] 스키마 온 라이트와 스키마 온 리드는 각기 다른 장단점을 가진다. 스키마 온 라이트는 데이터 품질을 사전에 보장하지만 유연성이 제한되고, 스키마 온 리드는 유연성을 제공하지만 사후에 스키마 관리가 필요하다. 실무에서는 Bronze-Raw, Silver-Cleansed, Gold-Analysis 3단계로 나누어, 수집 단계에서는 온 리드의 유연성을, 분석 단계에서는 온 라이트의 품질을 적용하는 hybrid 접근이 흔히 사용된다.

📢 섹션 요약: 스키마 온 라이트는 사전 데이터 품질 보장과 일관된 구조를, 스키마 온 리드는 다양한 데이터 수용과 분석 유연성을 제공하며, 실무에서는 hybrid 접근이 흔히 사용된다.


Ⅲ. 결론

스키마 온 라이트와 스키마 온 리드는 데이터를 저장하고 읽는 방식에서根本적으로 다른 패러다임이다. 스키마 온 라이트는 사전에 스키마를 정의하여 데이터 품질을 보장하지만 분석의 유연성이 제한되고, 스키마 온 리드는 데이터를 원시 형태로 저장하여 다양한 분석을 가능하게 하지만 사후 스키마 관리가 필요하다. 실무에서는 데이터 레이크의 Bronze-Raw, Silver-Cleansed, Gold-Analysis 구조처럼 hybrid 접근을 취하여, 수집 단계에서는 온 리드의 유연성을, 분석 단계에서는 온 라이트의 품질을 적용하는 것이 일반적이다.

📢 섹션 요약: 스키마 온 라이트와 온 리드는 각각 데이터 품질과 분석 유연성 사이의 트레이드오프이며, 실무에서는 beide의 장점을活用하는 hybrid 접근이 권장된다.


핵심 인사이트 ASCII 다이어그램 (Concept Map)

┌─────────────────────────────────────────────────────────────────────────────┐
│                    Schema-on-Write vs Schema-on-Read Concept Map                │
│                                                                             │
│              ┌─────────────────────────────────┐                           │
              │  Schema-on-Write vs Schema-on-Read  │                           │
              └───────────────┬─────────────────┘                           │
│                              │                                               │
│         ┌────────────────────┼────────────────────┐                        │
│         ▼                    ▼                    ▼                        │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐               │
│  │ Schema-on-   │    │ Schema-on-  │    │    Hybrid    │               │
│  │    Write     │    │    Read     │    │   Approach   │               │
│  │              │    │              │    │ (실무권장)   │               │
│  │ ✅ 품질보장  │    │ ✅ 유연성   │    │ Bronze: 온리드│               │
│  │ ✅ 일관성   │    │ ✅ 빠른수집  │    │ Silver: 정제  │               │
│  │ ❌ 제한적   │    │ ❌ 사후관리  │    │ Gold: 분석   │               │
│  └──────────────┘    └──────────────┘    └──────────────┘               │
│         │                    │                    │                       │
│         └────────────────────┼────────────────────┘                        │
│                              ▼                                               │
│                   ┌─────────────────────┐                                  │
│                   │   DW / Data Lake  │                                  │
│                   │   (목적에 맞게 선택)│                                  │
│                   └─────────────────────┘                                  │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

참고

  • 스키마 온 라이트는 저장 시 스키마를 검증하고, 온 리드는 읽기 시 적용한다.
  • 온 라이트는 데이터 품질과 일관성을, 온 리드는 유연성과 다양한 데이터 수용성을 제공한다.
  • Parquet, Avro 등은 스키마 온 리드를支援하는 self-describing 형식이다.
  • 실무에서는 Bronze-Raw, Silver-Cleansed, Gold-Analysis hybrid 접근이 권장된다.
  • 데이터 레이크는 온 리드, 데이터 웨어하우스는 온 라이트에 기반한다.
  • 메타데이터 카탈로그(Hive Metastore, Glue Catalog) 활용이 스키마 온 리드 관리에 필수적이다.