API Gateway
사용자는 메인 페이지를 보기 위해서 하나의 URL을 통해 서버에 요청을 보내지만 실제 사용자가 보게 되는 화면에는 다양한 종류의 서비스 결과들 입니다. 그림에서 보여지는 붉은색 상자는 개별 서비스를 나타내며 위에서 부터 순서대로 이름을 붙여보자면, ‘사용자 서비스’, ‘뉴스 서비스’, ‘실시간 급상승 검색어 서비스’, ‘광고 서비스’, ‘날씨 서비스’ 등으로 나눌 수 있습니다.
그림 3. 검색 포털 메인화면에서의 다양한 종류의 서비스
만약, 모놀리틱 아키텍처를 이용해서 이와 같은 요청을 처리하는 애플리케이션을 구현하였다면 실제 요청이 도착하여 결과를 반환하기 까지 서버는 다양한 종류의 쿼리를 데이터베이스에 보내게 됩니다.
API Gateway는 그 이름에서도 유추할 수 있듯이 서비스로 전달되는 모든 API 요청의 관문(Gateway) 역할을 하는 서버입니다. API Gateway는 시스템의 아키텍처를 내부로 숨기고 외부의 요청에 대한 응답만을 적합한 형태로 응답합니다. 즉, 클라이언트는 시스템 내부의 아키텍처가 마이크로서비스 형태로 되어있는지 모놀리틱 아키텍처로 구현되어 있는지를 알 필요가 없으며 서로 약속한 형태의 API 요청만을 서버로 보내면 알맞는 형태의 결과를 받을 수 있습니다.
모든 사용자의 API 요청은 그림 6과 같이 제일 먼저 API Gateway에 도착하게 됩니다. API Gateway는 받은 요청을 기반으로 필요한 마이크로서비스에 개별적인 요청을 다시 보내게 됩니다. API Gateway는 각각의 마이크로서비스로부터 받은 응답들을 다시 취합하여 클라이언트에게 전달하는 역할을 수행합니다. 이 과정에서 API Gateway는 사용자의 HTTP 요청을 마이크로서비스가 받을 수 있는 다른 형태의 프로토콜로 전환하는 역할을 수행하기도 합니다. 앞에서 살펴본 검색 포털의 메인화면을 예로 들어 설명하자면, 사용자의 클라이언트는 메인 페이지에 대한 요청을 API Gateway에 보내고, 이 요청을 받은 API Gateway는 해당 요청의 응답에 필요한 정보들을 사용자서비스, 뉴스 서비스, 실시간 급상승 검색어 서비스, 광고 서비스, 날씨 서비스등에 해당 결과들을 하나의 응답으로 취합한 뒤 클라이언트에게 다시 전달하게 됩니다.
그림 6. API Gateway를 활용한 마이크로서비스 아키텍처에서의 요청 처리
API Gateway는 이처럼 클라이언트의 요청을 일괄적으로 처리하는 역할 뿐만 아니라, 전체 시스템의 부하를 분산시키는 로드 밸런서의 역할, 동일한 요청에 대한 불필요한 반복작업을 줄일 수 있는 캐싱, 시스템상을 오고가는 요청과 응답에 대한 모니터링 역할도 수행할 수 있습니다.
이렇게 API Gateway를 이용하여 서비스 요청에 대한 처리를 하게되면 특정 서비스의 변경사항이 생기거나 서비스가 통합/분리 되더라도 클라이언트는 그 사실을 인지할 필요가 없으며 API Gateway 내부의 변경사항만으로 처리가 가능하게 됩니다. 이렇게 API Gateway를 이용하여 서비스 요청에 대한 처리를 하게되면 특정 서비스의 변경사항이 생기거나 서비스가 통합/분리 되더라도 클라이언트는 그 사실을 인지할 필요가 없으며 API Gateway 내부의 변경사항만으로 처리가 가능하게 됩니다. 이렇게 시스템 내부의 아키텍처를 숨길 수 있는Encapsulate 특성이 API Gateway가 갖는 가장 큰 장점이라고 할 수 있습니다.
API Gateway는 다른 모든 것들과 마찬가지로 장점만을 갖는 것은 아닙니다. API Gateway가 갖는 대표적인 단점으로는 구현하고 관리해야하는 요소가 하나 더 증가한다는 점입니다. 예를 들어, 특정 마이크로서비스에 기능이 추가되는 경우, API Gateway가 포함된 해당 기능을 사용자에게 전달하기 위한 내용을 API Gateway에도 반영해 주어야 합니다. 이러한 이유 때문에 API Gateway를 관리하는 절차가 최소화 되어야만 합니다.
API Gateway가 갖는 또 하나의 단점은 성능상의 병목(bottleneck)지점이 될 수 있다는 점입니다. 앞에서 설명한 바와 같이 API Gateway는 모든 요청을 수용해야 하는 창구 역할을 하기 때문에 이 부분에 병목현상이 발생하면 서비스 전체의 품질에 지대한 영향을 미치게 됩니다. 이러한 이유 때문에 API Gateway를 설계하고 구현할 때에는 항상 성능과 확장성을 고려해야만 합니다. 특히, API Gateway를 비동기(asynchronous)적이고 non-blocking I/O 처리가 가능하도록 구현하는 것이 적은 비용으로 최대의 성능을 발휘할 수 있는 관건이 됩니다.
##
API GATEWAY 구현시 고려해야할 점들
앞서 살펴본 검색 포털의 메인화면을 잘 살펴보면 각각의 서비스들이 서로 독립적으로 동작가능하다는 점을 알 수 있습니다. 이러한 경우 API Gateway는 동시에 여러개의 요청을 각각의 마이크로서비스에 전달하는 것이 가능합니다. 하지만, 모든 요청이 이와 같이 병렬로 처리될 수 있는 것은 아닙니다. 예를 들어, 검색 포털에서 카페의 메인화면을 표시하기 위해서 API Gateway는 먼저 ‘사용자 서비스’에 요청을 보내어 사용자 정보를 가져와야 하며, 이 정보를 기반으로 해당 사용자가 어떤 까페에 가입화여 활동중인지를 ‘카페 서비스’에 요청해야 합니다. 즉, 개별 마이크로서비스로 보내는 요청의 선후관계가 존재하게 되는 것입니다. 이러한 경우 일반적인 비동기처리를 위해서 콜백(callback) 함수를 이용하게됩니다. 즉, 사용자 서비스로 부터 정보를 받아온 뒤 이 요청의 콜백함수에서 카페 서비스로 다시 요청을 보내게 되는 것입니다. 이러한 방식의 애플리케이션 코드는 흔히 말하는 콜백 지옥(callback hell)을 경험하게 할 수 있으며 유지보수와 소스코드의 가독성을 현저하게 악화시키는 원인이 되곤 합니다.
이러한 문제점 때문에 많은 언어와 프레임워크들은 동일한 처리를 수행하는 코드를 좀 더 직관적이고 서술적으로 표현할 수 있는 Reactive 프로그래밍을 고안하게 되었습니다. 대표적인 reactive 프로그래밍 방식으로는 자바스크립트의 Promise, 스칼라의 Future등이 있습니다. 이러한 reactive 접근방식을 잘 활용하여 API Gateway를 구현하게 되면 비동기 처리의 성능적인 이점은 유지하면서 좀 더 직관적이고 관리하기 쉬운 코드를 작성할 수 있습니다.
API Gateway를 구현할 때 고려해야하는 또 한 가지 중요한 점은 예외에 대한 처리입니다. 마이크로서비스 아키텍처에서는 모놀리틱 아키텍처에 비하여 분산된 서버의 상태와 여러가지 변수들로 인해서 일부 서비스에 장애가 발생하거나 응답속도가 지연될 가능성이 높아지게 됩니다. 이렇게 특정서비스에 문제가 발생했을 때 API Gateway는 서비스 장애의 종류에 따라 적절한 처리가 가능하도록 설계/구현되어야 합니다. 예를 들어, 카페 메인화면에 대한 요청을 처리하는 과정에서 특정 서비스에 장애가 발생하는 상황을 예로 들어보도록 하겠습니다. 카페 메인화면에는 사용자 정보와 사용자가 가입한 카페 목록, 그리고 사용자가 관심을 가질만한 추천 카페 목록을 표시한다고 가정해 보겠습니다. 이 과정에서 ‘추천 카페 목록’을 제공하는 ‘추천 서비스’에서 장애가 발생하는 경우 일반적으로 카페 메인화면은 정상적으로 표시가 되고 추천 목록에는 임시적인 페이지로 대체되는 것이 적당할 것 입니다. 반면, 카페 목록을 제공해야 하는 ‘카페 서비스’에 장애가 발생하는 경우에는 가장 중요한 정보를 전달할 수 없기 때문에 오류 처리를 하는 것이 적합할 것 입니다. 이처럼 API Gateway는 특정 요청에 대하여 개별 서비스의 특수한 장애 상황에 대해서 어떻게 대처할지에 대한 고려가 구현시 포함되어야 합니다.
마지막으로 API Gateway는 모든 요청이 몰리는 지점이기 때문에 동일한 요청에 대하여 중복적으로 마이크로서비스에 요청을 보내는 것 보다 기존의 결과를 캐싱하여 재활용할 수 있도록 설계하는 것이 중요합니다. 예를 들어, 검색 포털의 메인화면에서 ‘날씨 서비스’와 같은 경우, 모든 요청에 대하여 반복적으로 현재 날씨를 가져오는 것 보다 주기적인 시간 단위로 갱신을 하며 한번 가져온 결과를 해당 주기 내에서 재활용하는 것이 불필요한 자원사용을 막는 현명한 방법이라고 할 수 있겠습니다.
참고
http://guruble.com/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4microservice-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B7%B8%EA%B2%83%EC%9D%B4-%EB%AD%A3%EC%9D%B4-%EC%A4%91%ED%97%8C%EB%94%94/