# 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 | --- ## 관련 문서 | 문서 | 설명 | |------|------| | [system-overview.md](system-overview.md) | 현재 시스템 아키텍처 | | [security-policy.md](security-policy.md) | 현재 보안 구조 | | [docker-setup.md](../specs/docker-setup.md) | 현재 Docker 구성 | | [server-how-it-works.md](../guides/server-how-it-works.md) | 서버 동작 원리 | --- **최종 업데이트**: 2026-02-22