Docker Compose 아키텍처 선택 가이드: 단일 vs 다중 인스턴스 구성
들어가며
마이크로서비스 아키텍처를 구축할 때, Docker Compose를 사용한 컨테이너 배포 전략은 매우 중요한 결정사항입니다. 특히 모니터링 스택까지 포함한 풀스택 애플리케이션을 배포할 때는 리소스 사용량과 비용을 신중히 고려해야 합니다. 이번 글에서는 단일 EC2 인스턴스 구성과 다중 EC2 인스턴스 구성의 장단점을 비교해보고, 각각의 적합한 사용 사례를 살펴보겠습니다.

1. 단일 인스턴스 구성 (All-in-One)
구성 요소
- EC2 인스턴스: t3.2xlarge (8vCPU, 32GB RAM)
- 애플리케이션: Spring Boot
- 데이터베이스: MySQL
- 메시징: RabbitMQ
- 검색엔진: Elasticsearch
- 모니터링: Prometheus, Grafana, Jaeger, Loki, OTEL
장점
- 단순한 관리 구조: 하나의 서버에서 모든 서비스를 관리
- 네트워크 설정 간소화: Docker Compose 내부 네트워크로 간단한 통신
- 빠른 개발 환경 구축: 개발자가 로컬에서 전체 스택을 쉽게 실행
- 컨테이너 간 통신 최적화: 같은 호스트 내에서 빠른 통신
단점
- 단일 장애점(SPOF): 서버 하나가 다운되면 전체 서비스 중단
- 리소스 경합 발생: 모든 서비스가 같은 하드웨어 리소스를 공유
- 스케일링 제약: 개별 서비스의 독립적인 확장이 어려움
- 성능 저하 위험: 특히 메모리 집약적인 서비스들의 경합
현실적인 리소스 분석
풀 모니터링 스택의 실제 메모리 사용량을 분석해보면:
메모리 집약적 서비스
- Elasticsearch: 2-3GB RAM
- Prometheus: 1-2GB RAM
- Jaeger: 512MB-1GB RAM
중간 사용량 서비스
- Grafana: 256-512MB RAM
- Loki: 256-512MB RAM
- OTEL Collector: 128-256MB RAM
총 모니터링 스택 예상 사용량: 5-7GB RAM + 상당한 CPU
t3.xlarge(16GB RAM)을 사용하더라도 모니터링 스택만으로 절반 가까운 메모리를 소모하게 되어, Spring Boot 애플리케이션의 성능에 심각한 영향을 미칠 수 있습니다.
비용 분석
- EC2 t3.2xlarge: 월 $230
- EBS 100GB: 월 $10
- 탄력적 IP: 월 $3.6
- 총 비용: 월 약 $243
2. 다중 인스턴스 구성 (분산 구조)
구성 요소
DB + 검색 서버 (t3.large)
- MySQL, Elasticsearch, RabbitMQ
- CPU: 2core, RAM: 8GB
앱 서버 (t3.medium)
- Spring Boot 애플리케이션
- CPU: 2core, RAM: 4GB
모니터링 서버 (t3.medium)
- Prometheus, Grafana, Jaeger, Loki, OTEL
- CPU: 2core, RAM: 4GB
장점
- 리소스 격리 및 최적화: 각 서비스가 전용 리소스 사용
- 개별 스케일링 가능: 부하에 따라 특정 서버만 확장
- 장애 격리 효과: 한 서버의 문제가 다른 서버에 미치는 영향 최소화
- 모니터링 전용 리소스: 안정적인 모니터링 환경 보장
- 운영 안정성 향상: 각 역할별 최적화된 환경 제공
단점
- 복잡한 네트워크 설정: 서버 간 통신을 위한 추가 설정 필요
- 높은 관리 오버헤드: 여러 서버를 개별적으로 관리
- 컨테이너 간 통신 오버헤드: 네트워크를 통한 통신으로 약간의 지연
- 복잡한 로그 수집: 분산된 환경에서의 통합 로깅
비용 분석
- DB+검색 서버 (t3.large): 월 $75
- 앱 서버 (t3.medium): 월 $35
- 모니터링 서버 (t3.medium): 월 $35
- EBS 3개 × 50GB: 월 $15
- 탄력적 IP 3개: 월 $10.8
- 총 비용: 월 약 $170
3. 다중 EC2 인스턴스 간 통신 구성
Docker Compose 네트워크의 한계
서로 다른 EC2 인스턴스에 배포된 Docker 컨테이너들은 Docker Compose의 내부 네트워크를 사용할 수 없습니다. 따라서 다음과 같은 방법으로 통신을 구성해야 합니다.
EC2 Private IP를 이용한 통신
# 앱 서버의 docker-compose.yml
services:
spring-boot:
environment:
- DB_URL=jdbc:mysql://10.0.1.100:3306/momo # DB서버 Private IP
- RABBITMQ_HOST=10.0.1.100 # RabbitMQ Private IP
- ELASTICSEARCH_URL=http://10.0.1.100:9200 # ES Private IP
AWS VPC 및 보안 그룹 설정
# DB 서버 보안 그룹 (필요한 포트만 앱 서버에 개방)
- MySQL (3306) ← 앱서버에서만 접근 허용
- RabbitMQ (5672) ← 앱서버에서만 접근 허용
- Elasticsearch (9200) ← 앱서버 + 모니터링서버에서 접근 허용
# 앱 서버 보안 그룹
- HTTP (8080) ← 외부 접근 허용
# 모니터링 서버 보안 그룹
- Grafana (3000) ← 관리자 IP에서만 접근
- Prometheus (9090) ← 관리자 IP에서만 접근
4. 다중 EC2 구성의 문제점과 한계
네트워크 관리의 복잡성
- IP 의존성: 하드코딩된 Private IP로 인한 유연성 부족
- 포트 관리: 각 서비스별 포트를 수동으로 관리해야 함
- 서비스 디스커버리 부재: 서비스 간 자동 발견 기능 없음
운영 관리의 어려움
- 배포 복잡성: 여러 서버에 개별적으로 배포 및 관리
- 로그 분산: 각 서버의 로그를 통합하여 모니터링하기 어려움
- 장애 대응: 분산된 환경에서의 장애 추적 및 대응 복잡
확장성의 한계
- 수동 스케일링: 부하 증가 시 수동으로 인스턴스 추가 및 설정
- 로드 밸런싱 부재: 앱 서버 확장 시 별도의 로드 밸런서 필요
- 리소스 낭비: 각 인스턴스의 리소스 사용률 최적화 어려움
5. AWS ECS를 활용한 해결방안
ECS의 주요 장점
서비스 디스커버리
{
"serviceName": "user-service",
"namespace": "momo.local",
"dnsConfig": {
"type": "A"
}
}
- 서비스 이름으로 자동 DNS 해석
- IP 주소를 직접 관리할 필요 없음
자동 스케일링
{
"targetGroupArn": "arn:aws:elasticloadbalancing:...",
"scalingPolicy": {
"targetValue": 70.0,
"scaleUpCooldown": 300,
"scaleDownCooldown": 300
}
}
- CPU/메모리 사용률 기반 자동 확장
- 트래픽 패턴에 따른 동적 리소스 할당
통합 로깅 및 모니터링
{
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/momo-app",
"awslogs-region": "ap-northeast-2",
"awslogs-stream-prefix": "ecs"
}
}
}
- CloudWatch Logs로 중앙 집중식 로그 관리
- X-Ray를 통한 분산 추적
로드 밸런싱
- Application Load Balancer와 자동 연동
- 헬스체크 기반 트래픽 라우팅
- 무중단 배포 지원
ECS vs 다중 EC2 비교
구분 다중 EC2 ECS
| 구분 | 다중 EC2 | ECS |
| 서비스 디스커버리 | 수동 IP 관리 | 자동 DNS 해석 |
| 스케일링 | 수동 인스턴스 관리 | 자동 확장/축소 |
| 로드 밸런싱 | 별도 구성 필요 | ALB 자동 연동 |
| 모니터링 | 분산 로그 관리 | 통합 CloudWatch |
| 배포 | 개별 서버 배포 | 무중단 롤링 배포 |
| 비용 | 고정 인스턴스 비용 | 사용량 기반 과금 |
결론
단일 인스턴스 선택 조건
- 개발/테스트 환경
- 적은 사용자
- 빠른 프로토타이핑이 필요한 경우
- 운영 인력이 부족한 상황
- 예산 제약이 있는 경우 (월 $200 미만)
다중 인스턴스 선택 조건
- 프로덕션 환경
- 많은 사용자
- 고가용성이 중요한 서비스
- 체계적인 모니터링이 필요한 경우
- SLA 준수가 중요한 비즈니스
궁극적인 권장사항
프로덕션 환경에서는 다중 인스턴스 구성이 단일 인스턴스보다 비용 효율적이면서도 안정적입니다. 하지만 운영의 복잡성을 고려할 때, AWS ECS나 EKS 같은 관리형 컨테이너 서비스를 사용하는 것이 장기적으로 더 나은 선택입니다.
특히 Elasticsearch 같은 검색 엔진이나 대용량 데이터 처리가 필요한 서비스의 경우, 전용 리소스 할당이 사용자 경험에 직결되므로 분산 구조가 필수적입니다.