kjp0411 님의 블로그
내일배움캠프 단기심화 Java - 본 캠프 Day 61 본문
TIL - 2026.05.11
오늘 한 일
MSA 티켓팅 프로젝트의 배포 인프라 구성을 검토했다.
기존에는 로컬 Docker Compose 환경에서 Gateway, Eureka, Config Server, 각 도메인 서비스를 실행하며 통합 테스트를 진행했지만, 이제는 실제 사용자 접속과 포트폴리오 데모까지 고려한 운영형 배포 구조를 설계해야 했다.
초기에는 다음과 같은 구조를 고민했다.
인프라 인스턴스
- Kafka
- Redis
- Prometheus
- Grafana
- Zipkin
- Keycloak
서비스 인스턴스
- Config Server
- Eureka Server
- User Service
- Club Service
- Match Service
- Seat Service
- Reservation Service
트래픽 인스턴스
- Queue Service
- Payment Service
RDS PostgreSQL
- 서비스별 Schema 분리
NAT Gateway
ALB
인프라 구성 방향
처음에는 ALB와 NAT Gateway까지 포함한 구조를 생각했다.
하지만 비용을 계산해보니 ALB와 NAT Gateway는 각각 월 5만 원 내외의 비용이 추가될 수 있고, EC2 인스턴스 3대와 RDS까지 함께 운영하면 월 30만 원 이상으로 올라갈 가능성이 있었다.
따라서 1차 배포에서는 비용과 운영 복잡도를 고려해 NAT Gateway와 ALB는 제외하고, Caddy 또는 Nginx를 이용해 HTTPS를 처리하는 방향이 더 현실적이라고 판단했다.
최종 검토한 1차 배포 구조
사용자와 면접관은 도메인을 통해 서비스에 접근하고, 요청은 Caddy 또는 Nginx를 거쳐 Gateway Service로 전달된다.
Gateway Service는 외부 요청의 진입점 역할을 하고, 내부적으로 Eureka를 통해 각 도메인 서비스로 라우팅한다.
전체 흐름은 다음과 같다.
- 사용자 / 면접관
- 도메인
- Caddy 또는 Nginx
- Gateway Service
- Eureka
- 각 도메인 서비스
- RDS PostgreSQL
EC2는 역할에 따라 3개로 분리하는 방향을 검토했다.
Infra 인스턴스
- Kafka
- Redis
- Keycloak
- Prometheus
- Grafana
- Zipkin
Main 인스턴스
- Caddy 또는 Nginx
- Gateway Service
- Config Server
- Eureka Server
- User Service
- Club Service
- Match Service
- Seat Service
- Reservation Service
Traffic 인스턴스
- Queue Service
- Payment Service
이렇게 나누면 MSA 구조가 더 명확하게 드러난다.
특히 티켓팅 서비스에서는 트래픽이 몰릴 가능성이 높은 영역이 대기열과 결제이기 때문에, Queue Service와 Payment Service를 별도 인스턴스로 분리하는 것이 설계상 의미가 있다고 판단했다.
RDS 구성
DB는 RDS PostgreSQL을 사용하고, 비용과 운영 복잡도를 고려해 RDS 인스턴스 1개 내부에 서비스별 schema를 분리하는 방식으로 구성하기로 했다.
RDS 내부에는 다음과 같은 schema를 둘 예정이다.
- user_service
- club_service
- match_service
- seat_service
- queue_service
- reservation_service
- payment_service
완전한 서비스별 DB 분리는 아니지만, 초기 MVP 배포 단계에서는 비용을 고려한 현실적인 선택이라고 판단했다.
서비스 간 테이블 직접 참조는 금지하고, 각 서비스는 자신이 소유한 schema에만 접근하도록 구성할 예정이다.
비용 검토
인스턴스 구성은 다음 두 가지 방향을 검토했다.
비용 절충안
- Infra: t4g.medium
- Main: t4g.large
- Traffic: t4g.medium
- RDS: db.t4g.small
예상 비용은 월 24만 원에서 27만 원 정도로 예상된다.
다만 Infra 인스턴스에 Kafka, Redis, Keycloak, Prometheus, Grafana, Zipkin을 모두 올릴 경우 4GB 메모리가 부족할 수 있다.
안정성 우선안
- Infra: t4g.large
- Main: t4g.large
- Traffic: t4g.medium
- RDS: db.t4g.small
이 경우 예상 비용은 월 29만 원에서 32만 원 정도로 올라갈 수 있다.
따라서 처음에는 비용 절충안으로 시작하고, 실제 메모리 사용량을 확인한 뒤 Infra 인스턴스만 t4g.large로 올리는 방식이 가장 현실적이라고 판단했다.
오늘 정리한 핵심 판단
이번 배포는 단순히 EC2에 서비스를 올리는 것이 아니라, MSA 구조가 잘 드러나도록 역할을 나누는 것이 중요했다.
특히 다음 기준을 중요하게 봤다.
- Gateway를 외부 진입점으로 둔다.
- Eureka로 서비스 디스커버리를 구성한다.
- Config Server로 설정을 중앙화한다.
- Kafka와 Redis를 별도 인프라 영역으로 분리한다.
- Queue/Payment처럼 트래픽이 몰릴 수 있는 서비스를 별도 인스턴스로 분리한다.
- RDS는 서비스별 schema로 논리적으로 분리한다.
- Prometheus, Grafana, Zipkin으로 모니터링과 분산 추적 환경을 구성한다.
- NAT Gateway와 ALB는 비용을 고려해 1차 배포에서는 제외한다.
- HTTPS는 Caddy 또는 Nginx를 통해 처리한다.
- Docker restart 정책을 적용해 컨테이너 비정상 종료 시 자동 재시작되도록 한다.
배운 점
MSA 프로젝트에서 중요한 것은 단순히 서비스를 여러 개로 나누는 것이 아니라, 각 서비스의 역할과 배포 구조를 명확히 설명할 수 있어야 한다는 점이다.
EC2 한 대에 모든 서비스를 올려도 MSA라고 볼 수는 있지만, 포트폴리오 관점에서는 인프라, 주요 서비스, 트래픽 집중 서비스를 분리하는 구조가 훨씬 설득력 있어 보인다.
또한 운영형 인프라를 구성할 때는 기술적으로 좋은 구조와 비용적으로 현실적인 구조를 구분해서 판단해야 한다.
ALB, NAT Gateway, Private Subnet 구조는 운영 관점에서는 좋지만, 초기 포트폴리오 배포 단계에서는 비용 대비 효과가 크지 않을 수 있다.
따라서 1차 배포에서는 비용을 줄이면서도 MSA 구조와 운영 경험이 드러나는 구성을 선택하고, 이후 고도화 단계에서 ALB, NAT Gateway, Private Subnet 구조를 추가하는 방식이 더 현실적이라고 느꼈다.
다음에 할 일
- 최종 인프라 구성안을 팀원들과 공유하기
- EC2 인스턴스 스펙 최종 결정하기
- RDS PostgreSQL 생성 및 schema 분리 전략 정리하기
- docker-compose.prod.yml 구조 설계하기
- Caddy 또는 Nginx 중 HTTPS 처리 방식 결정하기
- 서비스별 환경변수 분리하기
- Eureka 등록 시 localhost가 아닌 private IP 기준으로 등록되도록 설정하기
- Prometheus/Grafana/Zipkin 모니터링 구성 방식 정리하기
- AWS Budget을 설정해 월 비용 모니터링하기
- 배포 후 메모리 사용량을 확인하고 Infra 인스턴스 스펙 조정 여부 판단하기
한 줄 회고
MSA 배포 인프라는 단순히 서버를 많이 쓰는 것이 중요한 게 아니라, 비용과 운영 복잡도를 고려하면서도 서비스 분리 이유를 명확히 설명할 수 있는 구조를 설계하는 것이 중요하다는 것을 배웠다.
'TIL' 카테고리의 다른 글
| 내일배움캠프 단기심화 Java - 본 캠프 Day 63 (0) | 2026.05.13 |
|---|---|
| 내일배움캠프 단기심화 Java - 본 캠프 Day 62 (0) | 2026.05.12 |
| 내일배움캠프 단기심화 Java - 본 캠프 Day 60 (0) | 2026.05.08 |
| 내일배움캠프 단기심화 Java - 본 캠프 Day 59 (0) | 2026.05.07 |
| 내일배움캠프 단기심화 Java - 본 캠프 Day 58 (0) | 2026.05.06 |
