Co-Talk 대규모 트래픽 아키텍처 문서
버전 1.0 - 확장 가능한 아키텍처
1. 대규모 트래픽 가정
1.1 트래픽 시나리오
- 동시 접속자: 100만+ 명
- 일일 활성 사용자 (DAU): 500만+
- 초당 메시지 전송량 (TPS): 10,000+
- 피크 시간대: 동시 접속자 200만+
- 메시지 저장량: 일일 10억+ 메시지
1.2 성능 요구사항
- API 응답 시간: P95 < 100ms
- 메시지 전달 지연: < 50ms
- 가용성: 99.9% 이상
- 데이터베이스 쿼리: P95 < 50ms
2. 대규모 트래픽용 기술 스택
2.1 백엔드 언어 선택
옵션 1: Java + Spring Boot (강력 추천)
장점:
- 성능: JVM 최적화, 멀티스레딩 강력
- Virtual Threads (Java 25): Java 24에서 개선된 Virtual Threads (pinning 문제 해결 등), I/O 바운드 작업에 최적화, 수백만 동시 연결 처리 가능
- 최신 LTS: 2025년 9월 출시, 최소 8년간 장기 지원 (2033년까지)
- 확장성: 수평 확장에 최적화
- 안정성: 엔터프라이즈급 안정성
- 생태계: 대규모 서비스 검증된 라이브러리
- 모니터링: APM 도구 풍부 (New Relic, Datadog 등)
프레임워크:
- Spring Boot (v3.5+)
- Java 25 LTS 지원
- Virtual Threads 지원 (개선된 버전)
- Spring WebFlux (리액티브 프로그래밍)
- Spring Data JPA
- Spring Security
- Spring Cloud (마이크로서비스)
실시간 통신:
- Spring WebSocket 또는 Netty
- Netty 기반 WebSocket 서버 (고성능)
- 개선된 Virtual Threads와 결합 시 더 높은 성능
- 또는 Spring WebSocket + STOMP
추가 기술:
- Kotlin (선택) - Java 대안, 더 간결한 문법
- Project Reactor - 리액티브 스트림 처리
- Virtual Threads - Java 25의 핵심 기능, Java 24에서 개선된 안정성
옵션 2: Go (고성능 대안)
장점:
- 성능: 네이티브 컴파일, 낮은 메모리 사용
- 동시성: Goroutine으로 수천만 동시 연결 처리
- 빠른 시작: 간단한 문법, 빠른 컴파일
프레임워크:
- Gin 또는 Fiber (고성능 웹 프레임워크)
- Gorilla WebSocket (WebSocket 라이브러리)
단점:
- 생태계가 Java/Node.js보다 작음
- 실시간 메시징 특화 라이브러리 부족
옵션 3: Node.js (클러스터링 + 최적화)
장점:
- 개발 속도 빠름
- Socket.io 생태계
단점:
- 단일 스레드 한계 (클러스터링 필수)
- CPU 집약 작업에 불리
- 메모리 관리 주의 필요
최적화 방법:
- PM2 클러스터 모드
- Worker Threads 활용
- Redis 어댑터 필수
2.2 추천 스택: Java + Spring Boot
대규모 트래픽에는 Java + Spring Boot를 강력 추천합니다.
이유:
- 검증된 확장성 (Netflix, Amazon 등)
- 멀티스레딩으로 CPU 효율적 활용
- JVM 최적화로 높은 처리량
- 엔터프라이즈급 안정성
- 풍부한 모니터링 도구
3. 대규모 트래픽 아키텍처
3.1 전체 아키텍처 다이어그램
@startuml
!theme plain
skinparam backgroundColor #FEFEFE
skinparam defaultFontSize 11
skinparam componentStyle rectangle
skinparam ArrowColor #333333
top to bottom direction
title Co-Talk 인프라 아키텍처
rectangle "Edge" {
component [CDN\n(CloudFlare)] as CDN
}
rectangle "Load Balancing" {
component [Load Balancer\n(ALB/NLB)\n- SSL Termination\n- Health Check] as LB
}
rectangle "Application Layer" {
component [API Gateway\n(Kong / AWS API)] as APIGW
component [WebSocket Gateway\n(Netty / Spring WS)] as WSGW
component [API Servers\n(Spring)] as API
}
rectangle "Cache & Messaging" {
component [Redis\n(Cache)] as RedisCache
component [Redis\n(Pub/Sub)\n(Message Queue)] as RedisPubSub
component [Redis\n(Session)] as RedisSession
}
rectangle "Data Layer" {
component [PostgreSQL\n(Primary)] as PgPrimary
component [PostgreSQL\n(Read Replica)] as PgReplica1
component [PostgreSQL\n(Read Replica)] as PgReplica2
}
rectangle "Search" {
component [Elasticsearch\n(Message Search)] as ES
}
CDN -down-> LB
LB -down-> APIGW
LB -down-> WSGW
LB -down-> API
APIGW -down-> RedisCache
WSGW -down-> RedisPubSub
API -down-> RedisSession
APIGW -down-> PgPrimary
WSGW -down-> PgReplica1
API -down-> PgReplica2
PgPrimary -right-> PgReplica1 : replication
PgPrimary -right-> PgReplica2 : replication
PgPrimary -down-> ES
PgReplica1 -down-> ES
PgReplica2 -down-> ES
@enduml
3.2 마이크로서비스 아키텍처
@startuml
!theme plain
skinparam backgroundColor #FEFEFE
top to bottom direction
title 마이크로서비스 아키텍처
rectangle "API Gateway (Kong / AWS API Gateway)" as APIGW
rectangle "Services" {
component [Auth Service\n(Spring)] as Auth
component [User Service\n(Spring)] as User
component [Friend Service\n(Spring)] as Friend
component [Chat Service\n(Spring WS)] as Chat
component [Message Service\n(Spring)] as Message
component [Notification Service\n(Spring)] as Notif
}
APIGW -down-> Auth
APIGW -down-> User
APIGW -down-> Friend
APIGW -down-> Chat
APIGW -down-> Message
APIGW -down-> Notif
@enduml
3.3 실시간 메시징 아키텍처
@startuml
!theme plain
skinparam backgroundColor #FEFEFE
top to bottom direction
title 실시간 메시징 아키텍처
actor "Client 1" as C1
actor "Client 2" as C2
rectangle "WebSocket Gateway\n(Netty / Spring WS)" as WSGW {
note right
- Connection Management
- Message Routing
end note
}
rectangle "Message Broker\n(Redis Pub/Sub)" as Broker {
note right
- Channel per ChatRoom
- Message Distribution
end note
}
rectangle "WebSocket Gateway Instances\n(Instance 1, 2, 3...)" as WSGW2
C1 -down-> WSGW : WebSocket
WSGW -down-> Broker : Redis Pub/Sub
Broker -down-> WSGW2
WSGW2 -down-> C2 : WebSocket
@enduml
4. 핵심 컴포넌트 상세 설계
4.1 API Gateway
역할:
- 라우팅 및 로드 밸런싱
- 인증/인가 (JWT 검증)
- Rate Limiting
- 요청/응답 변환
- 로깅 및 모니터링
기술:
- Kong 또는 AWS API Gateway
- Spring Cloud Gateway (Java 스택)
4.2 WebSocket Gateway
역할:
- WebSocket 연결 관리
- 메시지 라우팅
- Redis Pub/Sub 구독/발행
- 연결 상태 관리
기술:
- Netty (Java) - 고성능 네트워크 프레임워크
- 또는 Spring WebSocket + STOMP
- Redis Pub/Sub - 서버 간 메시지 브로드캐스팅
최적화:
- 연결 풀 관리
- 메시지 배치 처리
- 압축 (gzip)
4.3 메시지 큐
역할:
- 메시지 비동기 처리
- 부하 분산
- 재시도 로직
- 순서 보장
기술:
- Redis Streams (간단한 경우)
- Apache Kafka (대용량, 순서 보장 필요 시)
- RabbitMQ (복잡한 라우팅 필요 시)
선택 기준:
- 초기: Redis Streams
- 대용량: Kafka
- 복잡한 라우팅: RabbitMQ
4.4 캐싱 전략
Redis 캐시 계층
캐시 항목:
- 사용자 정보 (TTL: 1시간)
- 친구 목록 (TTL: 30분)
- 채팅방 정보 (TTL: 1시간)
- 최근 메시지 (TTL: 10분)
- 온라인 상태 (TTL: 5분)
캐시 전략:
- Cache-Aside: 애플리케이션 레벨 캐시 관리
- Write-Through: 쓰기 시 캐시 업데이트
- Write-Behind: 비동기 쓰기 (메시지 저장)
4.5 데이터베이스 최적화
PostgreSQL 최적화
읽기 최적화:
- Read Replica: 읽기 전용 복제본 (3-5개)
- Connection Pooling: PgBouncer 또는 HikariCP
- 인덱스 최적화: 복합 인덱스, 부분 인덱스
쓰기 최적화:
- 파티셔닝: Messages 테이블 날짜별 파티셔닝
- 배치 삽입: 메시지 배치 처리
- 비동기 쓰기: 메시지는 먼저 Redis에 저장 후 DB에 비동기 저장
예시 파티셔닝:
1
2
3
-- Messages 테이블을 월별로 파티셔닝
CREATE TABLE messages_2024_01 PARTITION OF messages
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
메시지 저장 전략
Hot-Warm-Cold 아키텍처:
- Hot Storage (최근 7일)
- PostgreSQL (인덱스 최적화)
- 빠른 조회
- Warm Storage (7일 ~ 3개월)
- PostgreSQL (파티셔닝)
- 또는 TimescaleDB
- Cold Storage (3개월 이상)
- S3 + Athena (검색 필요 시)
- 또는 Elasticsearch
4.6 검색 엔진
Elasticsearch:
- 메시지 검색
- 사용자 검색
- 실시간 인덱싱
설정:
- 인덱스 템플릿
- 샤딩 전략
- 리플리카 설정
5. 확장성 전략
5.1 수평 확장
WebSocket 서버 확장
- Sticky Session: 로드 밸런서에서 IP 기반 세션 고정
- Redis Pub/Sub: 서버 간 메시지 브로드캐스팅
- 서비스 디스커버리: Consul, Eureka, Kubernetes Service
API 서버 확장
- Stateless 설계: 세션을 Redis에 저장
- 로드 밸런싱: Round Robin, Least Connection
- Auto Scaling: CPU/메모리 기반 자동 스케일링
5.2 데이터베이스 확장
읽기 확장
- Read Replica: 읽기 전용 복제본 추가
- 캐싱: Redis로 읽기 부하 감소
쓰기 확장
- 샤딩: 사용자 ID 기반 샤딩
- 파티셔닝: 날짜/시간 기반 파티셔닝
- CQRS: 읽기/쓰기 모델 분리
5.3 샤딩 전략
사용자 기반 샤딩:
1
2
3
4
Shard 1: User ID % 4 == 0
Shard 2: User ID % 4 == 1
Shard 3: User ID % 4 == 2
Shard 4: User ID % 4 == 3
채팅방 기반 샤딩:
- 채팅방 ID 해시 기반
- 같은 채팅방의 메시지는 같은 샤드에 저장
6. 성능 최적화
6.1 메시지 전송 최적화
배치 처리:
- 여러 메시지를 묶어서 처리
- Redis Pipeline 사용
비동기 처리:
- 메시지 저장을 비동기로 처리
- 먼저 Redis에 저장 후 DB에 비동기 저장
압축:
- WebSocket 메시지 압축 (permessage-deflate)
- 대용량 메시지 압축
6.2 데이터베이스 쿼리 최적화
인덱스 전략:
1
2
3
4
5
6
7
-- 메시지 조회 최적화
CREATE INDEX idx_messages_room_time
ON messages(chat_room_id, created_at DESC);
-- 친구 목록 조회 최적화
CREATE INDEX idx_friends_user_status
ON friends(user_id, status);
쿼리 최적화:
- N+1 문제 방지 (JOIN 사용)
- 페이지네이션 (Cursor-based)
- 배치 쿼리
6.3 네트워크 최적화
CDN 활용:
- 정적 파일 (이미지, CSS, JS)
- API 응답 캐싱 (가능한 경우)
압축:
- Gzip/Brotli 압축
- WebSocket 메시지 압축
7. 모니터링 및 관찰 가능성
7.1 메트릭 수집
애플리케이션 메트릭:
- Prometheus + Grafana
- JVM 메트릭 (Heap, GC)
- API 응답 시간
- WebSocket 연결 수
- 메시지 처리량
인프라 메트릭:
- CPU, Memory, Disk
- 네트워크 I/O
- 데이터베이스 성능
7.2 로깅
중앙화된 로깅:
- ELK Stack (Elasticsearch, Logstash, Kibana)
- 또는 Loki + Grafana
- 구조화된 로깅 (JSON)
로그 레벨:
- ERROR: 에러만 수집
- INFO: 주요 이벤트
- DEBUG: 개발 환경에서만
7.3 분산 추적
추적 시스템:
- Jaeger 또는 Zipkin
- 요청 추적 (Request ID)
- 서비스 간 호출 추적
7.4 알림
알림 시스템:
- PagerDuty 또는 Opsgenie
- 임계값 초과 시 알림
- 슬랙/이메일 통합
8. 보안 고려사항
8.1 인증 및 인가
- JWT 토큰: Stateless 인증
- Refresh Token: 보안 강화
- Rate Limiting: API 호출 제한
- DDoS 방어: CloudFlare, AWS Shield
8.2 데이터 보안
- 암호화: TLS 1.3 (전송 중)
- 데이터베이스 암호화: 암호화 at rest
- 비밀번호: bcrypt (cost factor: 12+)
8.3 네트워크 보안
- VPC: 네트워크 격리
- Security Groups: 방화벽 규칙
- WAF: 웹 애플리케이션 방화벽
9. 배포 전략
9.1 컨테이너화
Docker:
- 애플리케이션 컨테이너화
- 멀티 스테이지 빌드
Kubernetes:
- 컨테이너 오케스트레이션
- 자동 스케일링
- 롤링 업데이트
9.2 CI/CD
파이프라인:
- GitHub Actions 또는 Jenkins
- 자동 테스트
- 자동 빌드 및 배포
- Blue-Green 배포
9.3 무중단 배포
전략:
- Blue-Green 배포: 새 버전과 기존 버전 전환
- Canary 배포: 점진적 배포
- 롤링 업데이트: Kubernetes 기본 기능
10. 비용 최적화
10.1 인프라 비용
최적화 전략:
- Reserved Instances: 장기 사용 시 할인
- Spot Instances: 비중요 워크로드
- Auto Scaling: 필요 시에만 확장
10.2 데이터베이스 비용
최적화:
- 파티셔닝: 오래된 데이터 아카이빙
- Cold Storage: S3로 오래된 데이터 이동
- 읽기 복제본: 필요 시에만 추가
11. 기술 스택 요약 (대규모 트래픽)
백엔드
- 언어: Java 25 LTS
- 프레임워크: Spring Boot 3.1+
- 실시간 통신: Netty 또는 Spring WebSocket
- 메시지 큐: Redis Streams / Apache Kafka
- 캐싱: Redis Cluster
데이터베이스
- 주 데이터베이스: PostgreSQL (Primary + Read Replicas)
- 검색: Elasticsearch
- 캐시: Redis Cluster
인프라
- 컨테이너: Docker
- 오케스트레이션: Kubernetes
- 로드 밸런서: AWS ALB/NLB 또는 NGINX
- API Gateway: Kong 또는 AWS API Gateway
- 모니터링: Prometheus + Grafana
- 로깅: ELK Stack 또는 Loki
프론트엔드
- 프레임워크: Flutter 3.8+ (Dart SDK ^3.8.1)
- 상태 관리: BLoC/Cubit (flutter_bloc)
- 실시간 통신: STOMP over WebSocket (stomp_dart_client)
- 플랫폼: Android, iOS, macOS, Windows, Linux
12. 마이그레이션 전략
12.1 단계별 마이그레이션
Phase 1: 모니터링 구축
- Prometheus + Grafana 설정
- 로깅 시스템 구축
Phase 2: 캐싱 도입
- Redis 캐시 계층 추가
- 읽기 부하 감소
Phase 3: 읽기 복제본
- PostgreSQL Read Replica 추가
- 읽기 쿼리 분산
Phase 4: 메시지 큐 도입
- 비동기 메시지 처리
- 부하 분산
Phase 5: 마이크로서비스 전환
- 서비스 분리
- API Gateway 도입
Phase 6: 샤딩
- 데이터베이스 샤딩
- 수평 확장