공부하고 기록하는, 경제학과 출신 개발자의 노트

학습일지/네트워크

우아콘 2024 - 배달의민족 API Gateway

inspirit941 2024. 12. 18. 17:00
반응형

 

 

https://youtu.be/Ci_DsTkzcRY?si=p0SWeCcZpYWeox9j

 

 

스크린샷 2024-12-18 오후 12 43 13

 

API Gateway란?

스크린샷 2024-12-18 오후 12 44 34스크린샷 2024-12-18 오후 12 44 46스크린샷 2024-12-18 오후 12 48 41

 

 

api 요청 받고, 필요한 정책 수행하고, 필요한 곳에 요청을 보낸 뒤 응답을 되돌려준다?

  • 생각보다 명확하게 정의된 게 없음.
  • 2013년 Netflix Zuul부터 2015년 AWS API Gateway, 2017년 Spring Cloud Gateway 등 프로덕트를 찾아봐도 정의가 명확한 건 없었음.
    • 오픈소스 프로젝트인 Kong의 경우, API Management라는 이름으로 시작되었다가 슬그머니 API Gateway라는 표현을 쓰기 시작.
  • Cloud Native 이후 MSA까지 등장하면서 API Gateway는 꽤 보편화된 용어가 됨

그래도 잘 모르겠어서 네 개 프로덕트 소개를 전부 찾아봤음. 본인들이 API Gateway를 어떻게 정의했는지.

결과적으로, 큰 범주에서 두 가지 기능을 지원하면 API Gateway라고 부르는 것을 확인.

 

 

스크린샷 2024-12-18 오후 12 52 46스크린샷 2024-12-18 오후 12 52 57스크린샷 2024-12-18 오후 12 53 03스크린샷 2024-12-18 오후 12 53 36

 

  • 클라이언트 요청을 적절한 서비스로 전달하는 Routing 기능.
  • 많은 서비스에서 공통으로 필요한 기능을 대신 처리해준다. (Cross-Cutting Concerns)

 

 

배민에서 왜 필요했는가?

스크린샷 2024-12-18 오후 12 56 55

 

배민은 Monolitic 서비스를 MSA 서비스로 전환한 이력을 가지고 있음.

'배민에서 왜 필요했는가'라는 질문을 재정의하면, 'MSA 구조에서 API Gateway가 왜 필요했는가?' 라고도 볼 수 있다.

스크린샷 2024-12-18 오후 12 56 36

 

 

MSA 구조로 전환되면서, 하나의 지면을 보여주는 데에도 여러 서비스 호출이 필요해짐. 예컨대 마이배민 화면을 보면

  • 회원정보, 포인트, 쿠폰, 선물... 등 다양한 화면.
  • 각각의 서비스는 도메인 단위로 분리하기 좋은 것들. 따라서 다 분리되어 있다.

 

 

스크린샷 2024-12-18 오후 1 51 53

 

그런데, 클라이언트가 수많은 MSA 서비스를 직접 호출하게 될 경우

  • 클라이언트 의존성 증가로 인한 확장성 저하. i.e. 클라이언트가 필요로 하는 것들을 전달해줘야 함
  • 불필요한 정보가 클라이언트에 노출될 수 있음.
    • 예컨대 클라이언트는 이메일만 필요한데, MSA 시스템은 회원정보 전체를 전달함.
  • 클라이언트에 비즈니스 정책이 노출된다.
    • 예컨대 A와 B라는 서비스에서 각각 api 결과를 확인해야 특정 상태를 결정하는 로직이 있을 때, 클라이언트와 직접 연결될 경우 A 호출, B 호출 이후 상태결정 로직을 클라이언트가 해야 함.
    • 핵심 비즈니스일 경우, 이런 식의 결과노출은 바람직하지 않음

 

스크린샷 2024-12-18 오후 1 58 09스크린샷 2024-12-18 오후 1 58 27

 

이런 문제를 해결하는 디자인 패턴이 API Gateway Pattern. (패턴 이름인 거고, 이게 api gateway라는 프로덕트를 뜻하진 않는다. 배민에서는 이런 개념을 뜻하는 서비스를 '프론트 서버'라고 소개한 바 있음)

  • 패턴의 핵심은 '클라이언트를 전담하는 api' 제공.
  • 이 api의 존재로 도메인 <-> 클라이언트 간 의존성 제거, 필요한 정보만 전달, 비즈니스 정책이 반영된 결과를 전달하는 게 가능해짐.

스크린샷 2024-12-18 오후 2 00 43스크린샷 2024-12-18 오후 2 01 48스크린샷 2024-12-18 오후 2 01 54

 

즉, MSA 구조로 바뀌면서 발생하는 문제를 'API Gateway Pattern'을 따르는 프론트 서버가 해결했다.

  • 단순히 MSA에서 도메인이 분할되면서 발생하는 문제 때문에 API Gateway가 필요한 게 아님

스크린샷 2024-12-18 오후 2 03 32

 

MSA 방식을 따르다 보면 마주하는 Conway's Law

  • 어떤 조직이 설계하는 시스템은, 그 조직의 의사소통 구조를 반영한다
  • 쉽게 말해 '조직의 비즈니스 영역'이 하나하나의 MSA가 되는 것.
  • 이 법칙을 따라야 한다는 정언명령이 아니라, 좋은 아키텍처를 만들다 보면 이 법칙으로 수렴하게 된다는 의미의 Law임.

스크린샷 2024-12-18 오후 2 05 04스크린샷 2024-12-18 오후 2 06 36스크린샷 2024-12-18 오후 2 06 52

 

백엔드 서비스만 MSA와 Conway's Law를 따르는 게 아님. 프론트 서버도 결국 Monolitic이 아니라 MSA 구조로 가게 된다.

  • 회원 도메인 -> 회원 로직 처리하는 프론트 서버
  • 주문 도메인 -> 주문 로직 처리하는 프론트 서버
  • 가게 목록: 지면 하나에 리뷰, 광고, 쿠폰 등 다양한 도메인이 필요한 영역.
    • 다양한 도메인을 취합해야 동작할 수 있는 영역 -> 특정 도메인에서 프론트 서버를 전담할 수가 없다.
    • 따라서 이런 경우 Reverse Conway's Law가 적용됨.
    • 시스템 구조를 보니, 담당할 조직이 필요하다 -> 조직을 만든다 ('전시')

스크린샷 2024-12-18 오후 2 10 25스크린샷 2024-12-18 오후 2 11 23

 

이렇게, 프론트 서버도 도메인별로 분할되어 여러 개 만들어진다.

  • 그러면서 발생하는 게 '횡단관심사' 문제.
  • 각 서비스별로 처리해야 하는 공통영역 - 인증, 보안, 모니터링, 탄력성 - 이 겹치게 됨

스크린샷 2024-12-18 오후 2 12 18스크린샷 2024-12-18 오후 2 13 51

 

이게 문제가 되는 이유는, 겹치는 시스템이 많아질수록 유지보수 비용이 급증하기 때문.

  • 공통영역을 10개의 도메인이 공유한다? -> 예컨대 인증이나 보안에서 변경이 필요해지면, 10개의 도메인에서 다 수정해줘야 함
  • 근본적으로 MSA는 서비스 규모가 커질수록 microservice 개수가 증가하고, 공통영역인 횡단관심사 또한 증가할 수밖에 없는 구조

따라서, 횡단관심사는 서비스가 커지면서 반드시 해결해야 하는 문제.

스크린샷 2024-12-18 오후 2 16 20스크린샷 2024-12-18 오후 2 18 10

 

MSA 규모가 커지면서 발생하는 인증, 보안, 모니터링 등 횡단관심사 문제를 해결하기 위한 게 바로 API Gateway.

API Gateway vs API Gateway Pattern

스크린샷 2024-12-18 오후 2 18 41

 

둘은 같은 게 아니다. 도면으로 그려보면 구조는 비슷한데, 세부적으로 뜯어보면 차이가 있음.

스크린샷 2024-12-18 오후 2 21 58

 

API Gateway Pattern: MSA 구조에서, 클라이언트가 필요한 요구사항을 전담할 수 있는 Client-Specific 서비스.

  • 클라이언트 문제 해소에 초점

API Gateway: 횡단관심사 문제 해결이 목적

  • 클라이언트나 서버의 문제를 해결하려는 게 아니라, MSA가 커지면서 생기는 공통영역 문제를 해결하기 위한 것.

스크린샷 2024-12-18 오후 2 23 41

 

그러나, API Gateway를 잘 운영하려면 API Gateway Pattern을 알아야 한다고 생각함.

스크린샷 2024-12-18 오후 3 07 26

 

예컨대 API Gateway를 쓰고 싶어하는 두 가지 Case가 있다고 하자.

Case1: 클라이언트와 통신하는 서비스를 쓰고 있는데

  • 백엔드와 통신중인 클라이언트 서버 비용이 아깝다.
  • API Gateway로 교체하고 싶다.

Case2: private 영역에서만 서비스를 운영중

  • 외부로 서비스 오픈하기 위한 Public 서버로 API Gateway를 쓰고 싶다.

이건 프론트 서버에서 해야 할 일을 API Gateway로 해결하려는 시도. 이 경우, API Gateway를 쓰지 않도록 해야 한다.

스크린샷 2024-12-18 오후 3 09 34

 

API Gateway는 특정 비즈니스 로직을 추가할 수 없다. 비즈니스와 무관한 '횡단관심사' 해결에 집중해야 함.

  • 어느 하나의 비즈니스 레이어에 종속되면, 비즈니스의 변화가 API Gateway에 영향을 줄 수 있음.
  • Routing 기능도 본질적으로는 비즈니스 로직과 무관함. Proxy 느낌.

스크린샷 2024-12-18 오후 3 20 15

 

쉽게 요약한다면

  • API Gateway Pattern: MSA에서, 클라이언트와 서버 간 비즈니스 분산 문제를 해결하기 위한 프론트 서버.
  • API Gateway: 프론트 서버가 여러 개 있을 때 생기는 횡단관심사 문제 - 인증, 보안, 모니터링 등 - 를 해결하기 위한 서버.

스크린샷 2024-12-18 오후 3 22 26

 

따라서, API Gateway와 API Gateway Pattern은 해결하는 문제가 서로 다르다.

API Gateway는 API Gateway Pattern이 적용된 서버와 연결해야 한다.

배민 API Gateway 구조 소개

시스템 구조

스크린샷 2024-12-18 오후 3 24 23

 

  • SPOF 방지를 위한 Scalable한 구조 - 인프라가 허용하는 선에서 무한히 확장 가능하도록 한다.
  • 서비스 영향도에 따라 클러스터 개념으로 분리해서 운영중.
    • 다중 서버군 운영하면서, 영향도에 따라 적절히 배치함.

스크린샷 2024-12-18 오후 3 26 29스크린샷 2024-12-18 오후 3 26 34

 

예컨대 특정 API Gateway 서버 하나가 죽더라도, DNS 변경만 잘해주면 다른 서버로 넘겨서 정상적인 통신이 가능하도록 한다

 

스크린샷 2024-12-18 오후 3 27 31스크린샷 2024-12-18 오후 3 27 25

 

서비스에 문제가 있거나 트래픽이 폭증해서 서비스가 불안정할 경우, 동적으로 특정 서버그룹을 만들어서 연결해주는 식.

즉 물리적 분산, Scale이 가능한 구조 / 논리적으로는 동일한 코드베이스를 공유하는 하나의 애플리케이션

 

애플리케이션 구조

스크린샷 2024-12-18 오후 3 31 44

 

기본적으로는 Spring Cloud Gateway 사용.

  • 좋은 기능과 안정적인 환경을 지원하기 때문.
  • 단, 유연한 설정 / 동적인 기능을 위해 커스텀했음.
    • i.e. 원래 Spring Cloud Gateway는 Property 기반 동작방식인데, DB 기반으로 동작하도록 수정
    • Cloud Gateway는 적용해야 하는 Filter의 규칙과 순서가 중요한데, 내부에서 개발한 커스텀 필터를 잘못 적용하면 순서 때문에 동작에 문제가 생김.
      • 별도의 Filter Chain 만들어서 운영중.

스크린샷 2024-12-18 오후 3 35 08

 

Cloud Gateway는 Fully Reactive 환경임. 따라서 Kotlin + Koroutine 사용.

스크린샷 2024-12-18 오후 3 36 18

 

애플리케이션은 DB 설정에 따라 서비스별로 필요한 설정을 관리할 수 있음.

 

스크린샷 2024-12-18 오후 3 45 56스크린샷 2024-12-18 오후 3 45 56스크린샷 2024-12-18 오후 3 46 03스크린샷 2024-12-18 오후 3 54 35

 

Routing과 Filtering 기능을 지원한다.

  • Routing: 도메인 기반, Path 기반 라우팅 가능
  • Filtering: 요청 단위로 필터링 가능. Spring MVC에도 쓰이는 Best Matching
    • API Path별로 필터 적용

기능 1. 인증

스크린샷 2024-12-18 오후 4 01 03스크린샷 2024-12-18 오후 4 01 47

 

API Gateway가 필요했던 직접적인 이유.

  • 서비스가 커지면서, 인증 시스템에 의존하는 서비스가 엄청나게 많아짐
  • SPOF 요소

스크린샷 2024-12-18 오후 4 02 22스크린샷 2024-12-18 오후 4 04 56

 

처음에는 JWT 토큰을 도입하려고 시도.

  • 인증시스템에 문제가 생겼을 때, 각 서비스에서도 인증을 처리할 수는 있어야 함.
  • 그러려면, 개별 시스템이 '인증 로직', '인증에 쓰이는 키'를 전부 소유하고 있어야 함...
  • 만약 인증키에 문제가 생겨서 교체해야 한다? -> 모든 서비스가 전부 교체해야 함... 시간도 오래 걸림

즉, 방대한 MSA 구조에서는 쉽지 않았다. 전형적인 '횡단 관심사' 문제

스크린샷 2024-12-18 오후 4 27 40스크린샷 2024-12-18 오후 4 27 54

 

API Gateway가 인증을 처리하고, 처리된 결과와 클라이언트 정보를 취합해서 백엔드 서비스에 전달.

  • 백엔드 서비스는 인증에 신경쓸 필요가 없음.
  • 인증시스템에 문제가 생길 경우, API Gateway에서 JWT 인증키로 대응 가능.
  • 인증키 만료나 변경에도 유연하게 대응 가능.

기능 2. 라우팅

스크린샷 2024-12-18 오후 4 37 34스크린샷 2024-12-18 오후 4 37 45스크린샷 2024-12-18 오후 4 41 38

 

Request 정보를 이용하면 Routing을 어디로 보낼지 결정하기 쉬움.

  • token과 IP 정보 받아서, 특정 IP 대역일 경우 Test서버로 보낸다거나
  • 인증 결과로 나온 필드 기반으로 특정 서버로 라우팅한다거나

운영 테스트, 타겟팅, 카나리, 점진적인 서비스 투입, 서버 전환 등 다양한 기능이 가능함.

기타 나머지 기능 (보안, 흐름제어)

스크린샷 2024-12-18 오후 4 47 40

 

외부로부터 오는 서비스 공격도, 개별 서비스가 구현하는 대신 API Gateway에서 대응하면 편함.

스크린샷 2024-12-18 오후 4 46 30스크린샷 2024-12-18 오후 4 46 48

 

트래픽 과부하나 서비스 불안정과 같은 상황에서도 안정적으로 대응하기 위한 방법.

  • Rate Limiting, Circuit Breaker, Fallback, Retry, Static Response (서버 통하지 않고 Gateway에서 응답) 등등

스크린샷 2024-12-18 오후 4 52 39

마무리

스크린샷 2024-12-18 오후 4 52 56

 

반응형