💡 핵심 인사이트 델타 인코딩(Delta Encoding)은 **"연속적인 데이터 값들 사이의 차이(차분, Delta)만을 저장하여 데이터 압축을実現하는 인코딩 기법"**입니다. 시계열 데이터, 버전 관리 시스템, 네트워크 프로토콜 등에서相邻 데이터 간의 차이는 원본 값보다 훨씬 작은 경우가 많다는점을利用합니다. 예컨대 "100, 101, 102, 105, 108, 110" 대신 "(100, +1, +1, +3, +3, +2)"를 저장하면 더 작은数值로 표현 가능합니다. Facebook의 Gorilla 압축 알고리즘이 델타 인코딩을 시계열 압축에率先 적용하여著名해졌습니다.
Ⅰ. 델타 인코딩의基本 원리
[델타 인코딩 개념]
원본 데이터: [100, 103, 107, 112, 115, 118, 120]
델타 적용: [100, +3, +4, +5, +3, +3, +2]
압축 전:
- 7개 값 × 8바이트 (float64) = 56바이트
압축 후:
- 첫 값: 100 (8바이트)
- 델타 값: [+3, +4, +5, +3, +3, +2]
- 델타 값이 작으면? → 더 작은 데이터 타입으로 표현 가능
(예: 1바이트 부호 있는 정수로 표현 가능)
결과: 압축률 50~80% 향상
델타 인코딩의 문제점:累积 오차
[문제: 누적 에러 (Cumulative Error)]
원본: [100, 103, 107, 112, 115, 118, 120]
델타: [100, +3, +4, +5, +3, +3, +2]
첫 값 복원: 100 ✓
두 번째 복원: 100 + 3 = 103 ✓
세 번째 복원: 103 + 4 = 107 ✓
...
문제 상황: 전송 중 델타 값 중 하나가 손상되면?
원본: 100, +3, +4, +5, +3, +3, +2
손상 시: 100, +3, +7, +5, +3, +3, +2 ← +4가 +7로 오류!
복원 시: 100 → 103 → 110 (오류!) → 115 → ...
→ 이후 모든 값이 틀어짐! (오류 전파)
해결책: 체크포인트 (Periodic Reset)
[체크포인트 방식]
원본: [100, 103, 107, 112, 115, 118, 120]
델타: [100, +3, +4, +5, +3, +3, +2]
↑
매 3번째 값마다 원본을 그대로 저장 (체크포인트)
구조: [100, +3, +4, | 112, +3, +3, | 120]
체크포인트↑ 체크포인트↑ 체크포인트↑
복원:
- 100부터 +3, +4 적용 → 107 ✓
- 112부터 +3, +3 적용 → 118 ✓
- 120부터 복원 → 120 ✓
→ 한 섹션에서 오류가 나도 다음 체크포인트에서 자동 복구
II. Gorilla 압축 알고리즘: 델타 인코딩의 극적进化
Facebook (Meta)가 2015년에 공개한 시계열 압축 알고리즘:
[Gorilla 압축 알고리즘]
핵심 특징:
1. 델타 인코딩 + XOR 압축
2. 제어문을利用하여값 encoding
3. 참조 프레임(previous value) 활용
압축 과정:
Case 1: 첫 값 (initial)
→ 그냥 저장 (8바이트)
Case 2: 델타가 0
→ "0" 비트만 저장 (1비트!)
Case 3: 델타가 작고 범위内
→ 델타 값만 저장 (수 비트 ~ 수십 비트)
Case 4: 델타가 새로움 (앞値과 크게 다름)
→ 새 값 자체를 저장 (원본만큼)
활용:
- Facebook 내부 시계열 DB (Gorilla는 Prometheus와 InfluxDB에 사용)
-InfluxDB: Gorilla/Zstd 압축 조합으로 시계열 데이터 90% 압축
Gorilla 코드 예시
# Gorilla 압축의 핵심 개념 (실제 구현은 C++/Go)
class GorillaCompressor:
def __init__(self):
self.previous_value = 0
self.previous_timestamp = 0
self.previous_delta = 0
self.output = bytearray()
def compress(self, timestamp, value):
# 1. 델타 계산
delta = timestamp - self.previous_timestamp
delta_of_delta = delta - self.previous_delta
# 2. 값 델타 계산
value_delta = value - self.previous_value
# 3. 델타 오브 더eltas 인코딩
if delta_of_delta == 0:
self.output.append(0b0) # 1비트
elif -63 <= delta_of_delta <= 64:
self.output.append(0b10) # 2비트
self.output.append(delta_of_delta) # 7비트
# ... (더 많은 비트 활용)
self.previous_value = value
self.previous_delta = delta
III. 델타 인코딩의 다양한 활용 사례
1. 버전 관리 시스템 (Git)
[Git의 델타 인코딩]
파일 V1: "Hello World"
파일 V2: "Hello World!"
Git 저장 방식:
- V1: 전체 내용 저장
- V2: V1에서 바뀐 부분만 저장
Git 내부:
- packfile: 델타 오브제트들
- .idx: 델타를 빠르게查找するための색인
2. 네트워크 프로토콜 (WebSocket)
[WebSocket에서의 델타 인코딩]
상황: 실시간 대시보드 (수치가 초단위로 更新)
방법 1: 매번 전체 값 전송
-带宽: 매번 8바이트 × 수십 개 항목
방법 2: 델타 인코딩
- 전체 값 1회 전송
- 이후: 변화분만 전송
- 예: "현재 온도 23.5도, 0.1도 상승" 이라는 식으로
결과: 대역폭 70~90% 절감
3. 시계열 DB 압축 (InfluxDB / Prometheus)
-- InfluxDB에서 Gorilla 압축이 자동으로 적용
-- 사용자는意識하지 않고도 압축된 스토리지 사용
-- 예: 100만 포인트 데이터가 압축 후 수십 MB 수준
-- Cassandra: 시계열 데이터에 델타 인코딩 적용
CREATE TABLE sensor_data (
sensor_id TEXT,
timestamp TIMESTAMP,
value DOUBLE,
PRIMARY KEY (sensor_id, timestamp)
) WITH compression = {
'class': 'DeltaCompressor'
};
IV. 델타 인코딩 vs 다른 압축 기법
[압축 기법 비교]
델타 인코딩:
- 장점: 연속된 값들 사이 차분 저장 → 차분 < 원본인 경우 효과적
- 단점: 차분이 큰 데이터에서는 효과 없음
- 적합: 시계열, 버전 관리, 부드러운 곡선
Run-Length Encoding (RLE):
- "AAAAAABBBBBB" → "6A5B" (반복 횟수 저장)
- 델타와 달리 값의 변화보다 반복に着目
LZ77 / LZSS:
- "이전出现过文字列"을参照 (参照位置 + 길이)
- 델타와 달리 문자열 기반
Zstd (Facebook):
- 딥러닝 기반 사전 모델 + 델타 인코딩 혼합
- 압축률과 속도 모두 우수
Ⅴ. 델타 인코딩 도입 시 고려사항と 📢 비유
적합한 데이터 특성:
- 값이 시간에 따라 부드럽게 변하는 데이터 (온도, 주가, 센서값)
- 연속적이며局所적 변화가 있는 데이터
- 차분 분포가 원본보다 작은 경우
불적합한 데이터:
- 랜덤하게 변하는 데이터 (加密된文本, 난수)
- 값이剧烈하게 변하는 경우 (점프, 이상치 多発)
- 이례값이 많은 경우
체크포인트 전략:
# 체크포인트 빈도 선택 가이드
if 데이터_변화_예측_가능:
# 규칙적인 시계열: 30~60분마다 체크포인트
CHECKPOINT_INTERVAL = 3600 # 1시간
elif 데이터_오류_민감:
# 금융/의료: 더 짧은 체크포인트
CHECKPOINT_INTERVAL = 300 # 5분
else:
# 일반: 기본값
CHECKPOINT_INTERVAL = 1800 # 30분
📢 섹션 요약 비유: 델타 인코딩은 **"점점 줄어드는 물고기 잡는 이야기"**와 같습니다. 큰 물고기(원본 값)를 잡는 것은 어렵지만, 작은 물고기(차분)를 잡는 것은 쉽습니다. 델타 인코딩은 **"원래 물고기를 놓치고, 물고기의 움직임(차분)만 기록해두면, 나중에 그 움직임을 되돌려서 원래 위치를 알 수 있다"**는 원리입니다. Facebook의 Gorilla 알고리즘은 여기에 **"움직임의 정도에 따라 다양한 크기의 그릇을 사용한다"**는智能化을 더한 것입니다. 움직임이 작으면(값이 조금 변하면) 수비트로 처리하고, 움직임이 크면(값이 크게 변하면) 그에 맞는 큰 그릇을 사용합니다. **"작은 변화는 작게, 큰 변화는 크게 담아서 효율적으로 기록하는 것"**이 델타 인코딩의 핵심입니다.