MSA에 대한 고찰 (6)

들어가며

우리는 앞에서 회원과 상품, 주문을 분리하기로 결정하고 각가 다른 포트(8081, 8082, 8083)에서 독립적으로 실행된다고 가정해보자. 이런 경우에 여러 문제가 발생하게 된다.

  1. 클라이언트의 복잡성: 클라이언트 팀에서는 이제 회원 정보를 api.commerce.com:8081로, 상품 정보, 주문은 모두 따로 호출해야 한다. 하지만 상품 서비스가 트래픽이 폭증하여 10대로 증설되면(scale-out), 클라이언트는 이 10개의 주소를 모두 알고 로드밸런싱까지 해야할까? 이건 불가능하다.

  2. 중복되는 ‘횡단 관심사’ (Cross-Cutting Concerns)

    • 인증/인가: 사용자가 상품 주문을 한다. 상품 서비스도 이 사용자가 유효한자 JWT 토큰을 검사해야하고 주문 서비스도 같은 토큰을 검사해야 한다. 모든 마이크로 서비스가 ‘인증’이라는 동일한 로직을 중복으로 구현해야 한다.
    • 공통 로깅: 모든 시스템에 들어오는 API 요청을 로깅하고 싶다면, 이 로깅 코드를 5개의 서비스에 모두 복사 / 붙여넣기 해야한다.
    • CORS 및 보안: CORS(Cross Origin Resource Sharing)설정, SSL/TLS 처리, IP 기반 접근 제한 등을 모든 서비스가 개별적으로 처리해야 한다.

이러한 문제를 해결하지 못한다면, MSA의 독립 배포라는 장점은 얻을 수 있지만 유지보수쪽에서의 한계가 명확해진다.

단일 진입점 API Gateway

API 게이트웨이는 이 모든 문제를 해결하는 gatekeeper이다.

API 게이트웨이는 MSA 시스템의 유일한 정문(SPOE)의 역할을 수행한다. 마치 안내 데스크와 같은데, 방문객은 건물의 수백개 사무실의 주소를 알 필요가 없다. 방문객이 정문에 도착하면, 안내 데스크가 방문객의 신원을 인증을 확인하고, 방문 목적에 맞는 사무실로 안내해 준다.

API 게이트웨이는 이 역할을 통해 두 가지 가치를 제공한다.

  1. 라우팅: 클아이언트 복잡성 제거 클라이언트는 오직 게이트웨이의 주소(예: https://api.ecommerce.com) 하나만 알고 있다.
    • 클라이언트가 api를 호출한다.
    • 게이트웨이는 이 요청을 받고, 자신의 라우팅 테이블을 확인한다.
    • api/v1/members/** 경로는 member service로 가야함을 인지하고 요청을 대신 전달해준다.
    • 클라이언트는 자신의 요청이 내부적으로 member-service로 갔는지, product-service로 갔는지 전혀 알 필요가 없다.
  2. 필터: 횡단 관심사의 중앙 처리 게이트 웨이는 정문이므로 모든 요청이 통과하는 검문소의 역할을 한다. 이 검문의 기능이 필터이다.
  • 인증/인가 (Authentication/Authorization): 모든 요청이 게이트웨이를 통고할 때, 게이트웨이가 딱 한 번만 JWT 토큰을 검증한다. 토큰이 유효하면, 게이트 웨이는 X-Member-Id: 123과 같은 신뢰할 수 있는 헤더를 추가하여 요청을 전달한다. 그러면 내부 서비스에서는 헤더값만을 통해 비즈니스로직을 처리하면 된다.
  • 공통 로깅 및 메트릭: 게이트웨이에서 모든 요청/응답을 중앙에서 로깅하고, API별 호출 횟수나 응답 시간을 수집한다.
  • 보안 및 속도 제한: 악의적인 IP를 차단하고, API의 rate limit을 담당한다.

결론적으로 API 게이트웨이는 MSA를 운영 가능한 시스템으로 만들어주는 컴포넌트이다. 이제 제일 최신의 리액티브 게이트웨이인 Spring Cloud Gateway를 코틀린으로 구축해보자.