MicroService Architecture ‐ API Gateway Patterns - woojin-playground/Backend-PlayGround GitHub Wiki

MicroService Architecture - API Gateway Patterns

API Gateway Pattern

image
  • 클라이언트 애플리케이션에 대한 단일 진입점이다.
  • 클라이언트와 백엔드 서비스 사이에 위치한다.
    • 여러 마이크로서비스 요청을 1개의 응답으로 처리한다.
    • 내부 마이크로서비스로 라우팅을 담당한다.
  • 객체 지향 설계의 Facade 패턴과 유사하다.

장점

  • Reverse Proxy, Routing, Aggregation 지원
  • Abstraction Backend Service
  • 불필요한 네트워크 트래픽 요청 감소
  • Cross-cutting Concerns 문제 처리

단점

  • 단일 API Gateway로 SPOF 위험성 증가
  • API Gateway 비즈니스 복잡성 증가
  • API Gateway가 네트워크 트래픽의 병목 지점이 될 수 있다.

Gateway Routing Pattern

image
  • 단일 엔드포인트로 여러 마이크로서비스에 요청을 보낸다.
    • Routing, Reverse Proxy
    • 각 서비스에 대한 요청을 라우팅하는 Gateway Endpoint가 필요하다.
  • 클라이언트에서 여러 마이크로서비스를 사용하는 경우
    • 마이크로서비스가 변경되어도 클라이언트 코드 변경이 필요하지 않다.
    • Routing만 변경하면 된다.
    • 클라이언트 코드의 단순화
  • 다양한 API 버전에 대해 Routing 기능이 지원된다.

Gateway Aggregation Pattern

image
  • 클라이언트 로직 수행에 여러 개의 다른 백엔드 마이크로서비스를 호출해야 하는 경우에 사용한다.
  • 단일 엔드포인트를 노출하고 여러 마이크로서비스로 요청을 보낸 후 집계한다.
    • 여러 백엔드 서비스에 요청을 전송한 다음 집계한 내용을 클라이언트로 전달한다.
  • 클라이언트 애플리케이션에서 복잡한 내부 백엔드 서비스 통신에 대한 추상화를 이룰 수 있다.

Gateway Offloading Pattern

image
  • Gateway Proxy에 공유 기능을 결합한 것이다.
    • 대표적인 공유 서비스 기능 - 인증, SSL 종료, 로깅, 모니터링 등
  • Cross-cutting Concerns 처리
    • 인증, 권한 부여, 서비스 검색, 응답 캐싱, 재시도 정책, 회로 차단기, 속도 제한 및 조절, SSL 인증, 로깅, 모니터링, 부하 분산 등

BFF(Backend for Frontend) 패턴

image
  • 특정 Frontend 애플리케이션에 따라 API Gateway를 분리하는 방식이다.
  • BFF를 위한 여러 API Gateway를 구성하고 클라이언트에 따라 경계를 구분한다.
    • 사용자 인터페이스에 따라 여러 API Gateway를 생성한다.
    • 클라이언트 애플리케이션에 내부 마이크로서비스와 연결되는 집중된 인터페이스를 제공한다.
  • 대규모 시스템이면 여러 API Gateway가 노출된다.(Web, Mobile, Desktop)

장점

  • 클라이언트 중심 인터페이스
  • Frontend 클라이언트 애플리케이션을 위한 집중화된 인터페이스
  • Frontend 코드의 최소 로직
  • 데이터 표현 간소화 - 다양한 Backend를 조합하여 Frontend에 필요한 데이터만을 전달할 수 있다.

단점

  • 지연 시간 증가
  • 여러 클라이언트 애플리케이션이 있는 대규모 마이크로서비스에 적합하다.

Service Aggregator Pattern

image
  • 클라이언트 또는 API Gateway에서 요청을 수신한다.
  • 여러 내부 백엔드 마이크로서비스에 요청을 보낸 후 전송 결과를 결합해 1개의 데이터로 응답한다.
  • 비즈니스 로직을 특수 마이크로서비스로 중앙 집중화가 가능해진다.

Service Registry/Discovery Pattern

image
  • Service Registry 역할
    • 마이크로서비스의 네트워크 위치 정보 등록
    • 마이크로서비스 인스턴스의 중앙 DB
    • 마이크로서비스는 지정된 간격으로 정보 업데이트
    • 클라이언트는 Service Registry를 사용하여 마이크로서비스의 위치를 검색한 후 직접 호출한다.(대표적으로 Netflix Eureka가 있다.)
  • Client Service : Service Registry에 질의해 다른 서비스의 위치를 검색한다.
  • Inner Backend Service : 사용 전에 Service Registry에 등록하는 과정이 필요하다.
  • Kubernetes는 서비스 검색 작업을 자동으로 처리할 수 있게 된다.
image
  • Service Discovery 역할
    • 마이크로서비스를 배포하고 확장할 때 분산 애플리케이션들에게 확장성을 제공한다.
    • 더 많은 마이크로서비스 및 인스턴스 추가가 가능하다.
  • 클러스터에서 마이크로서비스를 등록(Registry), 검색(Discovery)
    • 서비스를 주입하거나 결합하는 방식이 아니라 마이크로서비스의 네트워크 위치 검색으로 이루어진다.
  • 클라이언트 및 내부 마이크로서비스로 트래픽 라우팅이 이루어진다.

장점

  • 잦은 통신 호출이 감소된다.
  • 여러 백엔드 서비스를 위한 추상화 작업
  • 특정 마이크로서비스에 로직 집중이 가능하다.
  • 마이크로서비스 등록, 검색, 위치 추적이 가능하다.

단점

  • 지연 시간이 증가한다.
  • 여러 클라이언트 애플리케이션이 있는 대규모 마이크로서비스에 적합하다.
  • 동기화 통신을 해결하기 위한 패턴이다.

Service Discovery + API Gateway, Backend for Frontend(BFF) 연동 로직 흐름 정리📒

image
  • 서비스 시작 → Eureka에 "서비스 이름/IP/포트"를 등록한다.
  • 클라이언트 요청 → Gateway가 Eureka에서 "USER-SERVICE" 위치를 조회한 후 로드밸런서(Gateway)가 인스턴스를 선택해 요청을 전달한다.
# Eureka 서버 자체는 자기 자신에게 등록하지 않는다.
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8761/eureka

# # 각 서비스는 Eureka에 등록한다.
spring:
  config:
    activate:
      on-profile: default
  application:
    name: apigateway-service
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: user-service-route
          uri: lb://USER-SERVICE
          predicates:
            - Path=/user-service/**
          filters:
            - RemoveRequestHeader=Cookie
            - RewritePath=/user-service/(?<segment>.*), /$\{segment}
        - id: order-service-route
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/order-service/**
          filters:
            - RemoveRequestHeader=Cookie
            - RewritePath=/order-service/(?<segment>.*), /$\{segment}
uri: lb://ORDER-SERVICE
uri: lb://USER-SERVICE
  • 클라이언트가 요청을 Gateway로 보낸다.
  • Gateway가 predicates: Path=/user-service/** 조건을 보고 user-service-route를 선택한다.
  • RewritePath 필터가 /user-service/users → /users로 경로 변환을 수행한다.
  • lb://USER-SERVICE를 보고 Eureka에 USER-SERVICE가 어디있는지 확인하고 Eureka가 127.0.0.1:8081 주소를 반환해준다.
  • 그럼 Gateway가 http://127.0.0.1:8081/users로 실제 요청이 전달되어 요청 처리 후 응답을 반환한다.
  • 마지막으로 Gateway가 클라이언트에게 응답을 전달하게 된다.
⚠️ **GitHub.com Fallback** ⚠️