---
id: cs-skip-list-persistent-data
title: Skip List / Persistent Data Structures
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [cs, data-structure, vibe-coding]
tech_stack: { language: "TS", applicable_to: ["CS"] }
applied_in: []
aliases: [skip list, persistent data, immutable, structural sharing, Hash Array Mapped Trie, HAMT, finger tree]
---

# Skip List / Persistent Data Structures

> Modern data structure. **Skip list (Redis), Persistent (Clojure, Immer)**. Lock-free + functional.

## 📖 핵심 개념
- Skip list: probabilistic balanced.
- Persistent: 매 변경 = 새 version.
- Structural sharing.
- Lock-free 친화.

## 💻 코드 패턴

### Skip list
```
모든 element 가 sorted.
매 element 가 random "tower" (1-N level).

Level 3:        [1] -------> [9]
Level 2:        [1] -> [4] -> [9]
Level 1:        [1] -> [4] -> [7] -> [9]
Level 0: [1] -> [3] -> [4] -> [7] -> [9]

Search:
- Top level 에서 시작.
- 매 level 가 forward / down.
- O(log N) average.
```

### TypeScript (간단)
```ts
class SkipNode<T> {
  value: T;
  forward: (SkipNode<T> | null)[];
  
  constructor(value: T, level: number) {
    this.value = value;
    this.forward = new Array(level).fill(null);
  }
}

class SkipList<T> {
  head: SkipNode<T>;
  
  constructor(private maxLevel: number = 16, private p: number = 0.5) {
    this.head = new SkipNode<T>(null!, maxLevel);
  }
  
  randomLevel(): number {
    let level = 1;
    while (Math.random() < this.p && level < this.maxLevel) level++;
    return level;
  }
  
  insert(value: T) {
    const level = this.randomLevel();
    const node = new SkipNode(value, level);
    
    const update = new Array<SkipNode<T>>(this.maxLevel);
    let current = this.head;
    
    for (let i = this.maxLevel - 1; i >= 0; i--) {
      while (current.forward[i] && current.forward[i]!.value < value) {
        current = current.forward[i]!;
      }
      update[i] = current;
    }
    
    for (let i = 0; i < level; i++) {
      node.forward[i] = update[i].forward[i];
      update[i].forward[i] = node;
    }
  }
  
  search(value: T): boolean {
    let current = this.head;
    for (let i = this.maxLevel - 1; i >= 0; i--) {
      while (current.forward[i] && current.forward[i]!.value < value) {
        current = current.forward[i]!;
      }
    }
    return current.forward[0]?.value === value;
  }
}
```

→ Insert / search / delete = O(log N).

### Skip list 의 사용
```
- Redis 의 sorted set (ZADD, ZRANGE).
- LevelDB / RocksDB (memtable).
- LSM tree 의 level.

→ Lock-free + 빠름.
```

### vs B-tree
```
B-tree: 정확 balance, complex.
Skip list: probabilistic, simple.

→ Implementation 가 simple.
Concurrent 가 친화 (lock-free).
```

### Persistent data structure
```
"매 변경 = 새 version. 옛 version 보존".

Immutable + structural sharing.
```

```ts
const list1 = [1, 2, 3];
const list2 = [...list1, 4];

// JS spread = O(N) copy.
// Persistent = O(log N) (structural sharing).
```

### HAMT (Hash Array Mapped Trie)
```
Persistent map 의 implementation.
- 32-way trie.
- 매 update = log32(N) node 새.
- 나머지 = share.

→ Clojure 의 PersistentHashMap.
Immer / immutable.js 의 backend.
```

### Immer (TS)
```ts
import produce from 'immer';

const state = { items: [{ id: 1, name: 'a' }] };

const newState = produce(state, draft => {
  draft.items.push({ id: 2, name: 'b' });
  draft.items[0].name = 'A';
});

// state 가 unchanged.
// newState 가 새.
// 공통 부분 = shared.
```

→ Mutable syntax + immutable result.

### immutable.js (legacy)
```ts
import { Map, List } from 'immutable';

const m = Map({ a: 1, b: 2 });
const m2 = m.set('a', 10);

// m 가 unchanged.
// m2 가 새.
```

→ Immer 가 modern. Immutable.js 가 legacy.

### Persistent의 가치
```
- Time travel debugging (옛 version 가져옴).
- React 의 referential equality (skip re-render).
- Concurrent (no lock, copy-on-write).
- Undo / redo.
```

### React + Immer
```ts
const [state, dispatch] = useReducer(produce((draft, action) => {
  switch (action.type) {
    case 'add': draft.items.push(action.item); break;
  }
}), initial);
```

→ Mutable syntax in reducer.

### Finger tree
```
Persistent sequence.
- Front / back access O(1).
- Concat O(log N).
- Splay similar.

→ Haskell / functional language 친화.
```

### Functional map
```
Clojure: PersistentHashMap.
Scala: immutable.Map.
Haskell: Data.Map.
JS: Immer / immutable.js / Mori.
```

### Database 의 persistent
```
LMDB: copy-on-write B-tree.
- 매 transaction = 새 root.
- 옛 reader 가 옛 root.
- MVCC 비슷.

→ Persistent 의 disk version.
```

### LSM tree (related)
```
- Memtable (skip list / sorted).
- SSTable (immutable).
- Compaction.

→ Persistent + skip list 의 combo.
```

→ [[CS_BTree_LSM_Storage]].

### Hash Array Mapped Trie (HAMT) 깊이
```
32-way branching:
- Root: 32 child max.
- 매 child = 32 grandchild.
- 5 level = 32^5 = 33M element.

Insert:
- Path 의 매 node 새.
- 다른 = share.
- O(log32 N) ≈ O(1).
```

### Reagent / Re-frame (ClojureScript)
```clojure
(re-frame.core/reg-event-db
  :add-item
  (fn [db [_ item]]
    (update db :items conj item)))
```

→ 매 update = new persistent map.

### React 18+ + persistent
```
React 의 reconciliation:
- Old state vs new state.
- Object.is comparison.
- Persistent = O(1) compare.
```

→ Performance 친화.

### Memory 사용
```
Mutable: 1 copy.
Persistent (HAMT): 1.x copy (sharing).

→ "Memory cost ↑" 가 가짜 — sharing 가 작음.
```

### Lock-free
```
Persistent + atomic pointer = no lock.

let state = atomic(initial);

function update() {
  while (true) {
    const old = state.load();
    const new_ = produce(old, ...);
    if (state.compareAndSwap(old, new_)) break;
  }
}
```

→ CAS (Compare-And-Swap) loop.

### Use case
```
- Redux / Zustand state.
- Undo / redo.
- Time travel debug.
- Concurrent.
- Functional programming.
- Database (LMDB, FoundationDB).
```

### 함정
```
- Persistent 가 매 update 의 cost (small but nonzero).
- Memory 가 큰 (history 누적).
- Garbage collection 의 pressure.
- 매 lib 의 API 다름.
```

### Performance
```
Mutable: O(1) update, no compare.
Persistent: O(log N) update, O(1) compare.

→ Read-heavy = persistent.
Write-heavy = mutable.
```

### Real-world
- **Clojure / ClojureScript**: 모두 persistent.
- **React + Redux**: persistent state.
- **Datomic**: persistent DB.
- **Redis**: skip list.
- **LMDB / FoundationDB**: copy-on-write.

## 🤔 의사결정 기준
| 작업 | 추천 |
|---|---|
| Sorted set | Skip list |
| Concurrent | Skip list / persistent |
| State management | Immer (persistent) |
| Time travel | Persistent |
| Functional | HAMT |
| Disk | LSM / LMDB |

## ❌ 안티패턴
- **모든 거 persistent**: write-heavy = slow.
- **Skip list manual**: library 사용.
- **No GC**: history 누적.
- **Persistent + 큰 history**: memory.
- **Lock + persistent 둘 다**: 의미 X.

## 🤖 LLM 활용 힌트
- Skip list = Redis sorted set.
- Persistent = HAMT (Clojure / Immer).
- Structural sharing = O(log N) memory.
- Lock-free 친화.

## 🔗 관련 문서
- [[CS_BTree_LSM_Storage]]
- [[CS_LockFree_Atomic]]
- [[CS_CRDT_Patterns]]
