# SAM 10,000 테넌트 스케일링 로드맵

> **작성일**: 2026-02-22
> **성격**: 가상 시나리오 — 세계 최고 수준 엔지니어링 팀이 설계한다는 가정

---

## 1. 현재 상태 진단

### 1.1 현재 아키텍처 요약

```
브라우저 → Nginx → PHP-FPM(20 workers) → Laravel → MySQL 8.0 (단일)
서버: 2코어/3.8GB RAM | 배포: 수동 git pull | 모니터링: 없음 | 캐시: 없음
```

### 1.2 핵심 병목 지점

| 영역 | 현재 | 10,000 테넌트 시 문제 | 심각도 |
|------|------|---------------------|--------|
| DB | MySQL 단일 | 커넥션 폭발, 슬로우 쿼리 | 치명적 |
| 컴퓨팅 | FPM 20워커 | 동시 요청 20개 제한 | 치명적 |
| 캐시 | 없음 | 모든 요청이 DB 직행 | 치명적 |
| 큐 | DB 드라이버 | 큐 자체가 DB 압박 | 심각 |
| 검색 | SQL LIKE | 219개 테이블 풀스캔 | 심각 |
| 배포 | 수동 git pull | 다운타임, 롤백 불가 | 높음 |
| 모니터링 | 없음 | 장애 인지 불가 | 높음 |

### 1.3 가장 먼저 죽는 곳

- 동시 사용자 **20명** → FPM 워커 전부 점유 → 504 Timeout
- 동시 사용자 **200명** → MySQL `max_connections`(151) 고갈
- 테넌트 **1,000개** → 권한 UNION 3개 쿼리가 매 요청마다 실행

---

## 2. 5단계 로드맵 개요

```
Phase 1 (0~3개월)   캐시 + 모니터링 + 서버 업그레이드       →   100 테넌트
Phase 2 (3~6개월)   DB 복제 + K8s + S3 + 검색 엔진         → 1,000 테넌트
Phase 3 (6~9개월)   마이크로서비스 + 이벤트 아키텍처         → 3,000 테넌트
Phase 4 (9~12개월)  DB 샤딩 + 테넌트 티어링 + 멀티리전     → 10,000 테넌트
Phase 5 (12~18개월) 관측성 고도화 + 카오스 엔지니어링       → 10,000+ 테넌트
```

---

## 3. Phase 1: 기초 체력 (0~3개월) → 100 테넌트

### 3.1 Redis 도입 (최우선)

| 대상 | 캐시 TTL | 효과 |
|------|---------|------|
| 세션 저장소 | 2시간 | DB 세션 테이블 부하 제거 |
| 권한 캐시 | 5분 | UNION 3개 쿼리 제거 (매 요청) |
| 메뉴 트리 | 10분 | 중첩 쿼리 제거 |
| 공통 코드 | 1시간 | `common_codes` 반복 조회 제거 |
| Laravel 큐 | - | `database` → `redis` 드라이버 전환 |

**예상 효과**: DB 쿼리 **60~70% 감소**, 응답 시간 **3~5배 개선**.

### 3.2 모니터링 구축

Grafana + Prometheus + Laravel Telescope + MySQL slow_log.

**핵심 알림**: FPM 워커 사용률 >80%, MySQL 커넥션 >100, 응답 시간 >2초, 큐 적체 >1000건 → Slack 알림.

### 3.3 서버 업그레이드 + CI/CD

| 항목 | 현재 | Phase 1 |
|------|------|---------|
| CPU/RAM | 2코어/3.8GB | 8코어/32GB |
| 스토리지 | HDD | NVMe SSD |
| FPM | 20 워커 | 100 워커 |
| 배포 | 수동 git pull | Jenkins CI/CD (무중단 rolling) |

---

## 4. Phase 2: 수평 확장 (3~6개월) → 1,000 테넌트

### 4.1 아키텍처

```
브라우저 → LB(L7) → App Server ×N → Redis Cluster
                                   → MySQL Primary + Replica ×2
                                   → S3 + CDN (정적/업로드 파일)
```

### 4.2 핵심 변경

| 영역 | 변경 | 효과 |
|------|------|------|
| **K8s** | HPA 기반 오토스케일링 (API 3~10 pods) | 트래픽에 따라 자동 확장 |
| **DB R/W 분리** | `config/database.php`에 read/write 설정 | 읽기 부하 80% Replica로 분산 |
| **파일 → S3** | Laravel Filesystem → S3 + CloudFront | 서버 간 파일 공유, CDN 가속 |
| **검색 엔진** | SQL LIKE → Meilisearch | 밀리초 응답, 형태소 분석, 오타 허용 |

---

## 5. Phase 3: 마이크로서비스 (6~9개월) → 3,000 테넌트

### 5.1 서비스 분리

```
모놀리스(sam-api) → Auth | Product | Order | MES | Finance | Notification
```

**분리 순서**: ① 알림 (독립적, 비동기) → ② MES (변경 빈도 높음) → ③ 인증 (가용성 최우선)

### 5.2 이벤트 기반 전환

동기 호출 체인을 이벤트 발행으로 전환한다. 주문 생성 시 재고 차감/알림/회계를 비동기 처리.

**메시지 브로커**: Redis Streams 또는 RabbitMQ. 응답 시간 2초 → 200ms.

### 5.3 API Gateway

Kong/Traefik으로 테넌트별 Rate Limiting, 인증 검증, 요청 라우팅, 응답 캐싱 통합.

---

## 6. Phase 4: 대규모 멀티테넌시 (9~12개월) → 10,000 테넌트

### 6.1 DB 샤딩

```
Shard Router (tenant_id 기반) → Shard 0 | Shard 1 | Shard 2 ...
                                 각 Shard = Primary + Replica
```

`tenant_id`가 파티션 키이므로 크로스 샤드 조인 불필요 — SAM의 강점.

### 6.2 테넌트 티어링

| Tier | 자원 | SLA | Rate Limit |
|------|------|-----|-----------|
| Enterprise | 전용 DB/Redis/Pod | 99.99% | 1000/분 |
| Business | 공유 (높은 우선순위) | 99.9% | 300/분 |
| Standard | 공유 | 99.5% | 60/분 |

### 6.3 멀티리전

한국(Primary) + 일본/동남아(Secondary) 리전. DB 복제 + Global Load Balancer로 지리적 라우팅.

---

## 7. Phase 5: 엔터프라이즈 성숙 (12~18개월) → 10,000+

| 영역 | 도입 | 목적 |
|------|------|------|
| **관측성** | Jaeger(분산추적) + Loki(중앙로그) + PagerDuty | 전체 서비스 체인 추적 |
| **카오스 엔지니어링** | DB 다운, Pod Kill, 네트워크 지연 주입 | 복원력 검증 |
| **데이터 파이프라인** | CDC(Debezium) → 데이터 웨어하우스 | 운영 DB에서 분석 쿼리 분리 |
| **배포** | Blue-Green + Canary (5% → 100%) | 30초 이내 롤백 |

---

## 8. 기술 스택 진화 요약

| 영역 | 현재 | Phase 1 | Phase 2 | Phase 4 |
|------|------|---------|---------|---------|
| 서버 | 단일 2코어 | 단일 8코어 | K8s 3+ 노드 | 멀티리전 |
| DB | MySQL 단일 | + 쿼리 최적화 | Primary + Replica ×2 | Shard ×N |
| 캐시 | 없음 | Redis 단일 | Redis Cluster | 테넌트별 격리 |
| 큐 | DB | Redis | Redis | 티어별 큐 |
| 배포 | 수동 | Jenkins CI/CD | K8s Rolling | Canary |
| 모니터링 | 없음 | Grafana | + Telescope | + 카오스 |

---

## 9. 가장 중요한 3가지

**1. Redis (=산소)**: 캐시 없이 10,000 테넌트는 **절대 불가능**. 권한 UNION 쿼리 3개 + 메뉴 + 세션이 매 요청마다 실행된다. Redis 하나로 DB 부하 60% 감소.

**2. DB R/W 분리 (=심장)**: ERP 읽기:쓰기 = 8:2. Replica 2대 추가로 DB 부하 1/3 분산. Laravel `config/database.php` 변경만으로 적용.

**3. 관측성 (=눈)**: 모니터링 없이 스케일링은 눈 감고 운전하는 것. 슬로우 쿼리 + 응답 시간 + 알림부터 시작.

---

## 10. SAM 특수 고려사항

### 10.1 tenant_id 기반 격리

- **강점**: `BelongsToTenant` 스코프 일관 적용, 크로스 테넌트 조인 불필요 → 샤딩에 유리
- **개선 필요**: `tenant_id` 인덱스 첫 번째 컬럼 여부 전수 검사, `deleted_at` 누적 데이터 파티셔닝

### 10.2 권한 시스템 최적화

3중 UNION 쿼리가 매 요청 실행된다. 개선: ① Redis 권한 캐시(TTL 5분) → ② 변경 시 해당 사용자 캐시만 무효화 → ③ JWT 클레임에 권한 포함(DB 조회 0회).

### 10.3 219개 테이블 샤딩 분류

| 분류 | 예시 | 처리 |
|------|------|------|
| 테넌트 데이터 | orders, products | 샤딩 대상 |
| 시스템 공통 | permissions, common_codes | 공유 DB 유지 |
| 감사 로그 | audit_logs | 별도 시계열 DB |

---

## 관련 문서

| 문서 | 설명 |
|------|------|
| [overview.md](overview.md) | 현재 시스템 아키텍처 |
| [security-policy.md](security-policy.md) | 현재 보안 구조 |
| [docker-setup.md](docker-setup.md) | 현재 Docker 구성 |
| [server-how-it-works.md](../guides/server-how-it-works.md) | 서버 동작 원리 |

---

**최종 업데이트**: 2026-02-22
