레이블이 GraphQL인 게시물을 표시합니다. 모든 게시물 표시
레이블이 GraphQL인 게시물을 표시합니다. 모든 게시물 표시

8/05/2022

Restful vs gRPC vs GraphQL

얼마전 프로젝트 진행 시, RESTful의 엔드포인트에 대해서 문제가 생겼었다. 구현상에 문제는 없지만 Addressability를 보장해야 하는 DX관점에서의 문제였다.

지금이야 REST로 API를 만들어서 제공하지만, 상황에 따라 gRPC 혹은 GraphQL을 사용해야 할 경우도 생기기에 각 표준에 대해서 정리하고자 한다.

통신 방식의 비교


이미지 출처: https://www.sensedia.com/post/apis-rest-graphql-or-grpc-who-wins-this-game


기술별 특성 비교


이미지 출처: https://www.sensedia.com/post/apis-rest-graphql-or-grpc-who-wins-this-game

REST

REST는 현재 가장 많이 사용되는 API 아키텍처이다. HTTP Method를 사용하여 리소스를 제공한다.

REST에서 사용되는 HTTP Method

  • POST: 새 리소스를 생성한다.
  • PUT: 리소스가 존재하는 경우 업데이트하거나 리소스가 없으면 생성한다.
  • DELETE: 리소스를 삭제한다.
  • PATCH: 기존 리소스를 부분적으로 업데이트 한다.
  • GET: 리소스를 쿼리한다.

REST의 장점은 아래와 같다.

  • 성능 - 빠른 반복 및 HTTP 표준 표현이 필요한 시스템에 가장 적합하다.
  • 확장성 - 많은 수의 구성 요소와 구성 요소 간의 상호 작용을 지원한다.
  • 단순성 - REST에는 아키텍처를 단순화하고 분리하는 균일한 인터페이스가 존재한다.

이미 오래전부터 사용되었기에 대부분의 개발자가 익숙하다는 장점이 있다. REST는 HTTP 프로토콜 디자인과 매우 밀접하게 브라우저 및 기타 HTTP 클라이언트는 기본적으로 REST API를 이해하고 있다.

하지만, REST는 만병 통치약이 아니고 유일한 API 아키텍처가 아니다. REST의 경우 리소스가 복잡할 수록 여러 API를 사용하거나 응답이 무거울 수 있다. 따라서 GraphQL로 대체되거나 gRPC를 사용하는 경우가 생기기도 한다. 그리고 REST에 대한 표준을 만들어야 한다. API를 만들때에 가장 중요한 것은 API를 사용하는 청중의 입장에서 설계하고 제공해야 한다. API 엔드포인트로 리소스를 제공하기에 하나의 API만 보면 안되고, 전체의 API의 엔드포인트를 보면서 문맥 및 의미하는 바가 잘 표현되었는지 확인해야 한다. 이 작업은 매우 어려운 작업이기에 매끄럽게 만들기가 어렵다. 이번에 발생한 것도 이 부분에서 문제가 발생한 것이다.

다른 API를 아키텍처를 사용할 이유가 없다면 REST가 가장 적합한 옵션이다. GraphQL, gRPC는 고유한 요구 사항이 있는 상황에 적합할 수 있다. 그리고 REST에 비해 학습 곡선이 가파르다.

범용적인 API가 필요할 경우 REST를 사용하면 좋다.

gRPC

gRPC는 Google에서 설계, 개발한 Google Remote Procedure Call이다. 데이터를 가볍고 빠르게 요청하기 위해 고려되었다. gPRC는 일반적인 원격 프로시저 호출보다 진화된 형태이다. gRPC를 사용하면 클라이언트는 원격 시스템이 마치 로컬인 것처럼 직접 메소드를 호출할 수 있다. gRPC는 프로토콜 버퍼(Protobufs)를 사용하여 데이터 전송을 위해 텍스트 기반의 JSON, XML이 아닌 바이너리로 직렬화된 데이터로 인터페이스를 정의한다. 또한 HTTP/1보다 더 안정적이고 빠른 HTTP/2를 사용하게 된다.

REST는 표준화된 용어를 통해 상호 작용을 정리하고 GraphQL은 생성된 스키마에 대해 요청을 실행하며 필요한 것을 가져오게 된다.

gRPC는 서버와 클라이언트 간의 관계에 의해 동작이 정의된다. 대부분의 권한은 클라이언트측에 의존하는 반면 처리 및 계산은 리소스를 제공하는 원격 서버에서 진행된다. 이점은 아래와 같다.

  • 가벼우며 클라이언트측의 리소스가 거의 필요하지 않다. 따라서 전력이 매우 부족한 상황에서 편리하게 이용할 수 있다.
  • 효율적이다. gRPC는 통신을 직렬화하는데 중점을 둔 구조화된 데이터 직렬화 방법인 protobufs를 사용한다.
  • 오픈소스 이며 자유롭게 사용, 수정 또는 분기할 수 있다.

gRPC는 정해진 양의 데이터 또는 클라이언트가 저전력이거나 리소를 보존하려는 시스템에 적합하다. 가장 좋은 예는 음성 컨트롤러, 스마트 조명 스위치, 화재 경보기, 잠금 장치 및 카메라와 같이 널리 사용되는 IoT 장치에 적용하면 장점을 최대한 이용할 수 있다.

GraphQL

GraphQL은 정확한 요청에 초점을 맞추고 필요한 것을 정확히 전달하기 위한 방식이다. GraphQL을 다른 API와 차별화하는 것은 클라이언트 중심의 접근 방식이다. 주요 이점은 아래와 같다.

  • 적응성 - 클라이언트가 원하는 데이터, 원하는 방식 및 형식을 결정한다.
  • 효율성 - 과도하게 가져오지 않고 클라이언트가 요청한 것을 정확하게 전달한다.
  • 유연성 - GraphQL은 크로스 플랫폼이며 12개 이상의 언어(Java, Perl, Python.,)을 지원한다.

GraphQL 사용 사례중 가장 많이 알려진 것은 Github이다. 확장성과 유연성 두 가지 주요 이유로 2016년에 전환했다. REST는 원하는 데이터를 얻기 위해 여러 요청을 해야 하고 각 요청에서 데이터를 과도하게 가져와야 하는 경우가 많다. Github의 급속한 성장과 수천만 명의 사용자를 보면 이것이 얼마나 부담되는 일인지 알 수 있다. GraphQL은 클라이언트가 특정 용도를 위해 특정 형식의 데이터를 요청할 수 있다는 점에 초점을 뒀기 때문에 Github의 Needs를 정확히 제공했다.

끝으로

각각의 기술은 고유한 장점과 단점이 존재한다. 목표가 무엇인지에 따라 어떤 것을 선택할지 결정되게 된다. 각 기술을 이해하고 현재 프로젝트에 가장 적합한 것이 무엇인지 판단하고 선택했으면 좋겠다.

References

  • https://medium.com/devops-dudes/graphql-vs-rest-vs-grpc-411a0a60d18d
  • https://konghq.com/blog/rest-vs-grpc-vs-graphql
  • https://www.sensedia.com/post/apis-rest-graphql-or-grpc-who-wins-this-game


12/12/2018

GraphQL 채택 후 Netflix가 배운 것들

Netflix에서는 콘텐츠 인기도 파악과 같은 다양한 데이터 및 집계 데이터를 활용하여 관련성이 높은 광고를 제공한다. Netflix의 목표는 모든 외부 채널에 대해 광고가 사용자와 잘 어우러지게 만드는 것이다. Netflix는 보다 효율적으로 하기 위해 끊임없는 실험을 하고 있다.


Monet의 React UI는 Apache Tomcat에 의해 구동되고 REST API에 Access를 했다. 시간이 지나고 어플리케이션이 발전함에 따라서 사용 사례가 복잡해지기 시작했다. Simple page는 다양한 소스의 데이터를 가져와야 한다. 이 데이터를 클라이언트에서 효과적으로 로드하기 위해서 Backend 데이터를 비정규화 하는 노력을 시도했다. 그 이유는 모든 페이지가 모든 데이터를 필요로 하지 않기 때문에 유지하기가 어려워지기 때문이다. Network 병목 현상에 발생했다.

Backend에서 클라이언트에게 보내는 field의 수를 줄이는 방법은 모든 페이지에 대해서 endpoint를 만드는 것이었지만, 효율적이지 못했다. 대신 GraphQL을 Middleware로 선택했다. 이미 개발되어 사용중이던 Falcor도 훌륭한 솔루션이었지만 GraphQL의 Eco시스템을 이용하기 위해 Falcor가 아닌 GraphQL을 사용했다. 데이터 구조가 점차 그래프 지향적으로 변경됨에 따라 Network 병목도 해결했고, 기능을 더 빨리 추가 할 수 있게 되었다.


장점

NodeJS에서 GraphQL을 약 6개월 정도 사용하였고 개발 속도 및 페이지 로드 성능을 크게 향상시키는 것을 입증했다.

Redistributing load and payload optimization

GraphQL을 Middleware로 추가 할 때 GraphQL 서버는 Client가 직접 호출했을 때와 같이 동일한 서비스 및 REST API를 호출해야 했다. 대부분의 데이터가 동일한 DC내의 서버사이로 전달 되기에 이러한 Server to Server 호출은 대기 시간이 낮고 대역폭이 높기 때문에 브라우저에서 직접 네트워크를 호출하는 것에 비해서 약 8배의 성능이 향상되었다. GraphQL 서버에서 Client Browser의 데이터 전송 구간은 여전히 느린 속도지만, 단일 네트워크 호출로 축소시켰다. GraphQL을 사용하면 Client가 필요한 데이터만 취할 수 있기 때문에 REST API 에 비해 상당히 작은 Payload를 가져온다. Netflix의 Application에서 이전에는 10MB의 데이터를 가져온 페이지는 약 200KB를 받는다. Page load는 데이터가 제한된 모바일 네트워크에서 훨씬 빨라졌고 훨씬 적은 메모리를 사용한다.

Reusable abstractions

개발자는 일반적으로 단일 목적으로 하는 코딩보다 재사용이 가능한 추상 방식을 사용하기를 원한다. GraphQL을 사용하면 각 데이터를 한번 정의하고 시스템의 다른 데이터와의 연관성을 정의한다.

아래의 예제를 보면, GraphQL의 Entitiy를 Catalog, 주석과 같이 한번만 정의한다. 이 정의에서 여러 페이지에 대한 View를 정할 수 있다. Client App의 한 페이지는 다른 Client Page에 광고가 속한 Catalog를 모든 댓글과 함께 보기를 원한다고 하면 동일한 그래프 모델을 사용하면 Backend 서버의 코드를 변경하지 않고도 두가지 View를 수용할 수 있게 된다.


Chaining Type Systems

GraphQL에서 Entitiy를 정의하고 나면 자동 코드 Generater 도구를 사용하여 Client 어플리케이션의 TypeScript 유형을 생성한다. 이러한 유형과 Query는 서버 Schema에 대해서도 유효성이 검사 되기에 서버에서 발생한 모든 변경 사항은 데이터를 사용하는 Client가 알게 된다. GraphQL과 함께 여러 서비스를 묶고 이러한 검사를 Build Process에 연결하면 잘못된 코드를 배포하기 전에 더 많은 문제를 파악할 수 있다.


개발 단순화

Client 어플리케이션을 만들 때 공통적으로 고려해야 하는 사항은 UI/UX 이지만, 개발자 인터페이스와 개발자 경험은 유지 관리 가능한 어플리케이션을 빌드하는 것만큼 중요하다. GraphQL을 사용하기 전에는 새로운 React 컨테이너 구성 요소를 작성하기 위해 복잡한 로직을 관리하여 필요 데이터에 대해 요청을 해야했다. 개발자는 하나의 데이터가 다른 데이터와 어떻게 관련되는지, 데이터를 Cache하는 방법, 병렬 또는 순차적으로 호출할 지 여부, Redux에서 데이터를 저장할 위치 등을 고려해야 한다. GraphQL Query Mapper를 사용하게 되면 각 React 구성 요소는 필요한 데이터를 설명하기만 하면 되고 Wrapper는 이러한 것들을 처리하게 된다.

다른 장점

몇 가지 다른 이점이 있다. 첫째 GraphQL Query의 Resolver가 실패하면 성공한 Resolver는 가능한 많은 페이지를 Rendering하기 위해 Client에 데이터를 반환하게 된다. 둘째, Backend 데이터 모델은 CRUD 인터페이스를 제공하기 때문에 매우 간단하다. 마지막으로 GraphQL Query가 테스트를 위해 stub으로 자동 변환될 수 있고 React 구성 요소와 분리되어 Resolver를 테스트 할 수 있기에 구성 요소를 테스트하는 것이 더 쉬워진다.

진화

GraphQL로 마이그레이션은 단순한 경험이었고, 네트워크 요구 사항을 정의하고 데이터를 변환하기 위해 구축한 대부분의 인프라는 코드 변경없이 React 어플리케이션에서 NodeJS 서버로 쉽게 이전 할 수 있었다. 하지만 몇가지 장애물이 존재했다.

GraphQL의 Resolver는 다른 Resolver와 관련없이 독자적으로 실행되기 때문에 동일하거나 유사한 데이터에 대해 중복적으로 네트워크 요청을 하는 것으로 나타났다. 모든 Resolver가 끝날 때 까지 네트워크 응답을 메모리에 저장하는 간단한 Caching Layer를 Wrapping하여 복제를 해결했다. Caching Layer를 사용하여 단일 서비스에 대한 여러 요청을 모든 데이터 대한 대량 요청으로 할 수 있게 되었다. Resolver는 Fetch 프로세스를 최적하는 방법에 대해 고민하지 않고도 필요한 모든 데이터를 요청 할 수 있다.


GraphQL은 다른 서비스에 대한 네트워크 호출을 자동으로 조정하여 복잡성을 숨긴다. 디버그 flag가 활성화되면 디버깅을 쉽게 하기 위해 GraphQL Response Payload에 로그가 나타난다. Netflix는 Debug Flag를 활용하여 브라우저의 네트워크 탭을 통한 자연스러운 디버깅 방법을 고안했다.

Netflix의 경우 GraphQL 사용의 초기 단계에 있지만, 현재까지 진행한 사항으로는 긍정적인 경험이었다고 한다. Netflix가 GraphQL을 사용하는 핵심 목표는 시스템이 점차 정교해짐에 따라 개발 속도를 높이는데 도움이 될 것으로 보고 있고 복잡한 데이터 구조로 어려움을 겪지 않고 Graph Data Model에 투자하여 시간이 지남에 따라 팀의 생산성이 향상되는 것이라고 한다.

지난 기간 동안, 만들어 놓은 Graph Model이 강력하기에 일부 기능을 구현하기 위해 Graph를 변경하는 일은 없었다고 했고, 확실히 더 생산적이었다고 한다. 그리고 Schema stitching과 같은 개념을 사용하여 다른 서비스와의 통합을 수월하게 하고 개발 시간을 절약되길 기대한다고 한다.

현재 진행중인 프로젝트에서도 GraphQL에 대해서 테스트중이고, Netflix와 같은 효과가 생기길 기대한다.

References: https://medium.com/netflix-techblog/our-learnings-from-adopting-graphql-f099de39ae5f

11/07/2018

GraphQL로 BFF 대체하기

 

위의 그림에서 BFF의 목적은 Orchestration, Business Logic을 공유하고 Backend 서비스가 제공하는 것보다 UI에 친화적인 모델을 제공하는 것입니다. 그래서 각 클라이언트별로 BFF가 존재하게 됩니다. Netflix는 Client Adapter라는 이름으로 SoundCloud는 BFF라는 이름으로 UI에 친화적인 Backend 서비스를 제공하고 있는데, 이런 BFF에도 문제점이 존재합니다.

  • 업무 조직간 교차 관리가 어렵습니다.
  • Traffic에 대한 용량 사이징을 예측하기 어렵습니다.
  • 단일 실패 지점이 될 가능성이 존재합니다.
  • 추가적인 아키텍처 복잡성이 발생합니다.

다른 접근 방법은 클라이언트가 서비스를 제공하거나 Backend와 직접 상호 작용을 하는 것입니다.

위의 그림처럼 BFF를 걷어내면 심플해보이는 장점이 있지만, 여전히 BFF와 공통된 문제점이 존재합니다. Application Server는 PC, Mobile의 데이터 요구를 구별해야 하며 각 클라이언트별로 API가 달라질 가능성이 존재합니다.

GraphQL을 써보자

이러한 상호 작용을 깔끔하게 하고 최종 사용자에게 더 나은 서비스를 제공하기 위해서 GraphQL을 사용해 볼 계획을 가지고 있습니다. GraphQL은 API Graph에서 구성 요소를 관리하는 복잡성에 대처할 수 있도록 Facebook에서 개발했습니다.

GraphQL을 사용하면 UI가 데이터와 선언적으로 상호 작용할 수 있으며 서버에서 UI를 분리 할 수 있습니다. UI에서 필요한 데이터를 지정하기에 UI에 친화적인 API를 구축하는 것에 대해 고민할 필요가 없습니다. 또한 GraphQL은 일반적인 AJAX 요청보다 더 쉽게 최적화되기에 Request 개수가 줄어들게 됩니다.


앞으로는 GraphQL이 주류가 될 것입니다. Amazon의 AppSync 혹은 Graphcool 같은 서비스가 주류가 되는데에 일조 할 것으로 보여집니다.


7/08/2018

GraphQL과 RESTful

 


GraphQL(Graph Query Language)은 Server API를 만들기 위해 Facebook에서 만든 Query Language입니다.

Query Language는 질의문(Query)과 컴퓨터언어(Language)의 조합입니다. 기존에 RESTful이라는 개념이 존재하였고, 그동안 잘 사용하고 있었는데 Facebook은 왜 이런 개념을 만든 것일까요?

https://graphql.org/blog/graphql-a-query-language/에 의하면 아래와 같은 문제점이 존재했다고 합니다.

  • 다양한 기기에서 필요한 정보들을 REST로 일일히 구현하기 힘듬
  • 각 기기마다 UI/UX가 다르기에 Server에서 일일히 대응하기가 어려움

그래서 Facebook은 서버가 데이터를 노출하는 방법을 정의한 기술 표준이 필요했고 내부적으로 만들어서 사용하다가 2015년도에 오픈소스로 공개하게 되었습니다.

RESTful과 GraphQL의 차이점은 무엇일까요?

RESTful과 GraphQL의 차이점

API Endpoint

REST의 핵심 아이디어는 Resource입니다.각 Resource는 URL로 식별되며 해당 URL 에 요청을 보내 정보를 얻습니다. REST는 Resource의 유형 및 모양과 리소스를 가져오는 방법이 결합된 방식을 제공한다는 점입니다.


GET / books / : id 
GET / authors / : id 
GET / books / : id / comments 
POST / books / : id / comments

GraphQL의 경우는 위에서 언급한 두 개념이 완전히 분리되어 있습니다. 전체 API를 위해서 단 하나의 Endpoint만 사용합니다. github의 경우 v3 API와 v4의 API의 기술 표준이 다릅니다. v3의 경우는 v3 루트 element하위에 각 Resource들의 endpoint가 존재하지만, v4의 경우 루트 element만 존재합니다. 이 의미는 사용측에서 Query 스키마 유형을 만들어야 합니다.


type Query {
  book(id: ID!): Book
  author(id: ID!): Author
}
type Mutation {
  addComment(input: AddCommentInput): Comment
}
type Book { ... }
type Author { ... }
type Comment { ... }
input AddCommentInput { ... }

API Response

RESTful의 경우 각 API마다 spec이 존재하며, 정의해놓은 format대로 각 Resource의 정보를 Response합니다.

GraphQL의 경우 사용하는 측에서 Response 구조를 원하는 방식으로 변경할 수 있습니다.

이 둘간의 차이점을 보여주는 그림입니다.


GraphQL을 사용하게되면 아래의 장점을 지니게 됩니다.

  • HTTP 요청 횟수를 줄일 수 있기 때문에, Network Latency가 감소됩니다.
  • HTTP 응답 Size가 줄게 됩니다.

결론

그동안 RESTful은 N+1 쿼리의 제약에서 자유롭지 못했습니다. 특정 사용자가 작성한 글의 모든 내용을 보고 싶다고 하면 모든 글의 목록을 가져오고 내용은 목록 리스트를 루프를 돌면서 fetch를 해야 했었습니다. 그리고 필요 정보만 가져오고 싶어도 API에서 제공해주는 모든 정보를 받은 후에 필터 처리를 해야 했었습니다. 이런 점은 성능에도 영향을 주게 되었고요.

물론, RESTful의 단점을 개선한 GraphQL도 장점만 존재하는 것은 아닙니다. 높은 학습 곡선이 존재하고 적절한 상황에서 사용해야 합니다.