Files
sam-docs/system/scaling-roadmap.md
권혁성 d4e5f62413 docs: [종합정비] Phase 1 시스템 현황 문서 14개 작성
- system/overview.md: 전체 아키텍처 개요
- system/api-structure.md: API 구조 (220 모델, 1027 엔드포인트, 18 라우트 도메인)
- system/react-structure.md: React 구조 (249 페이지, 612 컴포넌트)
- system/mng-structure.md: MNG 구조 (171 컨트롤러, 436 Blade 뷰)
- system/docker-setup.md: Docker 7 컨테이너 구성
- system/database/README.md + 9개 도메인 스키마 (270+ 테이블)
  - core, hr, sales, production, finance, boards, files, system, erp-analysis

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 18:03:13 +09:00

215 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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