331 lines
6.7 KiB
Markdown
331 lines
6.7 KiB
Markdown
---
|
||
id: arch-cell-based
|
||
title: Cell-based Architecture — blast radius 격리
|
||
category: Coding
|
||
status: draft
|
||
source_trust_level: B
|
||
verification_status: conceptual
|
||
created_at: 2026-05-09
|
||
updated_at: 2026-05-09
|
||
tags: [architecture, resilience, vibe-coding]
|
||
tech_stack: { language: "any", applicable_to: ["Architecture"] }
|
||
applied_in: []
|
||
aliases: [cell-based, cell architecture, bulkhead, blast radius, shuffle sharding, AWS cells]
|
||
---
|
||
|
||
# Cell-based Architecture
|
||
|
||
> 큰 system 가 1 cell. cell 가 다 죽으면 모두 down. **여러 cell + 사용자 가 1 cell 만 — blast radius 작아**. AWS, Slack, GitHub 의 모던 architecture.
|
||
|
||
## 📖 핵심 개념
|
||
- Cell = 작은 self-contained system (web + DB + cache).
|
||
- 사용자 별 1 cell 배정.
|
||
- Cell 간 isolation.
|
||
- Cell 가 죽으면 그 cell 의 사용자만 영향.
|
||
|
||
## 💻 코드 패턴
|
||
|
||
### 일반 system
|
||
```
|
||
모든 user → LB → app fleet → 1 DB
|
||
|
||
→ DB 죽으면 100% down.
|
||
App fleet bug 가 100% 영향.
|
||
```
|
||
|
||
### Cell-based
|
||
```
|
||
User → Router →
|
||
Cell A (10% user) → app A + DB A
|
||
Cell B (10% user) → app B + DB B
|
||
...
|
||
Cell J (10% user) → app J + DB J
|
||
|
||
→ Cell A 죽음 = 10% 만 down.
|
||
```
|
||
|
||
### Cell routing
|
||
```ts
|
||
function getCell(userId: string): string {
|
||
const hash = murmur32(userId);
|
||
const cellIndex = hash % NUM_CELLS;
|
||
return `cell-${cellIndex}`;
|
||
}
|
||
|
||
app.use((req, res, next) => {
|
||
const cell = getCell(req.user.id);
|
||
res.set('X-Cell', cell);
|
||
// Forward to cell
|
||
req.cell = cell;
|
||
next();
|
||
});
|
||
```
|
||
|
||
### Sticky routing
|
||
```
|
||
사용자 가 항상 같은 cell.
|
||
- Hash(user_id) % N
|
||
- Cookie 저장
|
||
- Geo (region)
|
||
|
||
→ Cache hit, locality.
|
||
```
|
||
|
||
### Cell size
|
||
```
|
||
큰 cell: 운영 적음, 큰 blast radius
|
||
작은 cell: 운영 많음, 작은 blast
|
||
|
||
Sweet spot: 1-10% user / cell.
|
||
- 100k user = 10-100 cell.
|
||
- 큰 system = N+ cells.
|
||
```
|
||
|
||
### Shuffle sharding (AWS)
|
||
```
|
||
N cell 중 매 user 가 K (e.g. 2-3) cell.
|
||
- User1 → Cell A, B
|
||
- User2 → Cell A, C
|
||
- User3 → Cell B, D
|
||
|
||
→ Cell A 죽음 = User1 가 B 로 fallback. 100% available.
|
||
```
|
||
|
||
```ts
|
||
function getShards(userId: string): string[] {
|
||
const seed = hash(userId);
|
||
return [`cell-${seed % N}`, `cell-${(seed + 7) % N}`];
|
||
}
|
||
```
|
||
|
||
### Bulkhead 비유
|
||
```
|
||
배 의 격실 (수밀 격벽).
|
||
1 곳 침수 = 그 격실 만.
|
||
|
||
Software:
|
||
- 1 thread pool 다 = 거기서만 hang
|
||
- 1 DB conn pool 다 = 그 service 만
|
||
```
|
||
|
||
### Cell 의 데이터
|
||
```
|
||
Option A: Cell 별 DB
|
||
Cell A — DB A
|
||
Cell B — DB B
|
||
|
||
Option B: Shared DB + tenant 분리
|
||
All cells → 1 DB (tenant ID)
|
||
|
||
→ A 가 isolation 강함. B 가 simple.
|
||
```
|
||
|
||
### Cross-cell read
|
||
```
|
||
"User A 가 User B 의 data 본다"
|
||
- A 와 B 가 다른 cell?
|
||
→ Cell B 에 query (cross-cell)
|
||
→ Network + 2x complexity
|
||
|
||
→ 큰 system 만. 같은 cell 친화 / global table.
|
||
```
|
||
|
||
### Global metadata
|
||
```
|
||
일부 data 가 cell 무관.
|
||
- Pricing
|
||
- Catalog
|
||
- Feature flag
|
||
|
||
→ Global DB + cell 가 read replica.
|
||
```
|
||
|
||
### Migration (cell 변경)
|
||
```
|
||
사용자 가 cell 변경 가능 — rare.
|
||
1. Source cell 에 read-only mark
|
||
2. Data copy → target cell
|
||
3. Verify
|
||
4. Routing 변경
|
||
5. Source cell 에서 삭제
|
||
|
||
→ Rebalance 시 발생.
|
||
```
|
||
|
||
### Cell autonomy
|
||
```
|
||
한 cell 가 down 해도:
|
||
- 다른 cell 가 영향 X
|
||
- 다른 cell 가 down 한 거 모름 (의존 X)
|
||
|
||
→ Shared dependencies = single point of failure.
|
||
Auth, payment 가 외부 service?
|
||
```
|
||
|
||
### Auth shared
|
||
```
|
||
Auth 가 cell 별 = scaling 어려움 (token 어느 cell?).
|
||
Auth 가 외부 (Auth0, Keycloak) → cell 가 verify.
|
||
|
||
→ Stateless cell.
|
||
```
|
||
|
||
### Deploy
|
||
```
|
||
N cell × deploy frequency.
|
||
1 cell deploy → verify → 다음 cell.
|
||
|
||
Canary:
|
||
1 cell 가 v2 → 10% user 가 v2.
|
||
→ Blast radius 작음 + 검증.
|
||
```
|
||
|
||
### 모니터링
|
||
```
|
||
Per-cell metric:
|
||
- cell-A: latency, error rate, ...
|
||
- cell-B: ...
|
||
|
||
Aggregated dashboard.
|
||
1 cell anomaly = visible.
|
||
```
|
||
|
||
### Failure injection
|
||
```
|
||
Chaos:
|
||
- Cell A 의 service kill
|
||
- Cell B 의 DB connection drop
|
||
|
||
→ 다른 cell 영향 X 검증.
|
||
```
|
||
|
||
### AWS 의 cell-based
|
||
```
|
||
S3, DynamoDB, IAM, CloudFront 가 cell.
|
||
1 cell ~10% user.
|
||
1 cell incident = 10% 영향 + 다른 cell 가 cover (failover).
|
||
```
|
||
|
||
### GitHub 의 cell-based (since 2022)
|
||
```
|
||
1 cell = 1 region of repos.
|
||
새 repo = 1 cell 배정.
|
||
|
||
→ Cell A incident = 그 cell 의 repo 만.
|
||
```
|
||
|
||
### Slack 의 cell-based
|
||
```
|
||
1 workspace = 1 cell.
|
||
Cell-based scaling + isolation.
|
||
```
|
||
|
||
### When 도입
|
||
```
|
||
- 큰 system (>1k user, > $$$ revenue)
|
||
- High availability 중요
|
||
- 1 incident = 큰 손해
|
||
- Independent scale 가능
|
||
|
||
→ 작은 system = overkill.
|
||
```
|
||
|
||
### Multi-region (다른 layer)
|
||
```
|
||
Region: 다른 지리.
|
||
Cell: region 안 / 사이.
|
||
|
||
→ N region × M cell/region.
|
||
Region disaster (data center 화재) ≠ cell incident (bug).
|
||
```
|
||
|
||
### Cost
|
||
```
|
||
- 운영 복잡 ↑
|
||
- Tooling (cell-aware deploy, monitoring)
|
||
- Cross-cell scenario 처리
|
||
|
||
→ Investment.
|
||
큰 system 가치 큰.
|
||
```
|
||
|
||
### Tenant model 비교
|
||
```
|
||
Single-tenant 1 DB / customer:
|
||
- 작은 cell (1 customer)
|
||
- 가장 isolated
|
||
- 비싼 운영
|
||
|
||
Multi-tenant 1 DB:
|
||
- 모두 1 곳
|
||
- 가장 cheap
|
||
- 가장 큰 blast
|
||
|
||
Cell:
|
||
- 중간 (10-1000 customer / cell)
|
||
- Sweet spot
|
||
```
|
||
|
||
→ [[Backend_Multi_Tenant_Architecture]].
|
||
|
||
### Implementation 어려움
|
||
```
|
||
1. Cell routing (가장 큰 결정)
|
||
2. Cell-aware tooling (deploy, monitoring)
|
||
3. Migration story (cell 변경)
|
||
4. Shared service (auth, billing)
|
||
5. Cross-cell data 의 flow
|
||
|
||
→ 시작 = 1 cell. 성장 = 분리.
|
||
```
|
||
|
||
### Strangler 식 도입
|
||
```
|
||
1. Modular monolith
|
||
2. 1 module 가 cell 후보 (e.g. tenant 별)
|
||
3. 분리 테스트
|
||
4. 점진 cell 화
|
||
```
|
||
|
||
### 작은 개념 — Bulkhead
|
||
```ts
|
||
// 작은 system 도 thread pool 별.
|
||
const dbPool = new Pool({ max: 20 });
|
||
const externalApiPool = new Pool({ max: 5 });
|
||
|
||
// External API 가 hang → external pool 다 → DB pool 영향 X.
|
||
```
|
||
|
||
→ Cell 의 작은 version.
|
||
|
||
## 🤔 의사결정 기준
|
||
| 상황 | 추천 |
|
||
|---|---|
|
||
| 작은 system | Modular monolith |
|
||
| 큰 + HA | Cell-based |
|
||
| 1k+ tenant | Cell |
|
||
| 매우 critical (banking) | Shuffle sharding |
|
||
| 1 region | Cell within region |
|
||
| Multi-region | Region + cells |
|
||
| Tenant 별 isolation 강 | Single-tenant DB |
|
||
|
||
## ❌ 안티패턴
|
||
- **1 monolith + 1 DB**: 큰 blast radius.
|
||
- **Cell 도입 + shared DB**: isolation 무효.
|
||
- **Cross-cell scenario 흔함**: cost 폭발.
|
||
- **Cell migration 없음**: rebalance 어려움.
|
||
- **Per-cell deploy 없음**: 1 deploy 가 모두 영향.
|
||
- **Per-cell monitoring 없음**: incident locate 어려움.
|
||
- **Shared auth 가 cell A 의 일부**: SPOF.
|
||
|
||
## 🤖 LLM 활용 힌트
|
||
- Cell-based = blast radius 격리 의 답.
|
||
- Shuffle sharding = 작은 cell + redundancy.
|
||
- Sticky routing (hash, cookie) 가 cell 의 중심.
|
||
- 작은 system = bulkhead 만 (thread pool, conn pool).
|
||
|
||
## 🔗 관련 문서
|
||
- [[Arch_Modular_Monolith]]
|
||
- [[Backend_Multi_Tenant_Architecture]]
|
||
- [[Backend_Geo_Replication]]
|