(글 오른쪽 하단 화이트/다크모드 전환 버튼을 통한 화이트모드 사용 권장합니다.)
BandFeed 서비스에서 제공하는 기능 및 배포 시 사용할 인프라 설계 의사결정 과정을 정리했습니다.
제공하는 기능
아래 더보기 토글은 지금까지 구현된 기능입니다.
(변경사항이 있을 때마다 업데이트할 예정)
( 26.06.15 기준 )
🔐 인증/공통 (Gateway)
- JWT 기반 인증 필터 — /api/users/signup, /api/users/login 제외 모든 요청 토큰 검증
- 인증된 사용자 ID를 X-User-Id 헤더로 다운스트림 서비스에 전파
- 서비스별 라우팅 (user/band/wiki/chat)
👤 User Service — 회원/팔로우
- 회원가입, 로그인(access/refresh 토큰 발급)
- 내 프로필 조회/수정, 비밀번호 변경, 회원 탈퇴
- 타 사용자 프로필 조회
- 팔로우 / 언팔로우, 팔로워·팔로잉 목록 조회
🎸 Band Service — 밴드 & 타임라인
- 밴드 생성/조회(목록·페이지네이션)/수정/삭제 (리더 권한 검증)
- 밴드 멤버 초대/조회/추방, 리더 권한 위임
- 밴드 타임라인 게시글 CRUD + 페이지네이션
- 내가 속한 밴드들의 게시글을 모은 피드(/feed)
- 게시글 댓글 작성/조회/삭제 (작성자 권한 검증)
🎵 Wiki Service — 곡/악기 위키
- Spotify 검색을 통한 곡 검색 및 등록
- 곡 상세 조회
- 곡별 악기 구성(난이도, 노트) 추가/조회/삭제
- 곡에 대한 위키 게시글 CRUD + 페이지네이션(최신/오래된 순)
- Spotify API 실패 시 502 예외 처리
💬 Chat Service — 1:1 채팅
- 채팅방 생성(또는 기존 방 재사용)/목록/상세/멤버 조회
- 메시지 전송/조회(페이지네이션), 읽음 처리
- WebSocket(STOMP, /ws)을 통한 실시간 메시지 송수신
⚙️ 공통 인프라
- Eureka(서비스 디스커버리), Config Server(중앙 설정 관리, GitHub 기반)
- 공통 에러 처리(BusinessException/ErrorCode 패턴), Soft delete(created/updated/deleted 감사 칼럼)
- Flyway 기반 DB 스키마 마이그레이션 (이번에 추가)
- Kafka, Redis, 모니터링(Prometheus/Grafana/Loki/Zipkin, monitoring profile)
배포 방식 의사결정 과정
초기 인프라 설계도

아래 더보기 토글은 Claude가 초기 인프라 설계도를 지적한 내용입니다.
원래 다이어그램에서 ECS EC2 launch type임을 알아보기 어려웠던 핵심 이유는 3가지입니다.
1. "EC2 instance contents" 박스가 ECS와 무관한 독립된 호스트처럼 보임
- private subnet 안의 EC2 박스가 ECS와 연결되어 있다는 표시 없이 그냥 단독으로 컨테이너들을 담고 있는 박스로 그려져 있었음
- 이러면 "이 EC2는 누가 관리하는가? docker-compose로 사람이 직접 띄운 건가, ECS가 관리하는 건가"가 그림만으로는 구분 안 됨
2. ECS↔EC2 사이의 양방향 화살표에 라벨이 없음
- 화살표만 있고 "이게 무슨 관계냐"(스케줄링 명령? 이미지 전달? 데이터 흐름?)가 안 적혀있어서, 처음에 사용자분이 "ECS가 EC2로 이미지를 push 한다"라고 오해하신 것처럼 데이터 흐름으로 잘못 읽힐 여지가 컸음
3. ECS와 ECR이 나란히, 같은 톤의 박스로 그려져서 "EC2가 의존하는 외부 리소스" 묶음처럼 보임
- RDS/ElastiCache 같은 "EC2가 사용하는 데이터 저장소"와 시각적으로 동급으로 배치되어, ECS도 그런 "리소스"처럼 인식되기 쉬움
- 실제로는 ECS는 EC2를 관리하는 컨트롤 플레인이라 위계가 다름 (EC2가 ECS에 등록된 "일원"이라는 포함 관계)
어떻게 표현했어야 했나 (제가 v2에서 수정한 방식)
- EC2 박스를 **"Private subnet — EC2 (ECS 컨테이너 인스턴스)"**처럼 라벨링해서, 이 EC2가 ECS 클러스터의 멤버임을 명시
- ECS↔EC2 화살표에 "스케줄링·에이전트" 같은 라벨을 붙여서 컨트롤 플레인 관계임을 명확히
- ECR pull은 "ECS가 직접 pull"이 아니라 **"EC2 위 ECS 에이전트가 pull"**이라는 점이 드러나도록, 가능하면 화살표 출발점을 EC2 박스 쪽에 두는 것이 더 정확함 (지금 v2는 ECS→ECR로 그려서 약간 단순화되어 있음 - 더 엄밀하게는 EC2 박스에서 ECR로 화살표를 그리는 게 맞음)
요약하면: "포함 관계(EC2가 ECS 클러스터의 일원)"와 "컨트롤 플레인 vs 데이터 플레인"을 구분해서 표현했어야 오해가 없었을 것입니다.
이때 컨트롤 플레인, 데이터 플레인이란?
일반적인 네트워크/시스템 설계에서 쓰이는 개념인데, ECS 맥락에 맞춰 설명하면:
Control plane (제어 영역)
- "무엇을 어떻게 할지 결정하고 지시하는" 부분
- 실제 트래픽이나 데이터가 흐르는 경로가 아니라, 설정/명령/상태 관리가 오가는 경로
- ECS 예시: "이 task definition대로 컨테이너 2개를 이 EC2에 띄워라", "이 컨테이너가 죽었으니 재시작해라" 같은 결정과 지시를 내리는 AWS ECS 서비스 자체
Data plane (데이터 영역)
- "실제로 일이 일어나는" 부분
- 사용자 요청, 이미지 파일, DB 쿼리 등 실질적인 데이터/트래픽이 오가는 경로
- ECS 예시: 사용자 HTTP 요청이 ALB→Gateway→각 서비스로 흐르는 것, EC2의 ECS 에이전트가 ECR에서 실제 이미지 바이너리를 다운로드하는 것
다이어그램 맥락에서 왜 중요한가
- "ECS → EC2" 화살표: control plane (ECS가 "이 컨테이너 띄워"라고 명령만 내림, 바이트 자체가 ECS를 거쳐가는 건 아님)
- "EC2 → ECR" 화살표: data plane (실제 이미지 데이터가 이 경로로 다운로드됨)
이 둘을 같은 종류의 화살표/같은 톤의 박스로 그리면, 보는 사람은 "ECS가 이미지를 받아서 EC2에 전달해 주는 하나의 파이프라인"처럼 오해하기 쉽습니다. 실제로는:
- ECS는 "누가, 언제, 어디서 실행될지"만 결정하고
- 실제 이미지 다운로드(데이터 이동)는 EC2의 에이전트가 ECR과 직접 수행
그래서 둘을 분리해서 그리면(예: control plane은 점선+회색, data plane은 실선+컬러), "ECS가 직접 이미지를 옮긴다"는 오해를 막을 수 있습니다.
인프라 설계도 수정 방안
: 1개의 개발계와 3개의 운영계(v1, v2, v3)로 나눠서 구성 및 마이그레이션 예정
1. 개발계

빠른 개발 및 테스팅을 위해 도커 컴포즈 네트워크를 사용한다.
로컬환경에서 각 서비스를 띄운다.
2. 운영계 - v1

도커 컴포즈 스택이 EC2에서 그대로 실행된다.
장점: 단일 EC2 구조로 배포비용이 적고, 테스트가 용이하다.
- t3.small 기준 월 15$ ~ 20$
- 배포환경에서 기능 테스트 쉬움.
단점: 향후 서비스 확장 시 구조적 한계로 관리하기 어렵다.
- SPOF, 스케일링 한계, EC2 한 개에 트래픽 집중 -> 부담, 무중단 배포 어려움.
3. 운영계 - v2

ECS는 컨테이너를 어디서 실행할지 스케쥴링하는 오 케스트레이터이다.
동작 방식은 2가지가 있다.
- EC2 launch type
- EC2 인스턴스 위에 ECS 컨테이너 에이전트를 설치
- EC2를 ECS 클러스터 인스턴스로 등록
- ECS가 도커 컨테이너를 이 EC2에 띄우라고 명령
- ECS 에이전트가 ECR(내부적으론 S3)에서 도커 이미지를 다운로드 및 실행
- Fargate : 서버리스 구조, EC2 자체가 없음.
위 사진은 그중 EC2 launch type 방식이다.
배포 단위는 ECS task definition이다.
ECS가 새 이미지로 task를 교체하여 배포한다.
참고로 ECR은 실제 도커 이미지는 내부적으로 S3에 저장하고 관리한다.
따라서 EC2에서 ECR로부터 이미지를 다운로드하려고 하면
사실 S3에서 도커 이미지를 다운로드한다.
ECS는 스케줄링만 함. (제어 plane)
실제 이미지 pull은 EC2가 함. (데이터 plane)
- ECS Agent → ECR → S3(레이어 실제 저장)
4. 운영계 - v3

ECS Fargate 방식을 적용하는 설계도이다.
- 트레이드오프
| 비교 항목 | v2 — EC2 Launch Type | v3 — ECS Fargate |
|---|---|---|
| 인프라 관리 | 개발자가 OS/Docker 직접 관리 (높은 공수) | AWS가 관리형으로 대행 (공수 제로) |
| 네트워크 모드 | Bridge 또는 호스트 포트 공유 방식 중심 | awsvpc 모드 강제 (Task별 고유 IP 부여) |
| 보안 그룹 범위 | EC2 인스턴스 단위 (컨테이너간 공유) | 개별 컨테이너(Task) 단위 격리 가능 |
| 스케일링 구조 | EC2 ASG + ECS Task 이중 설계 필요 | ECS Task 단일 오토스케일링으로 단순화 |
| 비용 효율성 | 자원을 꽉 채워 쓰는 대규모 상시 운영에 유리 | 트래픽 변동이 크거나 인프라 자동화에 유리 |
| 구성 난이도 | 높음 (EC2·Task 이중 스케일링 및 초기 에이전트 설정 필요 / SSH 트러블슈팅은 용이) |
낮음 (서버 관리 생략 및 Task 단일 스케일링으로 단순함 / 모니터링 시스템 구축 필요) |
프런트 배포 방식
백엔드를 운영계 v1으로 배포한다고 가정.
옵션 1. Nginx 컨테이너 방식
- 기존 EC2의 docker-compose에 Nginx를 추가해 React 빌드 파일을 서빙하는 방식
- 장점: 관리가 하나로 끝나 단순, 도메인이 같아 CORS 설정 필요 x
- 단점: 안 그래도 무거운 v1 EC2 자원(Spring, DB 등)을 공유하므로 부하 커짐.
서버가 터지면 프런트도 같이 죽음.
옵션 2. S3 + CloudFront 방식
- React 빌드 파일을 S3에 올리고, 글로벌 CDN인 CloudFront를 전면에 세워 배포하는 방식
- 장점: EC2 자원을 전혀 쓰지 않아 API 연산에 집중 O
백엔드가 다운되어도 프런트 화면은 정상적으로 유지.
프리티어 범위 내에서 비용도 거의 무료. - 단점: 도메인이 찢어져 CORS 설정 필요
배포 파이프라인(CI/CD)을 프런트/백엔드 각각 따로 구축해야 함.
따라서 옵션 1로 사용하다가 옵션 2로 마이그레이션 할 예정이다.
옵션2로 배포하면, 백엔드를 어떤 식으로 배포해도 상관없다.
프론트와 백엔드 사이의 요청 경로만 그에 맞게 맞춰주면 된다.
최종 배포 방법
백엔드는 단일 EC2 + dokcer-compose 네트워크 방식 + ECR 구조로 배포한다.
프론트는 위 docker-compose에 Nginx 서비스를 추가한 Nginx 컨테이너 방식으로 배포한다.
- 위 구조를 채택한 이유
- 저렴한 비용
- 쉬운 구성 난이도
3개의 인프라 서비스와 4개의 비즈니스 서비스를 하나의 EC2에 올려야 한다.
따라서 EC2 인스턴스는 메모리 용량이 8GB인 t3.large를 선택했다.
-> 현재 AWS에서 제공하는 EC2 프리티어 모델 중 메모리 8GB 인 것은 m7i-flex.large 밖에 없어서 이 모델로 선택했다.
그 외 모니터링 스택 배포는 여유 메모리를 계산하여 진행(EC2 추가 구입, 일부만 배포 등)한다.
그 외 설계(ECS Fargate, CloudFront 등)는 로드맵에 개선사항으로 남겨뒀다.
'개인 프로젝트' 카테고리의 다른 글
| [Spotify Web API 6편] Band 서비스 구현 (0) | 2026.06.10 |
|---|---|
| [Spotify Web API 5편] Docker 및 공통모듈 세팅 (0) | 2026.06.07 |
| [Spotify Web API 4편] MSA 프로젝트 초기 세팅 (0) | 2026.06.07 |
| [Spotify Web API 3편] 애그리거트 경계 설정 및 SA 문서 작성 (0) | 2026.06.06 |
| [Spotify Web API 2편] API 분석 (0) | 2026.06.05 |
