Note

MSA(마이크로서비스 아키텍처)에서는 각각의 서비스가 독립적으로 실행되며, API Gateway가 이들 서비스를 관리하고 라우팅합니다. 이번 예제에서는 다음과 같은 구조로 MSA를 구성합니다.

📚 구성 요소

  1. API Gateway (gateway.py)

    • 모든 요청을 받아 적절한 서비스로 라우팅합니다.
  2. Service A (app_a.py)

    • "Hello from Service A" 출력.
  3. Service B (app_b.py)

    • "Hello from Service B" 출력.
  4. Service C (app_c.py)

    • "Hello from Service C" 출력.
  5. Docker Compose

    • 각 서비스를 독립적으로 실행할 수 있도록 설정.

1. API Gateway 구현

📄 gateway.py

from fastapi import FastAPI
import httpx

app = FastAPI()

# Service URLs
SERVICES = {
    "service_a": "http://service_a:8001",
    "service_b": "http://service_b:8002",
    "service_c": "http://service_c:8003"
}


@app.get("/")
async def root():
    return {"message": "Welcome to the API Gateway!"}


@app.get("/service_a")
async def service_a():
    async with httpx.AsyncClient() as client:
        response = await client.get(f"{SERVICES['service_a']}/")
        return response.json()


@app.get("/service_b")
async def service_b():
    async with httpx.AsyncClient() as client:
        response = await client.get(f"{SERVICES['service_b']}/")
        return response.json()


@app.get("/service_c")
async def service_c():
    async with httpx.AsyncClient() as client:
        response = await client.get(f"{SERVICES['service_c']}/")
        return response.json()

2. Service A, B, C 구현

📄 app_a.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello from Service A"}

📄 app_b.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello from Service B"}

📄 app_c.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello from Service B"}

3. Docker Compose 설정

📄 docker-compose.yml

version: '3.8'

services:
  gateway:
    build: ./gateway
    ports:
      - "8000:8000"
    depends_on:
      - service_a
      - service_b
      - service_c

  service_a:
    build: ./service_a
    ports:
      - "8001:8001"

  service_b:
    build: ./service_b
    ports:
      - "8002:8002"

  service_c:
    build: ./service_c
    ports:
      - "8003:8003"

📂 4. 프로젝트 구조

/msa-example
├── gateway
│   ├── gateway.py
│   ├── requirements.txt
│   ├── Dockerfile
├── service_a
│   ├── app_a.py
│   ├── requirements.txt
│   ├── Dockerfile
├── service_b
│   ├── app_b.py
│   ├── requirements.txt
│   ├── Dockerfile
├── service_c
│   ├── app_c.py
│   ├── requirements.txt
│   ├── Dockerfile
└── docker-compose.yml

🐳 5. Dockerfile 예제

📄 Dockerfile (각 서비스 공통)

FROM python:3.9

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8001"]

📄 requirements.txt

fastapi
uvicorn
httpx  # API Gateway만 필요

🚀 6. 서비스 실행

Step 1: Docker Compose로 모든 서비스 실행

docker-compose up --build

Step 2: API Gateway로 접근

📊 7. 테스트 시나리오 예시

요청: http://localhost:8000/service_a
응답:

{
    "message": "Hello from Service A"
}

요청: http://localhost:8000/service_b
응답:

{
    "message": "Hello from Service B"
}

요청: http://localhost:8000/service_c
응답:

{
    "message": "Hello from Service C"
}

📝 8. 설명

  1. API Gateway

    • 클라이언트의 요청을 받아 Service A, B, C로 라우팅합니다.
    • httpx를 사용하여 비동기 HTTP 요청을 처리합니다.
  2. Service A, B, C

    • 각각 독립된 FastAPI 앱이며, 단순한 문자열을 반환합니다.
  3. Docker Compose

    • 각 서비스가 독립적으로 실행되며, API Gateway가 라우팅합니다.

🎯 9. 핵심 포인트

  1. 서비스 간 독립성 유지.
  2. API Gateway를 통해 클라이언트 요청을 단일 진입점에서 관리.
  3. Docker Compose로 손쉽게 MSA 배포.