콤팩션 (Compaction) - LSM 트리 구조 병합 및 툼스톤 정리
핵심 인사이트 (3줄 요약)
- 본질: 콤팩션 (Compaction)은 극단적인 쓰기 속도를 위해 데이터를 지우거나 덮어쓰지 않고 새로운 파일(SSTable)로 무한정 쌓아두기만 하는 LSM-Tree 엔진에서, 파편화된 파일들을 백그라운드에서 주기적으로 하나로 뭉쳐(Merge) 중복을 제거하고 정돈해 주는 청소부이자 심장 박동 메커니즘이다.
- 가치: 콤팩션을 멈추면 수천 개의 파일 파편으로 인해 쿼리 읽기 속도가 극단적으로 느려지고(Read Amplification), 무의미한 중복 데이터가 디스크를 가득 채운다(Space Amplification). 콤팩션은 이 두 가지 병목을 해소하여 시스템을 다시 날쌘 상태로 회복시킨다.
- 툼스톤(Tombstone)과의 융합: LSM 구조에서 데이터를 삭제(
DELETE)할 때는 직접 지우는 대신 '이 데이터는 죽었음'이라는 가상의 묘비 마크(Tombstone)를 적어둔다. 콤팩션 프로세스가 파일들을 뭉칠 때 이 툼스톤과 그 아래의 과거 데이터를 만나면 두 데이터를 동반 영구 소멸시켜 비로소 진짜 디스크 용량 반환을 이루어낸다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
-
개념: 콤팩션 (Compaction)은 메모리 버퍼(MemTable)에서 디스크로 밀어내어져(Flush) 끝없이 생성되는 다수의 불변(Immutable) 상태인 SSTable 파일들을 읽어 들여, 가장 최신 버전의 데이터만 살리고 과거의 낡은 데이터와 삭제 마커(Tombstone)를 버린 뒤, 새롭고 거대한 하나의 SSTable로 다시 구워내는(Merge) 디스크 정리 프로세스다.
-
필요성: LSM-Tree의 기본 철학(377번 문서 참조)은 '절대 원래 자리를 찾아 덮어쓰지 않는다(No In-place Update)'는 것이다. 만약
회원ID=5의 이름이 '김철수'에서 '이영희'로 바뀌면, 예전 김철수 기록은 1번 파일에 놔둔 채 10번 파일에 이영희를 새로 적어 넣는다. 삭제할 때도 15번 파일에회원ID=5 (Tombstone 마크)만 적어 넣는다. 이렇게 1년이 지나면 디스크에는 1만 개의 조각난 SSTable 파일이 널브러져 있게 된다. 클라이언트가ID=5를 찾으려 하면 DB는 가장 최근 파일부터 1번 파일까지 수천 번의 디스크 I/O를 일으키며 미친 듯이 뒤져야 한다. 이를 '읽기 증폭(Read Amplification)'이라고 한다. 이 재앙을 막기 위해 누군가는 주기적으로 방 청소를 해서 1만 개의 노트를 1개의 깨끗한 백과사전으로 압축해 주어야 하며, 그것이 콤팩션의 유일한 존재 이유다. -
등장 배경 및 딜레마: 빅데이터를 다루는 Cassandra, RocksDB, HBase 아키텍트들의 가장 큰 두통거리는 바로 콤팩션이다. 콤팩션은 필수 불가결하지만, 파일을 읽고 새로 쓰는 과정에서 CPU 코어를 심각하게 점유하고 어마어마한 디스크 I/O 대역폭을 갉아먹기 때문이다. 한 번 쓴 데이터가 콤팩션을 거치며 디스크에 여러 번 다시 씌어지는 현상을 '쓰기 증폭(Write Amplification)'이라 부르며, 이로 인해 피크 시간대에 콤팩션이 돌면 정상적인 앱 트래픽의 응답이 뚝뚝 끊기는 치명적인 스파이크가 발생한다. 어떻게 하면 자원을 덜 쓰면서 파일들을 우아하게 합칠 것인가가 분산 데이터베이스 튜닝의 핵심 역량이 되었다.
이 다이어그램은 콤팩션이 부재할 때 쌓이는 중복 데이터의 문제와, 콤팩션 수행 후 툼스톤(삭제) 처리를 거쳐 디스크가 깨끗해지는 병합 과정을 시각적으로 보여준다.
┌───────────────────────────────────────────────────────────────┐
│ LSM-Tree 콤팩션 (Merge & Tombstone Purge) 메커니즘 │
├───────────────────────────────────────────────────────────────┤
│ │
│ [ 콤팩션 전: 무질서하게 쌓여있는 다수의 SSTable 파일들 ] │
│ │
│ - 파일 1 (어제) : [ ID:1(A), ID:2(B), ID:5(C) ] │
│ - 파일 2 (오늘) : [ ID:2(X), ID:3(D) ] │
│ - 파일 3 (방금 전): [ ID:5 (Tombstone 🪦) ] │
│ │
│ ★ 문제: ID:2를 찾으려면 파일 2를 뒤져야 하고, 파일 1의 B와 C는 │
│ 쓸모없는 쓰레기 데이터(Space Amplification)로 용량만 차지함.│
│ │
│ ▼ (백그라운드 콤팩션 스레드 가동) │
│ ▼ 1, 2, 3번 파일을 메모리로 읽어와서 병합(Merge) 시작 │
│ │
│ [ 콤팩션 후: 최신값만 추려낸 깨끗한 새 단일 파일 생성 ] │
│ │
│ - 통합된 새 파일 : [ ID:1(A), ID:2(X), ID:3(D) ] │
│ │
│ ★ 해결 결과 분석: │
│ 1. (ID:2) 최신 값인 X만 남고 구버전 B는 버려짐. │
│ 2. (ID:5) 툼스톤(방금 전)과 진짜 값(어제)이 만나 서로를 끌어안고 │
│ 흔적도 없이 영구 소멸(Purge)됨. 디스크 공간 회수 완료! │
│ 3. 기존 1, 2, 3번 파일은 안전하게 디스크에서 삭제(unlink) 됨. │
└───────────────────────────────────────────────────────────────┘
[다이어그램 해설] 이 구조도는 콤팩션이 일어나는 'K-way 병합(Merge) 정렬' 알고리즘의 직관적인 모습이다. SSTable 파일들은 이미 내부적으로 키(ID) 순서대로 정렬되어 있다. 따라서 콤팩션 스레드는 여러 파일의 첫머리 포인터를 짚고 나란히 읽어 나가며(순차 읽기), 같은 키를 만났을 때는 타임스탬프(버전)가 가장 최신인 놈만 살리고 구버전은 버리는 효율적인 병합 병합 정렬(Merge Sort)을 수행한다. 특히 가장 중요한 메커니즘은 삭제를 의미하는 **Tombstone (묘비명)**이다. LSM에서는 DELETE 쿼리를 날릴 때 디스크의 과거 기록을 지우지 못하고 ID=5(죽음)이라는 마커를 새로 쓸 뿐이다. 이 마커가 콤팩션을 통해 낡은 파일에 묻혀있던 진짜 데이터 ID=5(C)를 조우하는 순간, 알고리즘은 두 데이터를 결과 파일에 쓰지 않고 허공으로 증발시켜 버린다. 이 과정을 거쳐야 비로소 RDBMS의 DELETE처럼 물리적인 하드디스크 빈 용량 확보(Space Reclamation)가 이루어진다.
- 📢 섹션 요약 비유: 평일 내내 입었던 옷, 수건, 찢어진 양말(Tombstone)을 빨래통(디스크)에 계속 쌓아두다가(Append-only), 일요일이 되면 빨래를 다 엎어서 낡고 찢어진 건 버리고 깨끗하게 개어서 하나의 서랍장에 압축해 넣는(Compaction) 주말 대청소 작업과 같습니다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
콤팩션의 3대 핵심 비용 지표 (Amplification 트레이드오프)
콤팩션 전략을 튜닝할 때는 물리학의 열역학 법칙처럼, 하나를 얻으면 반드시 하나를 내어주어야 하는 3대 증폭(Amplification) 지표 간의 타협점을 찾아야 한다.
| 지표명 | 개념 및 발생 원인 | 최소화를 위한 희생 요소 | 시스템 위협 |
|---|---|---|---|
| 쓰기 증폭 (Write Amp) | 애플리케이션이 1MB를 썼는데, 콤팩션으로 인해 파일이 합쳐지고 다시 씌어지면서 실제 디스크에는 10MB가 씌어지는 현상 | 읽기 증폭 또는 공간 증폭 증가 | 디스크 I/O 고갈, SSD 수명 극심한 단축 (Flash Wear-out) |
| 읽기 증폭 (Read Amp) | 사용자 쿼리로 데이터 1건을 찾기 위해, 조각난 수십 개의 SSTable 파일을 열어서 수십 번의 논리적 디스크 스캔이 발생하는 현상 | 더 잦은 콤팩션을 돌려 쓰기 증폭 증가 | 쿼리 레이턴시 폭발, CPU 과부하, 타임아웃 장애 유발 |
| 공간 증폭 (Space Amp) | 실제 유효한 데이터는 100GB인데, 구버전 찌꺼기와 툼스톤이 방치되어 하드디스크를 200GB, 300GB씩 잡아먹고 있는 현상 | 지속적인 콤팩션을 통한 디스크 깎아내기(쓰기 증폭) | 서버 스토리지 용량 고갈에 따른 인프라 예산 낭비 |
양대 콤팩션 전략 아키텍처 (Size-Tiered vs Leveled)
이러한 트레이드오프를 조절하기 위해 아키텍트들은 파일들을 묶어내는 두 가지 상반된 철학적 접근법을 만들어냈다. 워크로드 성격에 따라 반드시 어느 한쪽을 선택해야 한다.
┌──────────────────────────────────────────────────────────────────┐
│ LSM 콤팩션 2대 전략 구조 비교 (Size-Tiered vs Leveled) │
├──────────────────────────────────────────────────────────────────┤
│ │
│ [ A. 크기 기반 콤팩션 (Size-Tiered Compaction, STCS) ] │
│ - 철학: "크기가 비슷한 파일이 4개 모이면 무조건 합쳐서 더 큰 걸 만들자!"│
│ │
│ (10MB) 🗂️🗂️🗂️🗂️ ───(Merge)───▶ (40MB) 🗃️ │
│ (40MB) 🗃️🗃️🗃️🗃️ ───(Merge)───▶ (160MB) 📁 │
│ │
│ * 장점: 병합을 자주 안 해서 쓰기 증폭(Write Amp)이 제일 낮음 (고속 쓰기).│
│ * 단점: 큰 파일 안에 오래된 쓰레기 데이터가 너무 많고(공간 낭비), │
│ 여러 파일을 동시에 뒤져야 해서 읽기 증폭(Read Amp)이 큼. │
│ │
│ [ B. 레벨 기반 콤팩션 (Leveled Compaction, LCS) ] │
│ - 철학: "파일 크기를 작게 고정(10MB)하고, 각 층수(Level)를 두어 │
│ 레벨 내에서는 Key가 절대 안 겹치게 엄격히 분류하자!" │
│ │
│ L0 (10MB x 4) : 🗂️ 🗂️ 🗂️ 🗂️ (여기만 Key 중복 허용, 꽉 차면 아래로) │
│ │ 밀어내기 │
│ ▼ (하위 레벨과 Merge) │
│ L1 (10MB x 10): [A~C] [D~F] [G~I] ... (Key가 완벽히 쪼개져 있음) │
│ │ 꽉 차면 또 밀어내기 │
│ ▼ │
│ L2 (10MB x100): [A~A1] [A2~B] [B1~C] ... (용량이 10배씩 커짐) │
│ │
│ * 장점: 특정 키를 찾을 때 각 레벨당 딱 1개의 파일만 뒤지면 됨. │
│ 읽기 증폭(Read Amp)이 극적으로 낮고, 낭비 공간 거의 없음. │
│ * 단점: 데이터가 한 단계 내려갈 때마다 계속 다시 씌어지므로 │
│ 쓰기 증폭(Write Amp) 페널티가 엄청남. 디스크 혹사. │
└──────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 이 구조도는 Cassandra나 RocksDB의 테이블 엔진 튜닝 시 가장 중요한 아키텍처적 결단을 시각화한 것이다. 크기 기반 (Size-Tiered) 방식은 단순히 덩치 비슷한 놈들끼리 모아 뭉치는 게 끝이다. 로직이 단순해 쓰기 성능이 매우 뛰어나지만, 데이터가 100GB짜리 거대한 파일로 뭉쳐지면 그 파일 하나를 콤팩션할 때 여유분으로 디스크 100GB가 추가로 필요하다는 무서운 단점(순간 공간 폭발)이 있다. 반면 레벨 기반 (Leveled) 방식은 엄격한 도서관 사서와 같다. L1, L2, L3로 층을 나누고 층이 내려갈 때마다 용량이 10배씩 커진다. 가장 중요한 특징은 L1 층부터는 **"같은 층 안에 있는 파일들끼리는 저장된 키(Key) 범위가 절대 겹치지 않는다"**는 점이다. 따라서 클라이언트가 조회 쿼리를 날렸을 때 최상위 L0를 제외하고는 각 층당 무조건 파일 1개만 뒤져보면 데이터 존부 여부를 알 수 있어 검색이 광속으로 끝난다. 하지만 이 완벽한 정렬 상태를 유지하기 위해, 위층에서 데이터 하나가 쏟아져 내려오면 아래층 파일 여러 개를 열어 헤집고 다시 쓰는 엄청난 콤팩션 노가다(쓰기 증폭)를 백그라운드 스레드가 쉴 새 없이 해야만 한다.
- 📢 섹션 요약 비유: 크기 기반(Size-Tiered) 방식은 방 정리를 할 때 10리터 쓰레기봉투 4개가 차면 50리터 봉투 하나에 다 쏟아붓는 방식이고, 레벨 기반(Leveled) 방식은 옷장에 칸막이를 쳐놓고 위칸 옷이 넘치면 아래칸으로 한 장씩 빼면서 바지와 티셔츠 종류별로 칼같이 각 잡아 다시 개어 넣는 방식입니다.
Ⅲ. 융합 비교 및 다각도 분석 (Comparison & Synergy)
워크로드 특성별 콤팩션 전략 매트릭스
비즈니스 도메인의 I/O 패턴을 이해하지 못하고 디폴트 콤팩션을 방치하면 디스크가 수명을 다하거나 읽기 타임아웃이 터진다.
| 워크로드 성격 | 권장 콤팩션 전략 | 선택의 아키텍처적 논거 | 실제 사례 (Use Case) |
|---|---|---|---|
| 순수 쓰기 중심 (Write-heavy) | Size-Tiered (STCS) | 쓰기 증폭을 낮추어 순간적으로 쏟아지는 트래픽 스파이크를 I/O 병목 없이 메모리/디스크로 수용 | IoT 센서 로깅, 시계열 이벤트 수집, 클릭스트림 저장 |
| 읽기 위주 및 잦은 Update (Read/Update-heavy) | Leveled (LCS) | 잦은 덮어쓰기로 인한 파편화를 억제하고 검색 경로를 최적화하여 빠른 조회 응답 시간 보장 | 사용자 프로필 정보 갱신, 장바구니 세션, 추천 엔진 피드 |
| 순수 시계열 보관 (Time-Series) | Time-Window (TWCS) | 시계열 데이터는 과거의 데이터를 다시 수정할 일이 없으므로, 특정 시간대(예: 하루 치) 파일만 병합하고 일정 시간 후 파일 자체를 통째로 삭제(TTL)하여 콤팩션 부하를 제로화 | 일일 트래픽 통계, 서버 CPU 모니터링 메트릭 |
툼스톤(Tombstone)과 가비지 컬렉션(GC)의 융합 관점
-
JVM(Java Virtual Machine) 언어로 개발된 데이터베이스(Cassandra 등)에서 콤팩션 스레드가 무리하게 돌면, 수많은 SSTable 파일을 메모리로 퍼올리며 엄청난 객체를 생성하여 JVM의 가비지 컬렉션(GC Pause)을 유발, 클러스터 멈춤 현상을 일으킨다.
-
이 문제를 해결하기 위해 최근 스토리지 엔진은 C/C++로 개발된 RocksDB 엔진을 차용하거나, 콤팩션 메모리를 오프힙(Off-heap) 영역으로 빼내어 GC의 방해를 피하는 메모리-스토리지 융합 아키텍처로 진화하고 있다.
-
📢 섹션 요약 비유: 콤팩션 전략을 잘못 고르는 것은, 한여름에 겨울 패딩을 입고 한겨울에 반팔을 입는 것과 같습니다. 쓰기 폭우가 쏟아질 때는 가벼운 우비(Size-Tiered)를 입고, 정교한 검색 지도를 그려야 할 때는 두꺼운 등산복(Leveled)을 입어야 시스템이 버틸 수 있습니다.
Ⅳ. 실무 적용 및 기술사적 판단 (Strategy & Decision)
실무 시나리오 및 의사결정
-
시나리오 — 디스크 I/O 고갈로 인한 콤팩션의 역습: 대규모 NoSQL 클러스터에서 며칠간 프로모션 트래픽으로 파일이 수천 개 쌓이자, 백그라운드 레벨 콤팩션(LCS)이 폭주하기 시작했다. 디스크의 I/O 대역폭을 콤팩션 스레드가 100% 점유해 버려, 정작 고객의 결제(Write) 요청을 처리하지 못하고 타임아웃 에러를 내뱉는 마비 사태가 발생했다. (Death by Compaction)
- 의사결정: 콤팩션이 앱 트래픽을 잡아먹지 못하도록 I/O 쓰로틀링 (I/O Throttling) 파라미터를 강제로 튜닝해야 한다. 콤팩션 스레드 개수 한도(
compaction_throughput_mb_per_sec)를 제한하여 백그라운드 작업이 디스크를 다 쓰지 못하게 브레이크를 건다. 파일이 제때 안 합쳐져서 읽기 속도가 조금 느려지는 페널티(Read Amp)를 감수하더라도, 당장의 메인 쓰기 트래픽(서비스 생존)을 살려내는 것이 위기 상황의 올바른 아키텍트 판단이다.
- 의사결정: 콤팩션이 앱 트래픽을 잡아먹지 못하도록 I/O 쓰로틀링 (I/O Throttling) 파라미터를 강제로 튜닝해야 한다. 콤팩션 스레드 개수 한도(
-
안티패턴 — 광역 삭제(Bulk Delete) 남용으로 인한 툼스톤 좀비 사태: 개발자가 실수로 들어간 1,000만 건의 테스트 데이터를 지우기 위해
DELETE FROM table WHERE ...쿼리를 날렸다. 지웠는데 디스크 용량은 오히려 늘어나고(툼스톤 추가), 이 테이블을 조회하는 모든 쿼리의 타임아웃이 터지기 시작했다.- 결과:
DELETE를 날린다고 당장 파일이 사라지는 것이 아니다. 1,000만 개의 툼스톤(삭제 마크)이 새로 디스크에 쌓인다. 심지어 조회 쿼리가 들어오면, DB는 정상 데이터인지 찾기 위해 수많은 파일을 읽고 거기서 나온 1,000만 개의 툼스톤 마커까지 꾸역꾸역 메모리에 올려서 일일이 제외 필터링을 하느라 메모리가 폭발하고 조회 지연이 발생한다. - 의사결정: LSM 구조에서 대량 삭제는 쥐약이다. 가급적 TTL (Time To Live)을 설정해 데이터가 만료 시간 후 자연스럽게 자동 드롭되게 설계하거나, 파티션이나 테이블 통째로 삭제(Drop Table / Truncate)하는 방식을 써서 툼스톤 생성 자체를 아키텍처 레벨에서 회피해야 한다.
- 결과:
콤팩션 관리 및 튜닝을 위한 의사결정 트리
┌───────────────────────────────────────────────────────────────────┐
│ LSM-Tree 콤팩션 병목 해결 및 전략 의사결정 트리 │
├───────────────────────────────────────────────────────────────────┤
│ │
│ [클러스터 응답 지연(Latency Spike) 발생 감지] │
│ │ │
│ ▼ │
│ 지연 원인이 "디스크 I/O 대역폭 고갈(100%)" 때문인가? │
│ ├─ 예 ──▶ [콤팩션 쓰로틀링(Throttling) 활성화] │
│ │ - 콤팩션 스레드 점유율을 낮춰 정상 트래픽 양보. │
│ │ - 너무 파편화가 심하면 Size-Tiered 전략으로 하향 변경.│
│ │ │
│ └─ 아니오 (CPU나 I/O 여유는 있는데 쿼리 자체만 느림) │
│ │ │
│ ▼ │
│ 조회 쿼리 시 너무 많은 툼스톤(Tombstone)을 스캔하고 있는가? │
│ ├─ 예 ──▶ [gc_grace_seconds 튜닝 및 수동 콤팩션 고려] │
│ │ - 죽은 데이터가 빨리 소멸되도록 강제 병합 실행. │
│ │ - 앱 단에서 과도한 Delete 쿼리 날리는지 리뷰. │
│ │ │
│ └─ 아니오 ──▶ [읽기 증폭(Read Amp) 의심] │
│ - 블룸 필터(Bloom Filter) 메모리 할당량 증설. │
│ - Leveled 콤팩션으로 상향 변경하여 파편화 차단.│
│ │
│ 판단 포인트: "쓰기가 죽으면 I/O를 열어주고, 읽기가 죽으면 파일을 합쳐라."│
└───────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 분산 스토리지 운영의 핵심은 이 세밀한 트레이드오프 저울질에 있다. 초보자는 읽기가 느려졌다고 무작정 더 빡센 레벨 콤팩션을 설정하는데, 이는 빈대(읽기 지연) 잡으려다 초가삼간(디스크 I/O) 다 태우는 짓이 될 수 있다. 항상 시스템 모니터링을 통해 현재 디스크의 I/O 큐(Queue) 상태와 툼스톤 스캔 횟수 메트릭을 확인한 후, I/O 여유가 남을 때만 백그라운드 병합 템포를 끌어올리는 우상향 곡선을 그려야 한다. 또한 툼스톤은 분산 노드 간의 일관성을 맞추기 위해 gc_grace_seconds (기본 10일) 동안은 콤팩션이 돌더라도 억지로 디스크에 지우지 않고 유지시키는데, 이 유예 기간 설정과 Anti-entropy(수동 노드 리페어) 주기가 어긋나면 죽은 데이터가 좀비처럼 부활하는 치명적 에러가 발생하므로 두 시스템 설정값의 연동 여부를 반드시 체크해야 한다.
- 📢 섹션 요약 비유: 콤팩션은 체력(I/O 대역폭)을 갉아먹는 강도 높은 대청소입니다. 시험 전날 밤(트래픽 피크 타임)에 갑자기 방 청소를 시작하면 정작 시험공부(정상 서비스)를 망치게 되므로, 청소는 한가한 주말에 조금씩 나누어서 하는 지혜가 필요합니다.
Ⅴ. 기대효과 및 결론
정량/정성 기대효과
| 구분 | 콤팩션 튜닝 미흡 (방치) | 콤팩션 최적화 전략 적용 | 개선 효과 |
|---|---|---|---|
| 정량 | 수백 개 파일 뒤지느라 Read Latency 폭발 | Leveled 방식 또는 Bloom Filter 방어로 스캔 최소화 | 읽기(Read) 응답 속도 상위 99%(p99) 지연 방어 |
| 정량 | 낡은 데이터와 툼스톤으로 디스크 용량 포화 | 무용지물 데이터 주기적 소멸 (Purge) 처리 | 스토리지 점유 공간 (Space Amplification) 획기적 반환 |
| 정성 | 피크 타임 I/O 100% 병목으로 앱 장애 | I/O 쓰로틀링과 시계열 전용(TWCS) 콤팩션 분리 | 트래픽 폭증 시에도 안정적인 쓰기 가용성 유지 |
미래 전망
- 클라우드 오프로드 (Offloaded Compaction): 현대의 클라우드 네이티브 데이터베이스(Amazon Aurora, Snowflake)는 무거운 콤팩션 연산을 데이터베이스 컴퓨팅 노드가 직접 하지 않는다. 백그라운드의 저렴한 별도 서버풀이나 분산 스토리지 계층 자체에서 콤팩션을 대신 돌려줌으로써, 메인 DB 인스턴스의 CPU가 오직 사용자 쿼리 응답에만 100% 집중할 수 있도록 아키텍처를 분리하는 패러다임이 안착하고 있다.
- 머신러닝 기반 자율 튜닝: 시스템 트래픽의 주야간 패턴과 디스크 I/O 병목 상태를 AI가 실시간으로 분석하여, 콤팩션 스레드 개수와 병합 트리거 임계치를 런타임에 동적으로 스스로 조절해 주는 자율 주행(Autonomous) 튜닝 기능이 RocksDB 플러그인 생태계에서 활발히 연구되고 있다.
참고 표준
- RocksDB Tuning Guide (Meta/Facebook): LSM-Tree 및 콤팩션 파라미터 최적화에 관한 업계 표준 가이드라인문
- Apache Cassandra Architecture / Hinted Handoff & Compaction Model: 분산 시스템의 가용성과 성능 튜닝의 교과서적 구현 모델
"저장하는 것만큼이나, 어떻게 우아하게 버릴 것인가가 중요하다." LSM-Tree 엔진에서 콤팩션은 단순한 청소 작업이 아니라, 시스템의 수명과 검색 성능을 연장하는 강력한 심폐소생술이다. 무작정 쏟아져 들어오는 빅데이터의 해일 속에서, 불필요한 데이터의 사체(Tombstone)를 치우고 의미 있는 핵심만을 새로운 결정체로 압축해 내는 콤팩션의 철학은 제한된 컴퓨팅 자원을 극한까지 쥐어짜 내야 하는 모든 아키텍트가 깊이 숙지해야 할 분산 엔지니어링의 정수다.
- 📢 섹션 요약 비유: 콤팩션은 광산에서 캐낸 엄청난 양의 흙더미(초기 SSTable)를 불순물(낡은 데이터와 툼스톤)과 섞여 있는 상태로 방치하지 않고, 거대한 용광로에 집어넣어 불순물은 다 태워버리고 순수한 금괴(최신 단일 파일) 하나로 제련해 내는 숭고한 정제 작업입니다.
📌 관련 개념 맵 (Knowledge Graph)
| 개념 명칭 | 관계 및 시너지 설명 |
|---|---|
| LSM-Tree (Log-Structured Merge-Tree) | 극단적 순차 쓰기(Sequential Write)를 달성하기 위해 콤팩션(디스크 정리)의 부하라는 대가를 기꺼이 지불한 저장 엔진의 근간이다. |
| 툼스톤 (Tombstone) | Immutable 구조에서 DELETE를 모사하기 위해 쓰는 삭제 마커로, 콤팩션이 일어날 때 진짜 데이터를 안고 동반 소멸하는 핵심 트리거다. |
| 쓰기 증폭 (Write Amplification) | 콤팩션이 여러 번 돌면서 사용자가 쓴 1바이트의 데이터가 디스크에 물리적으로 수십 번 다시 씌어지는 LSM 엔진의 가장 큰 약점 지표다. |
| 블룸 필터 (Bloom Filter) | 콤팩션을 덜 해서 파일이 수백 개로 조각나 있더라도, "이 파일엔 데이터 없음!"을 즉석에서 판별해 불필요한 디스크 읽기 증폭을 막아주는 마법사다. |
| Anti-entropy (Repair) | 분산 노드 간의 불일치를 맞추기 위해 낡은 데이터를 찾아 전송하면, 이 새로운 복원 데이터를 디스크에 예쁘게 섞어 넣는 마지막 단계가 바로 콤팩션이다. |
👶 어린이를 위한 3줄 비유 설명
- 매일매일 일기를 쓰면서 새로운 공책을 끝도 없이 만들기만 하면(LSM-Tree), 나중에 지난주 무슨 일이 있었는지 찾으려 할 때 산더미 같은 공책들을 다 뒤져야 해서 너무 힘들어요.
- 그래서 일요일 밤이 되면 모든 공책을 바닥에 엎어놓고, 오타 난 거나 지우고 싶었던 내용(툼스톤)은 다 찢어버린 뒤, 진짜 중요한 내용만 새롭고 두꺼운 일기장 1권에 예쁘게 다시 적어 넣는답니다.
- 이 귀찮지만 꼭 필요한 **'주말 일기장 합치기 청소'**를 컴퓨터 세상에서는 **콤팩션(Compaction)**이라고 불러요!