Post

8장 외부 API 패턴

8장 외부 API 패턴

목차

1
2
3
4
5
6
7
8
9
10
11
12
13
14
8장 외부 API 패턴
8.1 외부 API 설#계 이슈
__8.1.1 API 설계 이슈: FTGO 모바일 클#라이언트
__8.1.2 API 설계 이슈: 다른 종류의 클라이언트
8.2 API 게이트웨#이 패턴
__8.2.1 API 게이트웨이 패#턴 개요
__8.2.2 API 게이트웨이의# 장단점
__8.2.3 API 게이트웨이 사례: #넷플릭스
__8.2.4 API 게이트웨이 설계 이슈
8.3 API 게이트웨#이 구현
__8.3.1 기성 API 게이트웨이 제품/서비#스 활용
__8.3.2 API 게이트웨이 자#체 개발
__8.3.3 API 게이트웨이 구현: GraphQL
8.4 마치며

정리 전략?

  • 전부 정리는 NO
  • 핵심중에서 꼭 적고 가야겠다 싶은 것만!
  • 나의 생각을 섞어서 적을것..!
  • 떠오르는 것 먼저 간단하게..!

내용

8.1 외부 API 설계 이슈

  • 외부에 제공할 API를 설계한다고 생각해보자.
    • 이슈가 몇가지 있는데
        1. API 조합패턴으로 제공하자 라고 가정했을때 그 조합을 어디서 할것이며, 그 조합을 어떻게 할 것인가의 이슈가 있다.
        1. 그리고 API 설계한다고 했을때, api가 너무 많아질 경우. 클라이언트가 너무 다양할경우, API가 너무 많아질경우 어떻게 해야하나의 이슈
  • 모놀리식 애플리케이션 API를 클라이언트가 단순 호출하는 방식. 그러나 마이크로서비스 아키텍처에서는 다음과 같은 단점이 있기때문에 클라이언트 → API 직접호출 방식을 거의 쓰지 않음.

    • API가 나뉘어져 있기때문에 클라이언트가 필요한 데이터를 여러번 요청 해야하고, 그만큼 UX가 나빠진다.
    • 클라이언트가 서비스 및 API를 알아야 하는 구조라서 캡슐화가 되지 않고, 나중에 아키텍처와 API를 바꾸기 어렵다.
    • 클라이언트(특히 방화벽 외부) 사용하기에 불편하거나 실용적이지 못한 IPC를 서비스에 사용중인 경우가 있다. Untitled

**8.1.1 API 설계 이슈: FTGO 모바일 클라이언트

  • 모바일 앱이 여러 서비스를 호출해서 결과를 조합하는 API 조합기 역할을 맡을 경우 생기는 문제점
    • 클라이언트가 요청을 여러 번 전송하기 때문에 UX가 나빠진다
    • 캡슐화가 되지 않아 프론트엔드 개발자가 백엔드와 맞물려 코드를 변경해야 한다
    • 클라이언트에 비친화적인 IPC를 사용 중인 클라이언트도 있다

**8.1.2 API 설계 이슈: 다른 종류의 클라이언트

웹 애플리케이션

웹 애플리케이션은 웹에 비친화적인 프로토콜에도 접근 가능하다. 웹은 대개 같은 조직에 있는 백엔드 서비스 개발팀과 긴밀한 협업하에 작업을 진행하므로 백엔드 서비스가 변경될 때마다 웹 애플리케이션도 쉽게 수정할 수 있다.

따라서 웹 애플리케이션이 직접 백엔드 서비스에 접근하는 것이 얼마든지 가능하다.

브라우저 기반의 자바스크립트 애플리케이션

API 변경 시 업데이트 하기는 쉽지만 모바일 앱처럼 인터넷을 통해 서비스에 접근하기 때문에 네트워크 지연문제는 별반 다를 바 없다. 일반 모바일 앱보다 더 정교한 브라우저 기반의 UI(특히 데스크톱 UI)는 더 많은 서비스를 조합해야 할 필요가 있다. 따라서 인터넷으로 접속한 소비자, 음식점 등의 애플리케이션은 서비스 API를 효휼적으로 조합하기 어려울 것 이다.

서드파티 애플리케이션

장기간 하위 호환성을 관리할 책임을 백엔드 서비스 개발자에게 지우기란 현실적으로 어렵다. 따라서 서드파티 개발자에게 직접 서비스를 표출하는 대신 별도 팀에서 개발한 퍼블릭 API를 따로 가져가는 것이 좋다. 이런 퍼블릭API는 API 게이트웨이라는 아키텍쳐 컴포넌트로 구현한다.

8.2 API 게이트웨이 패턴

**8.2.1 API 게이트웨이 패턴 개요

  • API 게이트 웨이 패턴은 앞서 말한 API조합을 게이트웨이단에서 하자는 패턴임.
  • API 게이트웨이는 요청 라우팅, API 조합, 프로토콜 변환을 관장한다.
  • API 게이트 웨이는 클라이언트마다 적합한 API를 제공한다.
  • 엣지 기능 구현
  • 엣지 기능 구현
    • 인증: 요청한 클라이언트의 신원을 확인
    • 인가: 특정 작업을 수행하도록 허가받은 클라이언트인지 확인
    • 사용량 제한: 특정(또는 전체) 클라이언트의 초당 요청개수를 제한
    • 캐싱: 서비스 요청 횟수를 줄이고자 응답을 캐시
    • 지표수집: 과금 분석용 API 사용 지표 수집
    • 요청 로깅: 요청을 기록
    • 이런 엣지 기능을 구현한 곳은 3군데일수 있음.
      • 백엔드 서비스 : 이렇게 할수는 있는데, 요청이 서비스에 도달하기전에 하는게 좋습니다.
      • API 게이트 웨이 상류 : 요청이 API 게이트웨이에 들어오기전에 처리하는 방식.
      • 전용 엣지 서비스 : (장 : 관심사 분리 효과 / 단 : 홉 카운트가 늘어남. 네트워크 비용 추가.)

API게이트웨이 아키텍처

  • 2가지 방식 구현
    • 좀 당연한 말임.
    • API 조합이 필요 없는 경우 : API 작업을 해당 서비스의 API로 요청을 보냄
    • 필요 한 경우 :여러 서비스를 호출한 결과를 조합하는 식으로 구현

API 게이트웨이 소유권 모델

API 게이트웨이 전담팀 따로 신설 필요. 모바일 앱 개발자가 API 필요하면 요청후 마냥 기다려야하나? msa 아키텍처 사상과 배치됨.

넷플릭스 권장 :

API 가 효출된 모듈은 해당 클라이언트팀의 소유 API 게이트웨이팀은 공통모듈 개발 및 게이트웨이 운영 이슈에 집중

프런트엔드 패턴을 위한 백엔드

  • 위 방식의 문제 : 책임 소재가 불분명해지는 이슈가 있음.
  • 새로운 방식 : 각 클라이언트 마다 API 게이트웨이를 따로두는 BFF 패턴을 적용하자!

**8.2.2 API 게이트웨이의 장단점

  • 장점
    • API조합을 클라이언트에서 하는 패턴에 비해 네트워크 딜레이가 적고, 클라이언트 패턴에 비해 유지보수가 좀더 자유로움.
    • 애플리케이션의 내부 구조를 캡슐화.
    • 클라이언트 애플리케이션 간 왕복 횟수가 줄어들음
    • 클라이언트 코드 역시 단순해짐.
  • 단점

    • 게이트웨이에 비즈니스 로직이 포함된다는게 단일 책임원칙 위반일 수도.
    • 고가용 컴포넌트 추가 부담
    • gw가 병목지점될 우려. 프로세스가 가벼워야한다. 안그러면 개발자가 길게 줄을 서서 기다리게된다.
  • 이런 단점에도 BFF 패턴을 이용하면 팀별로 독립적으로 개발/배포 가능 하니까 이것을 쓰는게 합리적.

**8.2.3 API 게이트웨이 사례: 넷플릭스

  • 넷플릭스 지블의 사례
  • 처음엔 자사 스트리밍 API 를 만능으로 개발하려고함. -> 실패. 기기별 API가 따로 구현된 gw 를 사용함. api 구현 코드는 클라이언트 기기 팀이 소유/개발.

  • gw 첫버전에서는 라우팅과 조합을 수행하는 그루비 스크립트로 API 구현. 각 서비스팀에서 자바클라이언트 라이브리러리를 만듦. 이걸 스크립트를 짜서 호출. 6~7개의 서비스가 관여함. 무거움.

  • BFF 패턴으로 이전중. Node.js 모듈로 개발. 스크립트가 서비스를 직접 호출하는게 아니라 팔코(second api gw) 를 활용.

**8.2.4 API 게이트웨이 설계 이슈

  • 성능과 확장성
  • 리액티브 프로그래밍 추상체를 이용하여 관리가능한 코드 작성
  • 부분 실패 처리
  • 애플리에킹션 아키텍처에서 선량한 시민 되기.

성능과 확장성

  • API 게이트웨이 에 동기IO를 사용할 것인가, 비동기IO를 사용할 것인가
    • 동기 IO 이슈 : 다소 무거운 쓰레드 사용으로 스레드 개수에 제약을 받음. 동시 접속 가능 개수도 제한적임.
    • 비동기 콜백 기반의 프러그래밍은 : 오버헤드가 적음. 단 코드를 작성, 이해 , 디버깅하는 어려움.
      • 이벤트 루프 스레드가 블로킹되지 않도록 조치가 필요함.

리액티브 프로그래밍 추상체를 이용하여 관리가능한 코드 작성

  • 동시처리는 콜백방식보다는 리액티브한 선언형 스타일을 써라
    • 자바8 : CompletableFuture
    • 리액터 프로젝트 Mono
    • RxJava 의 옵저버블.
    • 스칼라 Future

부분 실패 처리

  • 게이트웨이는 확장은 물론 안정적으로 작동해야한다.
    • 여러 게이트 웨이 인스턴스를 두자.
    • 실패한 서비스로 들어온 요청이 스레드처럼 한정된 리소스를 계속 붙들고 있게 하지는 말자.
      • 회로 차단기 패턴(서킷브레이커)는 이 문제를 해결할 수 있는 좋은방법임.

애플리에킹션 아키텍처에서 선량한 시민 되기.

  • 서비스 디스커버리 (3장) + 관측성 패턴 (11장)을 활용하면 개발자가 애플리케이션 동작 상태를 모니터링하고 문제를 진단하는 데 도움이 됨.
    • 서비스 디스커버리 (3장)(자신이 호출할 서비스 인스턴스의 네트워크 위치 파악에 도움)

8.3 API 게이트웨이 구현

  • 요청 라우팅 : 요청을 HTTP메소드, 경로에 따라 서비스로 라우팅한다. 게이트웨이는 HTTP 요청메서드를 이용하여 적절한 CQRS쿼리 서비스로 라우팅 한다. 커맨드와 쿼리는 각각 별도의 서비스로 처리한다.
  • API 조합: 조합 패턴에 따라 REST 끝점을 구현하고, 요청 핸들러는 여러 서비스를 호출한 결과를 조합한다.
  • 엣지 기능: 가장 대표적인 엣지 기능은 인증이다.
  • 프로토콜 변환: 서비스가 사용하는 클라이언트에 친화적인 프로토콜과 비친화적인 프로토콜을 상호 변환한다.
  • 애플리케이션 아키첵처의 선량한 시민이 된다.

  • API 게이트웨이를 구현하는 다음 두가지 방법.

    • 기성 API 게이트웨이 제품/서비스 활용: 개발 노력은 거의 안들지만 유연성은 제일 떨어진다. 가령 기성 API 게이트웨이 제품은 대체로 API 조합을 지원하지 않는다.
    • API 게이트웨이 프레임워크 또는 웹 프레임워크를 기반으로 API 게이트웨이를 직접 개발: 가장 유연한 접근 방식이지만, 적잖은 개발 노력이 투입되어야한다

**8.3.1 기성 API 게이트웨이 제품/서비스 활용

  • 기성 제품들 aws elb, alb(클라우드 기반), kong(직접 설치 가능)
  • API조합빼고 다 지원.
  • 그런데 결국 API 조합이 안되는게 이슈.

**8.3.2 API 게이트웨이 자체 개발

  • 다음 두가지 이슈를 검토해야한다

    • 코딩 복잡도를 최소화할수있는 라우팅 규칙 정의 메커니즘
    • HTTP헤더 처리 등 HTTP 프록시 로직을 정확히 구현

넷플릭스 주울

  • 일부 아쉬운 점. 경로 기반 라우팅만 지원됨.

스프링 클라우드 게이트웨이

  • 스프링 클라우드 게이트 웨이가 자체 개발시 유리하게 쓸만함
  • 스프링 5, 부트2, 웹플럭스 등의 프레임워크를 토대로한 API 게이트웨이 프레임워크이다. 리액터 프로젝트는 Mono 추상체를 제공하는 NIO기반의 JVM 리액티브 프레임워크이다. 스프링 클라우드 게이트웨이는 단순하지만 범용적인 수단을 제공한다.
    • 요청을 백엔드 서비스로 보낸다
    • API를 조합하는 요청 핸들러 역할을 한다
    • 인증 등의 엣지 기능을 처리한다.
  • API 게이트웨이는 다음 패키지들로 구성된다.
    • ApiGatewayMain 패키지: API 게이트웨이의 메인 프로그램
    • 하나 이상의 API 패키지: API 끝점이 구현된 API 패키지. 가령 Order 패키지에는 주문 관련 API 끝점이 구현되어 있다.
    • 프록시 패키지: 서비스를 호출하기 위해 API 패키지가 사용하는 프록시 클래스로 구성
    • orderConfiguration은 주문관련 요청을 라우팅하는 스프링 빈이 정의된 클래스이다. 라우팅 규칙은 HTTP 메서드, 헤더, 경로를 조합하여 정한다. API 요청을 백엔드 서비스 URL에 매핑하는 규칙은 orderProxyRouting빈에 정의되어있다. 예를 들어 경로가 /order로 시작하는 요청은 OrderService로 보낸다.

__8.3.3 API 게이트웨이 구현: GraphQL

  • 클라이언트마다 필요한 데이터가 다를수도 있다. 쿼리매개변수로 구분짓거나 BFF패턴을 적용해서 여러 앤드포인트를 정의할수 있지만, 수많은 API 앤드포인트를 전부 이런식으로 처리하기엔 버겁다.

  • API 게이트웨이에서 별의 별 클라이언트를 지원하는 REST API를 구현하는것은 시간낭비이다.

  • 외부 API 설계 이슈 2번째 부분을 해결함.

    • 개인적 의견으로 단점이 클라이언트단에 비즈니스 로직이 전파되는 것 아닌가? 이런 걱정인데, 조합기를 제공한다는 관점에서 클라이언트 단에서 API를 조합하는 것보다 훨씬 안전한가? 라는 생각을 하게 됨.

graphQl 스키마 정의

GraphQL은 스키마 중심적이다. 서버 쪽 데이터 모델과 작업(클라이언트가 수행가능한 쿼리)의 구조를 정의한 타입들로 구성된다. GraphQL에는 여러 종류의 타입이 있다. 주로 많이 쓰는 객체형과 자바 이넘과 비슷한 두가지 타입만 사용한다.

GraphQL 쿼리 실행

가장 큰 매력은 클라이언트가 반환 데이터를 쿼리언어로 자유롭게 제어할 수 있다는 점이다. 클라이언트는 쿼리 문서가 담긴 요청을 서버에 전송하여 쿼리를 실행한다. 다음과 같이 소비자가 firstName/lastName를 조회하는 간단한 쿼리는 쿼리명, 인수 값, 반환될 결과 객체 필드를 쿼리 문서에 명시한다.

스키마를 데이터에 연결

애플리케이션에서 GraphQL 서버가 데이터를 소유한 서비스 API를 하나하나 호출해야 할 것이다. 스키마에 정의된 객체형 필드에 리졸버 함수를 붙이면 GraphQL 스키마를 데이터 소스와 연관지을 수 있다.

배치/캐싱으로 로딩 최적화

GraphQL 쿼리실행시 각각의 리졸버는 독립적으로 실행되므로 서비스 왕복횟수가 길어지면 성능이 떨어질 위험이 있다. 주문이 N개 있으면 소비자 서비스에 한번, 주문 이력서비스에 한번, 음식점 서비스에 N번 호출하게 될 것이다.(jpa n+1 해결 방식과 유사)

아폴로 GraphQL 서버와 익스프레스를 연계

pass

GraphQL 클라이언트 작성

클라이언트가 원하는 데이터를 조회하는 다양한 쿼리를 FtgoGraphQLClient 클래스에 정의할 수 있다.

8.4 마치며

  • 애플리케이션 외부 클라이언트는 대부분 API 게이트웨이를 통해 서비스에 접근하며, API 게이트웨이는 클라이언트별 사용자 정의 API를 제공한다. 요청 라우팅, API 조합, 프로토콜 변환, 인증같은 엣지 기능도 API 게이트웨이가 담당한다.
  • 애플리케이션 하나의 API 게이트웨이를 두는 것 외에, 클라이언트를 유형마다 API 게이트웨이를 이루는 정의하는 BFF 패턴을 적용할 수 있습니다. BFF 패턴은 클라이언트 팀이 API 게이트웨이를 자체적으로 개발, 배포, 유지하는 데 있어서 자율성을 크게 향상시키는 장점이 있습니다.
  • API 게이트웨이는 다양한 기술로 구현할 수 있습니다. 기성 API 게이트웨이 제품을 써도 되고, 여러분이 직접 프레임워크를 이용하여 API 게이트웨이를 개발할 수도 있습니다.
  • 스프링 클라우드 게이트웨이는 API 게이트웨이 개발을 간단하게 돕는 훌륭한 프레임워크이다. 스프링 클라우드 게이트웨이는 메서드, 경로 등 요청 속성에 따라 요청을 직접 백엔드 서비스나 사용자 정의 핸들러 메서드로 보낸다. 확장 가능하고 리액티브한 스프링 프레임워크5와 리액터 프로젝트 프레임워크에 기반한다. 사용자 정의 요청 핸들러를 리액티브 스타일로 직접 개발 하는것도 얼마든지 가능하다.
  • GraphQL은 그래프 기반의 쿼리언어를 제공하는 프레임워크이다. 스프링 클라우드 게이트웨이와 더불어 API 게이트웨이 개발의 쌍벽을 이루는 기술이다. 그래프 지향 스키마를 작성하여 서버쪽 데이터 모델과 이 모델이 지원하는 퀴리를 기술한 후, 데이터를 조회하는 리졸버를 작성해서 스키마를 서비스에 매핑한다. GraphQL에 기반한 클라이언트는 서버가 정확히 어떤 데이터를 반환해야 하는지 기술된 스키마를 대상으로 쿼리한다. GraphQL 기반 API 게이트웨이는 다양한 클라이언트를 지원한다.

참고용어

  • BFF(Backend For Frontend)
    • 이것은 API 조합을 Standalone한 서비스로 만들어 제공하는 것으로 해석했다.

참고자료

  • https://velog.io/@daehoon12/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4-%ED%8C%A8%ED%84%B4-8.-%EC%99%B8%EB%B6%80-API-%ED%8C%A8%ED%84%B4#%EC%95%84%ED%8F%B4%EB%A1%9C-graphql-%EC%84%9C%EB%B2%84%EC%99%80-%EC%9D%B5%EC%8A%A4%ED%94%84%EB%A0%88%EC%8A%A4%EB%A5%BC-%EC%97%B0%EA%B3%84
  • https://velog.io/@bonjugi/%EC%99%B8%EB%B6%80-API-%ED%8C%A8%ED%84%B4
  • https://freeend.tistory.com/114
This post is licensed under CC BY 4.0 by the author.