지나공 : 지식을 나누는 공간

GraphQL 간단한 소개, REST API와의 비교 본문

Tech/GraphQL

GraphQL 간단한 소개, REST API와의 비교

해리리_ 2022. 5. 13. 11:51

요즘 신입사원 과제 프로젝트 덕분에 안 써본 다양한 기술을 접하고 있다. 지난 번엔 Reactive Streams에 대해 간단히 적었는데, 지금은 GraphQL을 다룬다.ㅋㅋㅋ 아직 reactive 에서 쓰다 만 임시저장 글이 많은데 graphQL 한번 올리고 그 담에 이어서 또 reactive 정리를 이어서 할 것 같다.

 

이번 포스팅은 Apollo 블로그에서 REST와 GraphQL을 비교한 내용을 번역하면서 설명을 추가했다.

https://www.apollographql.com/blog/graphql/basics/graphql-vs-rest/

 

로드맵 펼치기

더보기
야생형 개발자로서... 일단 더 많이 접한 REST랑 어떻게 다른지를 보는 게 더 이해가 빠를 것 같다.

REST와의 비교 : https://www.apollographql.com/blog/graphql/basics/graphql-vs-rest/
 

GraphQL vs. REST

Edited by Ceora Ford Often, GraphQL is presented as a revolutionary new way to think about APIs. Instead of working with rigid server-defined endpoints, you can send queries to get exactly the data you’re looking for in one request. And it’s true — G

www.apollographql.com

 

GraphQL 소개 from docs : https://graphql.org/learn/
 

Introduction to GraphQL | GraphQL

Introduction to GraphQL Learn about GraphQL, how it works, and how to use it. Looking for documentation on how to build a GraphQL service? There are libraries to help you implement GraphQL in many different languages. For an in-depth learning experience wi

graphql.org

 

클라이언트와 서버에서 GraphQL을 활용하는 튜토리얼 from docs : 

https://www.howtographql.com/

 

How to GraphQL - The Fullstack Tutorial for GraphQL

Fullstack GraphQL Tutorial to go from zero to production covering all basics and advanced concepts.

www.howtographql.com

 

더 깊이 있게 GrahQL Query의 내부 원리를 공부하는 링크 :
https://www.apollographql.com/blog/graphql/basics/the-anatomy-of-a-graphql-query/

 

The Anatomy of a GraphQL Query

GraphQL is just entering the mainstream as a new standard for data fetching. There are now a lot of great conversations happening around developments in the technology and new tools being built every day. One of the best parts of GraphQL is that it gives y

www.apollographql.com

 

REST API에 대한 설명

GraphQL에 대한 설명

Introduction

Facebook이 오픈한 새로운 API 표준으로, 선언적으로 데이터를 가져올 수 있다.

  • 선언적이라는 말은 결과를 받아 엮어서 계산해내는 게 아니라 결과로 원하는 게 뭔지를 지정하는 것이다. 결국 클라이언트는 원하는 결과를 정해서 주고, 서버가 그 결과대로 계산될 수 있게 방법을 파악한다.
  • 선언적 언어는 클라이언트를 위한 추상화 수준을 제공하므로, 클라이언트 입장에서는 백엔드 구현 세부 사항을 걱정하지 않고 상호작용할 수 있어서 쉽다.

REST API vs GraphQL

익히 써온 게 REST API니까 직관적으로 REST API와 GraphQL을 비교해보자.

REST API

REST API를 보면 하나의 request마다 GET,POST 등 HTTP method가 정해져 있고, 그 url에는 어떤 자원을 다루는 API인지 그 자원이 명시되어 있다. 그래서 백엔드 개발자는 기획안을 보면서 어떤 자원들을 엮어서 하나의 API로 만들어야 할지 파악하고, 필요할 만한 여러가지 REST API들을 설계한다. 자원을 저장하는 API도 필요할 것이고, 자원을 가져오는 API도 필요할 것이다.

이렇게 백엔드 개발자가 필요한 API 들을 고민해서 만들어두면, 클라이언트 단에서는 지금 이 화면을 만드는 데에 필요한 API, 즉 이 버튼을 눌렀을 때 아님 뭐 이러저러한 이벤트가 발생했을 때 이뤄져야 하는 저장이나 삭제 등을 구현하기 위해서, 필요한 API를 잘 엮어 활용할 것이다. 그렇게 엮이는 API가 여러 개일 수도, 하나일 수도 있다. 아무튼 필요한 REST API들을 잘 엮어서 어떤 이벤트가 발생했을 때 벌어져야 하는 일들을 구현한다. 만약 어떤 하나의 기능을 구성하는 데에 여러가지 API들을 함께 써야 한다면 한 순간에 여러 개의 request가 날아가고, 서버와 여러 번 커넥션이 이뤄진다.

REST API를 쓸 때에는 한 화면을 구성하는 데에 필요한 API가 여러 개가 될 수 있다. 이런 목록 중에서 필요한 걸 골라서 적용한다.

GraphQL

반면 GraphQL은 그냥 어떤 자원들이 있는지만 작성해두면, 클라이언트 단에서 지금 이 순간에 벌어져야 하는 일들을 하나의 request만으로 구현할 수 있다. schema에 어떤 자원들이 있는지 명시하고, 내가 지금 필요한 애만 가져올 수 있다.

 

이게 왜 좋냐면, REST API의 UnderFetcing, OverFetching 문제를 해결해주는 구조이기 때문이다.

Fetching은 가져온다는 의미로, API 요청을 통해 데이터를 가져오는 것이다. under 와 over가 접두어로 쓰이면 덜하게 혹은 과하게 가져온다는 말이라고 예상 가능하다.

// REST API
// GET /books/1 

{
  "title": "Black Hole Blues",
  "author": { 
    "firstName": "Janna",
    "lastName": "Levin"
  }
  // ... more fields here
}

REST API의 문제 : OverFetching

위와 같은 API가 있고 클라이언트에서는 위 response 속 필드를 모두 사용하는 경우도 있고, 저 중에 title이랑 author의 firstName만 사용하는 부분도 있다고 하자. 

이 두 가지 경우는 하나의 필드만 제외하고 나머지 필드는 둘이 동일하게 모두 필요하다. 이럴 때 겨우 하나의 파라미터만 다른 두 가지 상황을 위해 REST API를 하나 더 만들어야 할까? 그렇다고 API 하나로 쓰자니 response에 들어오는 필드 중 일부만 필요한 경우에는 저 모든 걸 가져오는 API를 호출하기가 부담스럽다. 이렇게 endpoint로 요청해서 응답받은 정보가 사용하지 않을 불필요한 데이터를 담고 있는 경우를 OverFetching이라고 한다. 필요 없는 데이터를 전송하니까 네트워크 낭비인 것이다.

REST API의 문제 : UnderFetching

반대로 UnderFetching은 하나의 endpoint로 필요한 모든 데이터 요청을 처리하지 못한다는 의미다. 여러 번의 API 호출이 필요하므로 API 요청 횟수가 증가하는 문제가 있다. 맨 처음에 위에서 REST API를 설명할 때 말한 상황이 여기에 해당된다. 클라이언트 단에서 하나의 일을 구현해낼 때 하나의 API로 다 되는 경우는 많지 않다. SNS 메인화면이 그 예인데, 메인 화면에는 타임라인도 있고 대댓글 알림 목록도 있고, 사용자 정보도 있다. 이걸 한 화면에 구현해내기 위해 각각에 대한 REST API가 만들어지면 얘네들을 호출해서 화면에 잘 조합해 나타낼 것이다.

GraphQL로 OverFetching, UnderFetching 해결하기

GraphQL 서버는 단일 endpoint를 노출하고, queries에 대해 응답한다.

1) 일단 자원들을 명시한다.

type Book {
  id: ID
  title: String
  published: Date
  price: String
  author: Author
}

type Author {
  id: ID
  firstName: String
  lastName: String
  books: [Book]
}

 

2) 자원을 명시했으니, 이 자원들한테 접근할 수 있게 Query를 만들자

type Query {
	book(id: ID!): Book
	author(id: ID!): Author
}

 

3) 이제 우리는 GraphQL을 사용해서 request를 보낼 수 있다.

// GET /graphql?query={ book(id: "1") { title, author { firstName } } }

{
  "title": "Black Hole Blues",
  "author": {
    "firstName": "Janna",
  }
}

 

결론) Query를 통해 book과 author에 접근할 수 있게 했는데, 내가 지금 당장 필요한 건 author 필드 전부가 아니라 firstName만 있으면 된다. 그래서 내가 원하는 것만 query에 담아서 요청했다.

 

GraphQL Schema를 작성해보자.
(REST API의 URL Routes와 비교도!)

API는 그 API가 뭘 call할 수 있는지 결과를 예측할 수 있어야 한다. 그래서 이게 어떤 것에 접근하는 API인지 등의 정보를 알 수 있는 description이 매우 중요하다.

이 description은 API 문서라고 생각하면 된다. GraphQL에서는 introspection이고, REST API에서는 Swagger같은 애들...!! 근데 이러한 정보들도 GraphQL에서는 프로그래밍 방식처럼 만들어질 수 있다.

 

아래 REST API 목록을 보면 굉장히 linear하다. 

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

 

내가 접근할 수 있는 것들에 대한 리스트가 있고, 내가 REST API를 통해 어떤 데이터를 받고 싶다면 그때 가장 먼저 정리해야할 요소가 "어떤 endpoint를 호출해야 할까?"이다.

즉 URL을 보면서 내가 뭐에 접근할 수 있는지를 파악한다. URL이랑 내가 접근할 수 있는 자원이 매우 매우 관련이 깊다!!! 그러다 보니 윗 문장처럼 어떤 endpoint를 호출해야 할지를 먼저 고민해야 하는 게 REST API의 특징이다.

 

그러나 GraphQL에서는 이 API를 가지고 뭘 할 수 있는 지를 URL로 식별하지 않는다. 그 대신 GraphQL 스키마를 활용한다.

type Query {
  book(id: ID!): Book
  author(id: ID!): Author
}

type Mutation {
  addComment(input: AddCommentInput): Comment
}

type Book { ... }
type Author { ... }
type Comment { ... }
input AddCommentInput { ... }

 

REST API와 다른 흥미로운 점들이 몇가지 있다.

  1. REST API는 서로 다루는 자원은 같지만 하는 작업이 다른 것에 대해 다른 HTTP verb(method라고 생각하면 됨)를 사용한다. (같은 URL이지만 작업이 다른, 예를 들어 GET이냐 POST냐만 다른 두 API처럼.)
    반면, GraphQL은 애초에 서로 다른 initial type을 사용한다. Mutation과 Query가 있는데, 어떤 작업을 할지를 이 두 가지 키워드 중에 고를 수 있다.
  2. GraphQL에서는 스키마에 정의된 관계에 따라 추가 데이터를 가져오는 복잡한 쿼리를 보낼 수 있지만, REST에서는 여러 요청을 통해 이를 수행해야 하고 혹은 응답을 수정하기 위해 초기 응답에 관련 데이터를 빌드하거나 URL에 일부 특수 매개변수를 포함해야 한다.

 

아래 표에 차이를 정리했다. 차이점 매칭은 색상으로 구분했다.

  REST API GraphQL
공통점
  • 자원을 갖고 있고, 그 자원에 ID를 명시할 수 있다.
  • HTTP GET request를 통해 URL로 데이터가 가져와질 수 있다.
  • JSON 형태로 리턴된다.
유사한 점
  • REST API의 endpoint 목록은 GraphQL의 Query와 Mutation 타입 속 필드의 목록과 유사하다.
  • API의 의미가 데이터를 읽는거냐 쓰는거냐에 따라 차이를 가진다.
차이점 호출하는 endpoint가 곧 그 객체를 의미한다. 호출하는 endpoint와 어떤 데이터가 가져와 지는 지 서로 상관이 없다. 분리되어 있다.
자원의 형태와 크기가 서버에 의해 결정된다. 서버에서 API 개발하면서 결정된다. 서버는 어떤 자원들이 사용 가능한지만 선언하고, 클라이언트가 요청하는 타임에 자기가 원하는 게 뭔지 명시해서 요청한다.
REST에는 중첩된 URL의 일급 개념이 없다.  Query 타입의 필드와 다른 타입의 필드 사이에 차이점이 없다. 단, Query 타입만 Query루트에서 액세스할 수 있다. 예를 들어 쿼리의 모든 필드에 인수가 있을 수 있다. 무슨 말인지 아직 모르겠다. ㅋㅋ 사용법을 보면 이해될듯!
HTTP 동작을 바꿈(Get,Post...)으로써 정의할 수 있다.  query에서 키워드를 바꾸면 된다.
각 request가 정확히 하나의 route handler(요청을 받는 서버 코드 속 함수)를 호출한다. 하나의 query가 많은 resolvers를 호출해서 여러개의 자원이 중첩된 응답을 만들어낼 수 있다.
응답의 형태를 내가 스스로 구상한다.
응답의 형태가 GraphQL 실행 라이브러리에 의해 build된다.

 

마지막 차이점이 젤 많이 언급되는 것 같다. 그걸 설명해주는 그림은 바로 아래에!

 

728x90
Comments