269. 수직 분할 (Vertical Fragmentation)
핵심 인사이트 (3줄 요약)
- 본질: 수직 분할은 테이블의 열(Attribute) 단위로 데이터를 물리적으로 분할하여, 각 분할이 원래 테이블의 일부 컬럼만을 포함하는 분할 기법이다.
- 가치: 자주 함께 사용되는 컬럼 그룹을 분리하여 I/O를 줄이고, 민감 정보와 일반 정보를 분리하여 보안성을 높이며, 특정 컬럼만 빠르게 조회할 수 있다.
- 융합: 수평 분할, 분할 정합성, 정규화, 분산 데이터베이스, 조인 연산과 밀접하게 연관된다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
개념 정의
수직 분할(Vertical Fragmentation)은 테이블의 열(Attribute) 단위로 데이터를 물리적으로 분할하는 기법이다. 각 분할(Fragment)은 원래 테이블의 일부 컬럼을 포함하며, 반드시 Primary Key를 모든 분할에 포함해야 조인를 통해 원래 테이블을 재구성할 수 있다.
필요성
테이블에 많은 컬럼이 있을 때, 특정 컬럼만 자주 조회하는 경우에도 전체 행을 읽어야 하는 I/O浪费가 발생한다. 또한 개인정보와 일반 정보를 함께 저장하면 보안 위험이 있고 관리가 어렵다. 수직 분할을 통해 이러한 문제를 해결할 수 있다.
배경
수직 분할은 1980년대 분산 데이터베이스 연구에서 비롯되었으며, 이후 다양한 관계형 데이터베이스에서 활용되고 있다. 특히 개인정보 보호, 성능 최적화, 저장 공간 관리 등에서 효과적이다.
비유
수직 분할은병원 차트와 같다. 환자의 기본 정보(성명, 나이)와 상세 의료 정보(진단, 처방, 검사 결과)를 함께 저장하면 보安全管理が 어렵다. 그러나部門별로 분리하면, 담당자만 자신의부문 정보를 볼 수 있어 보안성이 높아지고, 필요한 부문의 차트만 빠르게 조회할 수 있다.
📢 섹션 요약: 수직 분할은 열 단위로 데이터를 물리적 분할하여 I/O 감소, 보안 향상, 관리 편의성을 제공하는 기법이다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
수직 분할 동작
┌─────────────────────────────────────────────────────────────────────────────┐
│ 수직 분할 동작 구조 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ [원래 테이블: employees] │
│ ┌──────┬──────────┬──────────┬──────────┬──────────┬──────────┐ │
│ │ emp_id│ name │ email │ phone │ salary │ address │ │
│ ├──────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │
│ │ E001 │ Kim │a@a.com │ 010-1111 │ 5000 │ Seoul │ │
│ │ E002 │ Lee │b@b.com │ 010-2222 │ 6000 │ Busan │ │
│ │ E003 │ Park │c@c.com │ 010-3333 │ 5500 │ Incheon │ │
│ └──────┴──────────┴──────────┴──────────┴──────────┴──────────┘ │
│ │
│ [수직 분할 결과] │
│ │
│ employees_main (emp_id, name): -- 기본 정보 분할 │
│ ┌──────┬──────────┐ │
│ │ emp_id│ name │ │
│ ├──────┼──────────┤ │
│ │ E001 │ Kim │ │
│ │ E002 │ Lee │ │
│ │ E003 │ Park │ │
│ └──────┴──────────┘ │
│ │
│ employees_contact (emp_id, email, phone): -- 연락처 분할 │
│ ┌──────┬──────────┬──────────┐ │
│ │ emp_id│ email │ phone │ │
│ ├──────┼──────────┼──────────┤ │
│ │ E001 │a@a.com │ 010-1111 │ │
│ │ E002 │b@b.com │ 010-2222 │ │
│ │ E003 │c@c.com │ 010-3333 │ │
│ └──────┴──────────┴──────────┘ │
│ │
│ employees_salary (emp_id, salary, address): -- 민감 정보 분할 │
│ ┌──────┬──────────┬──────────┐ │
│ │ emp_id│ salary │ address │ │
│ ├──────┼──────────┼──────────┤ │
│ │ E001 │ 5000 │ Seoul │ │
│ │ E002 │ 6000 │ Busan │ │
│ │ E003 │ 5500 │ Incheon │ │
│ └──────┴──────────┴──────────┘ │
│ │
│ [재구성: emp_id 기준 JOIN] │
│ SELECT * FROM employees_main m │
│ JOIN employees_contact c ON m.emp_id = c.emp_id │
│ JOIN employees_salary s ON m.emp_id = s.emp_id; │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
수직 분할 정합성 규칙
┌─────────────────────────────────────────────────────────────────────────────┐
│ 수직 분할 정합성 규칙 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. 완전성 (Completeness) │
│ ───────────────────── │
│ • 원래 테이블의 모든 컬럼이 분할에 포함 │
│ • employees (6컬럼) = employees_main (2컬럼) + │
│ employees_contact (3컬럼) + │
│ employees_salary (3컬럼) - PK 중복 = 6컬럼 ✓ │
│ │
│ 2. 재구성 가능성 (Reconstruction) │
│ ───────────────────────── │
│ • Primary Key (emp_id) 기준 JOIN으로 원래 테이블 재구성 가능 │
│ • employees_main ⋈ employees_contact ⋈ employees_salary = employees ✓ │
│ │
│ 3. 중복 없음 (Disjointness) │
│ ──────────────────── │
│ • Primary Key를 제외한 컬럼이 중복되지 않음 │
│ • emp_id는 모든 분할에 중복 포함 (재구성을 위해 필수) │
│ • name, email, phone, salary, address: 중복 없음 ✓ │
│ │
│ ⚠️ 중요: Primary Key가 없는 테이블은 수직 분할이 어려움 │
│ → 해결: 행 식별자를 추가하여 PK로 사용 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
수직 분할 전략
┌─────────────────────────────────────────────────────────────────────────────┐
│ 수직 분할 전략 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. 사용 빈도 기반 분할 │
│ ───────────────────── │
│ • 자주 함께 조회되는 컬럼 그룹을 하나의 분할로 구성 │
│ • 예: 직원 목록 조회 시 name만 자주 사용 → name만 별도 분할 │
│ │
│ 2. 업데이트 빈도 기반 분할 │
│ ───────────────────── │
│ • 자주 업데이트되는 컬럼과 거의 변경되지 않는 컬럼 분리 │
│ • 예: 주소는 자주 변경, 이름은 거의 변경 안함 → 분리 │
│ │
│ 3. 보안 수준 기반 분할 │
│ ───────────────────── │
│ • 보안 등급이 다른 컬럼을 분리 │
│ • 예: 일반 정보와 민감 정보 분리 │
│ • salary, address → HR 부서만 접근 가능 │
│ │
│ 4. 컬럼 크기 기반 분할 │
│ ───────────────────── │
│ • 큰 크기 컬럼(TEXT, BLOB)과 작은 크기 컬럼 분리 │
│ • 예: profile_image (BLOB)만 별도 분할 → 조회 시 I/O 절약 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 수직 분할의 장점 │ │
│ │ │ │
│ │ • I/O 감소: 필요한 컬럼만 읽음 │ │
│ │ • 보안 향상: 민감 정보를 별도 관리 │ │
│ │ • 저장 공간 절약: 압축 효율 향상 │ │
│ │ • 백업/복구 유연성: 민감 정보만 별도 백업 │ │
│ │ │ │
│ │ 수직 분할의 단점 │ │
│ │ │ │
│ │ • 전체 데이터 조회 시 조인 오버헤드 증가 │ │
│ │ • 분할 관리 복잡도 증가 │ │
│ │ • PK 관리 부담 증가 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 수직 분할의 핵심은 Primary Key를 모든 분할에 공통으로 포함하는 것이다. 이렇게 해야 분할된 테이블들을 조인하여 원래 테이블을 완벽히 재구성할 수 있다. Primary Key가 없으면 튜플을正しく 식별할 수 없어 재구성이 불가능하다.
📢 섹션 요약: 수직 분할은 반드시 Primary Key를 모든 분할에 포함해야 하며, 사용 빈도, 업데이트 빈도, 보안 수준, 컬럼 크기 등을 고려하여 분할 전략을 수립해야 한다.
Ⅲ. 구현 및 실무 응용 (Implementation & Practice)
Oracle 수직 분할
-- Oracle: 테이블을 물리적으로 분리 (수직 분할 효과)
-- 메인 테이블: 기본 정보
CREATE TABLE employees_main (
emp_id NUMBER PRIMARY KEY,
name VARCHAR2(100)
);
-- 연락처 테이블
CREATE TABLE employees_contact (
emp_id NUMBER PRIMARY KEY REFERENCES employees_main(emp_id),
email VARCHAR2(100),
phone VARCHAR2(20)
);
-- 민감 정보 테이블
CREATE TABLE employees_sensitive (
emp_id NUMBER PRIMARY KEY REFERENCES employees_main(emp_id),
salary NUMBER,
address VARCHAR2(200)
);
-- 뷰를 통한 투명성 제공
CREATE VIEW employees AS
SELECT
m.emp_id,
m.name,
c.email,
c.phone,
s.salary,
s.address
FROM employees_main m
LEFT JOIN employees_contact c ON m.emp_id = c.emp_id
LEFT JOIN employees_sensitive s ON m.emp_id = s.emp_id;
-- 조회: 뷰를 통해 단일 테이블처럼 조회 가능
SELECT * FROM employees WHERE emp_id = 1;
PostgreSQL 수직 분할
-- PostgreSQL: Inheritance를利用した수직 분할 (제한적)
-- 메인 테이블
CREATE TABLE employees (
emp_id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
-- 파생 테이블
CREATE TABLE employees_contact (
emp_id INTEGER PRIMARY KEY,
email VARCHAR(100),
phone VARCHAR(20)
) INHERITS (employees);
-- 주의: PostgreSQL의 inheritance는 완전한 수직 분할 지원이 아님
-- → 뷰, 트리거 등을活用하여 구현 필요
MongoDB 임베디드 문서 (수직 분할 효과)
// MongoDB: 문서 설계를 통한 수직 분할 효과
// 분리된 컬렉션 (수직 분할 유사)
db.employees.insertOne({
emp_id: "E001",
name: "Kim"
});
db.employees_contact.insertOne({
emp_id: "E001",
email: "kim@example.com",
phone: "010-1111-1111"
});
db.employees_salary.insertOne({
emp_id: "E001",
salary: 5000,
address: "Seoul"
});
// 조인 (lookup)
db.employees.aggregate([
{
$lookup: {
from: "employees_contact",
localField: "emp_id",
foreignField: "emp_id",
as: "contact"
}
},
{
$lookup: {
from: "employees_salary",
localField: "emp_id",
foreignField: "emp_id",
as: "salary"
}
}
]);
📢 섹션 요약: Oracle, PostgreSQL, MongoDB 등 주요 DB에서 수직 분할을 구현할 수 있으며, 뷰와 조인을 통해 투명성을 제공할 수 있다.
Ⅳ. 결론
수직 분할은 열 단위로 데이터를 물리적 분할하여 I/O 감소, 보안 향상, 관리 편의성을 제공하는 기법이다. 반드시 Primary Key를 모든 분할에 포함해야 하며, 분할 정합성 규칙을 만족해야 한다. 사용 빈도, 보안 수준, 컬럼 크기 등을 고려하여 분할 전략을 수립해야 한다.
📢 섹션 요약: 수직 분할은 열 단위 분할로 I/O와 보안을 최적화하지만, Primary Key 포함과 조인 오버헤드를 고려해야 한다.
핵심 인사이트 ASCII 다이어그램 (Concept Map)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Vertical Fragmentation Concept Map │
│ │
│ ┌───────────────────────────┐ │
│ │ Vertical Fragmentation │ │
│ │ (수직 분할) │ │
│ └───────────┬───────────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 사용 │ │ 보안 │ │ 크기 │ │
│ │ 빈도 │ │ 수준 │ │ 기반 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ⚠️ Primary Key는 모든 Fragment에 공통 포함! │ │
│ │ 분할 정합성: 완전성 | 재구성 (JOIN) | 중복없음 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
참고
- 수직 분할은 열(Attribute) 단위로 데이터를 물리적 분할한다.
- 반드시 Primary Key를 모든 분할에 공통으로 포함해야 한다.
- JOIN으로 원래 테이블을 재구성할 수 있다.
- 사용 빈도, 보안 수준, 컬럼 크기 등을 고려하여 분할한다.
- 분할 정합성 규칙(완전성, 재구성 가능성, 중복 없음)을 만족해야 한다.