raw
DevOps

모놀리스 마이크로서비스를 구축해보기

2025.06.06·6분

비슷한 포스트 를 올렸지만, 이번 프로젝트를 만들면서 또 헤메길래 제대로 기억하기 위해 다시 한번 포스트...

출저:레드헷

최근에 여러 서비스를 만들어보기도 하는데, 트래픽이 몰리지 않는 작은 서비스여서 마이크로 서비스 아키텍쳐 로 구축해보려고 한다.

text
1인터넷 (외부 사용자)
2
3 [도메인 요청]
4
5┌─────────────────────────────────────────┐
6│ nginx-proxy (리버스 프록시) │ ← 포트 80/443 독점
7│ "쇼핑몰 안내데스크 역할" │
8└─────────────────────────────────────────┘
9 ↓ (도메인별 라우팅)
10 ┌────┴────┐
11 ↓ ↓ ↓
12[csmorning] [kidsbugs] [growpromise]
13 ↓ ↓ ↓
14┌─────────┐ ┌─────────┐ ┌─────────┐
15│nginx-cs │ │nginx-kb │ │nginx-gp │ ← 각 서비스별 nginx
16└─────────┘ └─────────┘ └─────────┘
17 ↓ ↓ ↓
18┌─────────┐ ┌─────────┐ ┌─────────┐
19│front+api│ │front+api│ │ api │ ← 실제 애플리케이션
20└─────────┘ └─────────┘ └─────────┘

이렇게 구현을 했는데, 구글에 의하면

마이크로서비스 아키텍처(MSA)는 애플리케이션을 작은 독립적인 서비스 단위로 분할하여 구축하는 아키텍처 스타일입니다. 각 서비스는 특정 비즈니스 기능을 수행하며, 서로 독립적으로 배포, 확장 및 유지 보수할 수 있습니다.

최상위 : nginx-proxy(게이트웨이)

yaml
1포트: 80 (HTTP), 443 (HTTPS)
2역할: 도메인별 트래픽 분산
3위치: ~/nginx-proxy/

동작 원리

  • 모든 HTTP/HTTPS 요청을 받음
  • Host 헤더를 보고 어느 서비스로 보낼지 결정
  • SSL 인증서 관리

중간층 : 각 서비스별 nginx

yaml
1nginx-csmorning: 내부 포트 80, 외부 노출 없음
2nginx-kidsbugs: 내부 포트 80, 외부 노출 없음
3nginx-growpromise: 내부 포트 80, 외부 노출 없음

역할

  • 정적 파일 서빙(HTML,CSS,JS)
  • API 라우팅(/api -> 백엔드)
  • 보안 헤더 추가

최하위 : 애플리케이션 컨테이너

yaml
1cs-morning:
2 - landing-page-csmorning (프론트엔드)
3 - api-server-csmorning (백엔드, 포트 3000)
4
5kidsbugs:
6 - landing-page-kidsbugs (프론트엔드)
7 - api-server-kidsbugs (백엔드, 포트 3000)
8
9growpromise:
10 - api-server-growpromise (백엔드, 포트 3000)

네트워킹 구조

Docker 네트워크 격리

text
1csmorning-network: cs-morning 컨테이너들
2kidsbugs-network: kidsbugs 컨테이너들
3growpromise-network: growpromise 컨테이너들

ningx-proxy 연결

yaml
1# nginx-proxy가 모든 네트워크에 연결됨
2networks:
3 - csmorning-network # cs-morning과 통신
4 - kidsbugs-network # kidsbugs와 통신
5 - growpromise-network # growpromise와 통신

실제 요청 흐름

예시 1 : https://csmorning.co.kr/api/users 요청

text
11. 사용자 브라우저 → nginx-proxy (443포트)
22. nginx-proxy → "csmorning.co.kr이니까 nginx-csmorning으로!"
33. nginx-csmorning → "/api니까 api-server-csmorning:3000으로!"
44. api-server-csmorning → 데이터베이스 조회
55. 응답이 역순으로 돌아감

예시 2 : https://growpromise.com/ 요청

text
11. 사용자 → nginx-proxy (443포트)
22. nginx-proxy → "growpromise.com이니까 nginx-growpromise로!"
33. nginx-growpromise → "/ 요청이니까 기본 응답 반환"
44. "GrowPromise API Server" 텍스트 응답

볼륨 마운트 구조

SSL 인증서 공유

text
1ningx-proxy 볼륨:
2- ~/cs-morning-project/<SSL 인증서 받은 파일 경로>
3- ~/growpromise-project/<SSL 인증서 받은 파일 경로>

설정 파일 관리

text
1~/nginx-proxy/conf.d/
2├── csmorning.conf # csmorning.co.kr 라우팅
3├── kidsbugs.conf # kidsbugs.co.kr 라우팅
4└── growpromise.conf # growpromise.com 라우팅

이러한 구조의 장단점은?

확장성

  • 새 서비스 추가 - 새폴더 + conf 파일 하나만 추가
  • 기존 서비스에 영향 없음

격리성

  • 각 서비스는 독립적인 네트워크
  • 한 서비스 장애가 다른 서비스에 영향 업승ㅁ

유지보수성

  • 각 서비스별로 개별 배포 가능
  • 설정 변경이 간단함

보안성

  • 외부에서는 nginx-proxy만 접근 가능
  • 내부 서비스들은 완전히 숨겨짐

스스로 해보는 QnA

Q1. 이 구조가 진짜 마이크로서비스인가요? 단순히 멀티 테넌트 모놀리스 아닌가요? A1. 멀티테넌스 마이크로서비스 입니다. 독립 배포 + 도메인 분리 그리고 Docker로 격리 하지만, MSA 정의로 엄격하게 들어가면, 각 서비스마다 독립적인 데이터베이스가 없고, 완전히 다른 인프라에서 실행하지 않습니다 따라서 마이크로서비스의 성격을 가지고 있는 아키텍쳐입니다.

Q2. nginx-proxy가 SPOF(Single Point of Failure)가 되는 문제는 어떻게 해결하시겠어요? A2. nginx-proxy가 단일 장애점이 될 수 있습니다. 트래픽이 증가함에 따라 다르게 적용하는데, 3단계로 나누어 1단계에서는 nginx-proxy를 여러대로 구성, 2단꼐에서는 로드밸런서 앞단에 HAProxy 또는 AWS ALB 추가, 3단계는 Kubernetes 환경으로 이전할 것 같습니다.