GraphQL과 REST API 차이점

REST API와 차이점

OverFetching

  • GraphQL은 요청(request)에 자신이 원하는 항목을 명시하면 응답(response)에 해당 항목만 반환되기 때문에 네트워크 대역폭을 절약할 수 있다. 대신 가변 요청을 처리하기 위해 GraphQL 요청엔 약간의 오버헤드 데이터가 있다. 반면 REST API는 엔트포인트 별로 항상 일정한 응답이 반환되기 때문에 필요없는 데이터도 반환될 수 있다.

    클라이언트에서 요구하는 데이터보다 더 많은 데이터를 수신하는 문제

UnderFetching

  • GrapghQL은 엔드포인트가 1개이기 때문에 HTTP 요청 1번에 원하는 데이터를 모두 가져올 수 있다. 하지만 REST API는 일반적으로 데이터 종류별로 엔드포인트가 존재하기 때문에 원하는 데이터의 엔드포인트마다 일일이 HTTP 요청을 해야한다.

    클라이언트에서 요구하는 데이터보다 더 적은 데이터를 수신하는 문제

Type

  • GraphQL은 요청과 응답에 대해 자료형 지정이 가능하다. 그래서 허용되지 않은 자료형 데이터가 요청으로 들어오면 응답이 거부되고, 클라이언트는 응답 데이터의 자료형을 명확하게 알 수 있다. 쉽게 말해 GraphQL의 장단점은 JavaScript에 비해 TypeScript가 가지는 장단점과 비슷하다.

Cross Platform

  • GraphQL, 안드로이드, iOS등 클라이언트 별로 API를 만들 필요 없이 1개만 만들면 된다.

REST API와 비슷한 점

엔드포인트

  • GraphQL은 엔드포인트가 1개이기 때문에 엔드포인트를 따로 유지보수할 필요가 없다. 하지만 반대로 말하면 클라이언트가 서버 API의 요청 가능 함수를 제대로 숙지하고 있어야 한다는 뜻이다. 반면 REST API는 엔드포인트를 따로 관리해야 한다. 즉, GraphQL서버 API의 함수 이름을 관리해야 하고, REST엔드포인트를 관리해야 한다.

스키마

  • REST는 따로 API 문서를 작성하고 관리해야 하지만, GraphQL은 엔드포인트에서 제공하는 스키마 파일을 통해 서버 API 함수의 종류와 자료형을 알 수 있다. 하지만 따지고 보면 GraphQL도 누군가는 스키마 파일을 관리해야 한다. 즉, REST는 API 문서를 직접 작성해야 하고, GraphQL은 스키마 파일을 직접 작성해야 한다.

쿼리 - 뮤테이션

  • GraphQL의 Query는 REST API의 GET과 비슷하고, GraphQL의 MUTATION은 REST API의 POST, PUT, DELETE와 비슷하다.

파일 전송

  • REST API와는 다르게 GraphQL은 자체적으로 텍스트 전송만 지원하고 파일 전송을 지원하지 않는다. 물론 파일을 텍스트로 표현할 수 있기 때문에 외부 라이브러리를 사용하면 파일 전송이 가능하다. 결과적으로는 둘 다 파일 전송을 지원한다.

캐싱

  • REST API는 엔드포인트가 여러 개이기 때문에 각 데이터 요청에 대해 HTTP 캐싱을 그대로 활용할 수 있다. 하지만 GraphQL은 엔드포인트가 1개이기 때문에 HTTP 캐싱을 그대로 이용할 수는 없고 다른 캐싱 기법(Apollo client 등)이 필요하다. 결과적으론 둘 다 캐싱을 지원한다.

요약

  1. Rest에서는 Resource에 대한 형태 정의와 데이터 요청 방법이 연결되어 있지만, GraphQL에서는 Resource에 대한 형태 정의와 데이터 요청이 완전히 분리되어 있습니다.
  1. Rest에서는 Resource의 크기와 형태를 서버에서 결정하지만 GraphQL에서는 Resource에 대한 정보만 정의하고 필요한 크기와 형태는 client단에서 요청 시 결정합니다.
  1. Rest에서는 URI가 Resource를 나타내고 Method가 작업의 유형을 나타내지만, GraphQL에서는 GraphQL Schema가 Resource를 나타내고 Query, Mutation 타입이 작업의 유형을 나타냅니다.
  1. Rest에서는 여러 Resource에 접근하고자 할 때 여러 번의 요청이 필요하지만, GraphQL에서는 한번의 요청에서 여러 Resoruce에 접근할 수 있습니다.
  1. Rest에서 각 요청은 해당 엔트포인트에 정의한 핸들링 함수를 호출하여 작업을 처리하지만, GraphQL에서는 요청 받은 각 필드에 대한 resolver를 호출하여 작업을 처리합니다.

즉, REST 방식은 수신되는 (Response) 데이터 구조를 서버에서 정의하며, GraphQL은 클라이언트에서 정의한다는 것이 가장 큰 차이점이다.

REST API

GET /books/1

{
	"title": "Romance of the Three Kingdoms",
  	"author": {
     	 "firstName": "Luo",
         "lastName": "Guanzhong"
     }
}

리소스의 타입 또는 형태와 리소스를 가져오는 방식이 연결되어 있다. /books라는 리소스를 요청 하면 위의 JSON 파일의 형태의 데이터가 주어지게 됩니다.

GraphQL

위의 코드를 GraphQL로 옮기기 위해서는 Book과 Author라는 타입을 정의해야 합니다.

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

GraphQL에서는 리소스의 유형과 리소스를 가져오는 방식이 완전하게 분리되어 있습니다. 현재 Book과 Author의 형태만을 정의했지 client에서 데이터를 어떻게 요청할 수 있는지에 대해서는 아무런 정보가 없습니다. Book과 Author에 접근할 수 있도록 하기 위해서는 Query라는 타입이 필요합니다.

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

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

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

REST와는 다르게 /books등과 같이 각 Resource에 대한 엔드포인트가 따로 존재하지 않고, 하나의 엔드포인트만 존재합니다. 또한 해당 엔드포인트로 요청 시, 원하는 리소스와 해당 리소스에서 원하는 필드를 특정하는 GraphQL query를 함께 보냅니다. 위의 gql을 통해 id = 1인 book의 title과 author의 firstName만 가져올 수 있었습니다.

URL Routes vs GraphQL Schema

API는 요청할 수 있는 리소스가 어떤 것이 있고, 어떤 리소스에 어떤 요청을 했을 때 어떠한 결과가 나에게 전달되는 지를 모르면 당연하게도 아무 쓸모가 없습니다. 모든 API 서비스는 해당 API에 대한 명세가 있습니다. GraphQL에서는 GraphQL introspection이, REST API에서는 Swagger가 문서화를 쉽게 도와줍니다. 문서화 뿐만 아니라 실제 요청을 테스트해 볼 수 있도록 도와줍니다.

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

REST API에서 어떤 데이터를 조회하거나 추가하는 것과 같은 작업을 진행하고자 할 때, 제일 먼저 생각해야 하는 것은 어떤 엔드포인트로 요청을 보내야 하는지 입니다. 각 엔드포인트는 해당 리소스를 가리키며, 요청의 HTTP method에 따라 어떤 작업을 진행하는 지 달라집니다.

GraphQL에서는 URL을 Resource를 특정 짓는 것에 사용하지 않습니다. GraphQL Schema가 Resource를 특정 짓습니다. 또한 HTTP Method로 어떤 작업을 진행하게 되는지 구분하지 않고 Query, Mutation이라는 타입을 사용해 구분합니다.

어떻게 보면 어떤 리소스와 필드를 가져오게 될 지 결정한다는 점에서 REST의 resource 목록이 Query와 Mutation 타입에서 나열된 필드와 비슷합니다.

GraphQL은 한번의 요청으로 여러 resource에 대해 접근할 수 있습니다. 반면에 REST API에서 여러 리소스에 접근하고자 한다면 여러 번의 요청은 불가피합니다.

Route Handlers vs Resolvers

API를 요청하면 API 서버에서는 어떻게 될까요 ? 요청으로부터의 Resource, HTTP Method에 해당하는 사전에 정의된 로직(DB와의 작업을 진행하거나, 다른 API를 호출하거나, 계산, 분석 등을 진행)을 실행하고, 결과를 되돌려주는 것이 일반적입니다.

REST API (Route Handlers)

app.get('/books/:id', function(req, res) {
	const { id } = req.params;
    
    const result = {
    	title: "Romance of the Three Kingdoms",
        author: {
        	firstName: "Luo",
            lastName: "Guanzhong"
    	}
    };
    res.send(result);
})

title과 author 필드를 갖는 json 데이터라는 문자열을 응답하는 /books 엔드포인트가 있습니다. /books 엔드포인트는 GET 방식 요청에만 반응합니다. 클라이언트에서 이 서버의 GET /books/1로 요청하면 다음 응답을 받을 수 있습니다.

{
 	"title": "Romance of the Three Kingdoms',
  	"author": {
  		"firstName": "Luo",
  		"lastName": "Guanzhong"
	}
}

GraphQL API (Resolvers)

const resolvers = {
 	Query: {
        book: (parent, args) => {
          const result = {
            title: "Romance of the Three Kingdoms",
          };
          return result;        
        },
      	author: (parent, args) => ({ firstName: "Luo", lastName: "Guanzhong" })      
    }
}

REST와는 다르게 특정 엔드포인트에 대한 어떤 함수를 제공하는 대신, Query 타입의 books와 같은 특정 필드에 해당하는 함수를 제공합니다. GraphQL에서 이런 함수를 resolver라고 합니다.

클라이언트에서 다음의 쿼리를 통해 요청하여 응답을 받을 수 있습니다.

query {
	book(id: "1") {
    	title
        author {
        	firstName
            lastName
        }
    }
}

서버로 요청이 들어오면, 서버는 요청에서 GraphQL Query를 찾습니다. query에 존재하는 field들의 resolver를 호출하고 각 필드마다 호출된 resolver의 반환 값을 모아 query의 형태와 일치하는 json 데이터를 응답합니다. 이 경우에는 다음의 데이터가 응답될 수 있습니다.

{
	"title": "Romance of the Three Kingdoms",
        "author": {
            "firstName": "Luo",
            "lastName": "Guanzhong"
        }
}
GraphQL APIREST API

좋은 웹페이지 즐겨찾기