https://youtu.be/Ci_DsTkzcRY?si=p0SWeCcZpYWeox9j
API Gateway란?
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라고 부르는 것을 확인.
- 클라이언트 요청을 적절한 서비스로 전달하는 Routing 기능.
- 많은 서비스에서 공통으로 필요한 기능을 대신 처리해준다. (Cross-Cutting Concerns)
배민에서 왜 필요했는가?
배민은 Monolitic 서비스를 MSA 서비스로 전환한 이력을 가지고 있음.
'배민에서 왜 필요했는가'라는 질문을 재정의하면, 'MSA 구조에서 API Gateway가 왜 필요했는가?' 라고도 볼 수 있다.
MSA 구조로 전환되면서, 하나의 지면을 보여주는 데에도 여러 서비스 호출이 필요해짐. 예컨대 마이배민 화면을 보면
- 회원정보, 포인트, 쿠폰, 선물... 등 다양한 화면.
- 각각의 서비스는 도메인 단위로 분리하기 좋은 것들. 따라서 다 분리되어 있다.
그런데, 클라이언트가 수많은 MSA 서비스를 직접 호출하게 될 경우
- 클라이언트 의존성 증가로 인한 확장성 저하. i.e. 클라이언트가 필요로 하는 것들을 전달해줘야 함
- 불필요한 정보가 클라이언트에 노출될 수 있음.
- 예컨대 클라이언트는 이메일만 필요한데, MSA 시스템은 회원정보 전체를 전달함.
- 클라이언트에 비즈니스 정책이 노출된다.
- 예컨대 A와 B라는 서비스에서 각각 api 결과를 확인해야 특정 상태를 결정하는 로직이 있을 때, 클라이언트와 직접 연결될 경우 A 호출, B 호출 이후 상태결정 로직을 클라이언트가 해야 함.
- 핵심 비즈니스일 경우, 이런 식의 결과노출은 바람직하지 않음
이런 문제를 해결하는 디자인 패턴이 API Gateway Pattern. (패턴 이름인 거고, 이게 api gateway라는 프로덕트를 뜻하진 않는다. 배민에서는 이런 개념을 뜻하는 서비스를 '프론트 서버'라고 소개한 바 있음)
- 패턴의 핵심은 '클라이언트를 전담하는 api' 제공.
- 이 api의 존재로 도메인 <-> 클라이언트 간 의존성 제거, 필요한 정보만 전달, 비즈니스 정책이 반영된 결과를 전달하는 게 가능해짐.
즉, MSA 구조로 바뀌면서 발생하는 문제를 'API Gateway Pattern'을 따르는 프론트 서버가 해결했다.
- 단순히 MSA에서 도메인이 분할되면서 발생하는 문제 때문에 API Gateway가 필요한 게 아님
MSA 방식을 따르다 보면 마주하는 Conway's Law
- 어떤 조직이 설계하는 시스템은, 그 조직의 의사소통 구조를 반영한다
- 쉽게 말해 '조직의 비즈니스 영역'이 하나하나의 MSA가 되는 것.
- 이 법칙을 따라야 한다는 정언명령이 아니라, 좋은 아키텍처를 만들다 보면 이 법칙으로 수렴하게 된다는 의미의 Law임.
백엔드 서비스만 MSA와 Conway's Law를 따르는 게 아님. 프론트 서버도 결국 Monolitic이 아니라 MSA 구조로 가게 된다.
- 회원 도메인 -> 회원 로직 처리하는 프론트 서버
- 주문 도메인 -> 주문 로직 처리하는 프론트 서버
- 가게 목록: 지면 하나에 리뷰, 광고, 쿠폰 등 다양한 도메인이 필요한 영역.
- 다양한 도메인을 취합해야 동작할 수 있는 영역 -> 특정 도메인에서 프론트 서버를 전담할 수가 없다.
- 따라서 이런 경우 Reverse Conway's Law가 적용됨.
- 시스템 구조를 보니, 담당할 조직이 필요하다 -> 조직을 만든다 ('전시')
이렇게, 프론트 서버도 도메인별로 분할되어 여러 개 만들어진다.
- 그러면서 발생하는 게 '횡단관심사' 문제.
- 각 서비스별로 처리해야 하는 공통영역 - 인증, 보안, 모니터링, 탄력성 - 이 겹치게 됨
이게 문제가 되는 이유는, 겹치는 시스템이 많아질수록 유지보수 비용이 급증하기 때문.
- 공통영역을 10개의 도메인이 공유한다? -> 예컨대 인증이나 보안에서 변경이 필요해지면, 10개의 도메인에서 다 수정해줘야 함
- 근본적으로 MSA는 서비스 규모가 커질수록 microservice 개수가 증가하고, 공통영역인 횡단관심사 또한 증가할 수밖에 없는 구조
따라서, 횡단관심사는 서비스가 커지면서 반드시 해결해야 하는 문제.
MSA 규모가 커지면서 발생하는 인증, 보안, 모니터링 등 횡단관심사 문제를 해결하기 위한 게 바로 API Gateway.
API Gateway vs API Gateway Pattern
둘은 같은 게 아니다. 도면으로 그려보면 구조는 비슷한데, 세부적으로 뜯어보면 차이가 있음.
API Gateway Pattern: MSA 구조에서, 클라이언트가 필요한 요구사항을 전담할 수 있는 Client-Specific 서비스.
- 클라이언트 문제 해소에 초점
API Gateway: 횡단관심사 문제 해결이 목적
- 클라이언트나 서버의 문제를 해결하려는 게 아니라, MSA가 커지면서 생기는 공통영역 문제를 해결하기 위한 것.
그러나, API Gateway를 잘 운영하려면 API Gateway Pattern을 알아야 한다고 생각함.
예컨대 API Gateway를 쓰고 싶어하는 두 가지 Case가 있다고 하자.
Case1: 클라이언트와 통신하는 서비스를 쓰고 있는데
- 백엔드와 통신중인 클라이언트 서버 비용이 아깝다.
- API Gateway로 교체하고 싶다.
Case2: private 영역에서만 서비스를 운영중
- 외부로 서비스 오픈하기 위한 Public 서버로 API Gateway를 쓰고 싶다.
이건 프론트 서버에서 해야 할 일을 API Gateway로 해결하려는 시도. 이 경우, API Gateway를 쓰지 않도록 해야 한다.
API Gateway는 특정 비즈니스 로직을 추가할 수 없다. 비즈니스와 무관한 '횡단관심사' 해결에 집중해야 함.
- 어느 하나의 비즈니스 레이어에 종속되면, 비즈니스의 변화가 API Gateway에 영향을 줄 수 있음.
- Routing 기능도 본질적으로는 비즈니스 로직과 무관함. Proxy 느낌.
쉽게 요약한다면
- API Gateway Pattern: MSA에서, 클라이언트와 서버 간 비즈니스 분산 문제를 해결하기 위한 프론트 서버.
- API Gateway: 프론트 서버가 여러 개 있을 때 생기는 횡단관심사 문제 - 인증, 보안, 모니터링 등 - 를 해결하기 위한 서버.
따라서, API Gateway와 API Gateway Pattern은 해결하는 문제가 서로 다르다.
API Gateway는 API Gateway Pattern이 적용된 서버와 연결해야 한다.
배민 API Gateway 구조 소개
시스템 구조
- SPOF 방지를 위한 Scalable한 구조 - 인프라가 허용하는 선에서 무한히 확장 가능하도록 한다.
- 서비스 영향도에 따라 클러스터 개념으로 분리해서 운영중.
- 다중 서버군 운영하면서, 영향도에 따라 적절히 배치함.
예컨대 특정 API Gateway 서버 하나가 죽더라도, DNS 변경만 잘해주면 다른 서버로 넘겨서 정상적인 통신이 가능하도록 한다
서비스에 문제가 있거나 트래픽이 폭증해서 서비스가 불안정할 경우, 동적으로 특정 서버그룹을 만들어서 연결해주는 식.
즉 물리적 분산, Scale이 가능한 구조 / 논리적으로는 동일한 코드베이스를 공유하는 하나의 애플리케이션
애플리케이션 구조
기본적으로는 Spring Cloud Gateway 사용.
- 좋은 기능과 안정적인 환경을 지원하기 때문.
- 단, 유연한 설정 / 동적인 기능을 위해 커스텀했음.
- i.e. 원래 Spring Cloud Gateway는 Property 기반 동작방식인데, DB 기반으로 동작하도록 수정
- Cloud Gateway는 적용해야 하는 Filter의 규칙과 순서가 중요한데, 내부에서 개발한 커스텀 필터를 잘못 적용하면 순서 때문에 동작에 문제가 생김.
- 별도의 Filter Chain 만들어서 운영중.
Cloud Gateway는 Fully Reactive 환경임. 따라서 Kotlin + Koroutine 사용.
애플리케이션은 DB 설정에 따라 서비스별로 필요한 설정을 관리할 수 있음.
Routing과 Filtering 기능을 지원한다.
- Routing: 도메인 기반, Path 기반 라우팅 가능
- Filtering: 요청 단위로 필터링 가능. Spring MVC에도 쓰이는 Best Matching
- API Path별로 필터 적용
기능 1. 인증
API Gateway가 필요했던 직접적인 이유.
- 서비스가 커지면서, 인증 시스템에 의존하는 서비스가 엄청나게 많아짐
- SPOF 요소
처음에는 JWT 토큰을 도입하려고 시도.
- 인증시스템에 문제가 생겼을 때, 각 서비스에서도 인증을 처리할 수는 있어야 함.
- 그러려면, 개별 시스템이 '인증 로직', '인증에 쓰이는 키'를 전부 소유하고 있어야 함...
- 만약 인증키에 문제가 생겨서 교체해야 한다? -> 모든 서비스가 전부 교체해야 함... 시간도 오래 걸림
즉, 방대한 MSA 구조에서는 쉽지 않았다. 전형적인 '횡단 관심사' 문제
API Gateway가 인증을 처리하고, 처리된 결과와 클라이언트 정보를 취합해서 백엔드 서비스에 전달.
- 백엔드 서비스는 인증에 신경쓸 필요가 없음.
- 인증시스템에 문제가 생길 경우, API Gateway에서 JWT 인증키로 대응 가능.
- 인증키 만료나 변경에도 유연하게 대응 가능.
기능 2. 라우팅
Request 정보를 이용하면 Routing을 어디로 보낼지 결정하기 쉬움.
- token과 IP 정보 받아서, 특정 IP 대역일 경우 Test서버로 보낸다거나
- 인증 결과로 나온 필드 기반으로 특정 서버로 라우팅한다거나
운영 테스트, 타겟팅, 카나리, 점진적인 서비스 투입, 서버 전환 등 다양한 기능이 가능함.
기타 나머지 기능 (보안, 흐름제어)
외부로부터 오는 서비스 공격도, 개별 서비스가 구현하는 대신 API Gateway에서 대응하면 편함.
트래픽 과부하나 서비스 불안정과 같은 상황에서도 안정적으로 대응하기 위한 방법.
- Rate Limiting, Circuit Breaker, Fallback, Retry, Static Response (서버 통하지 않고 Gateway에서 응답) 등등
마무리
'학습일지 > 네트워크' 카테고리의 다른 글
KubeCon 2019 - The story of Why we migrate to gRPC and How we go about it (Spoti (0) | 2022.10.12 |
---|---|
KubeCon 2018 - Using gRPC for long-lived and Streaming RPCs (0) | 2022.09.12 |
Deview 2021 - NAVER 암호화 트래픽을 책임지는 HTTPS 플랫폼 기술 - 2. 활용 (0) | 2022.06.13 |
Deview 2021 - NAVER 암호화 트래픽을 책임지는 HTTPS 플랫폼 기술 - 1. 기술 (0) | 2022.06.11 |
gRPC (4) - Client Streaming 개념 및 예제코드 (0) | 2021.08.16 |