GraphQL 사용법 알아보기

2017년 04월 01일


살펴보기

GraphQL은 쿼리 언어입니다. 필요한 데이터를 쿼리로 표현한 뒤, 이 쿼리를 이용해서 데이터를 주고 받습니다.

클라이언트 측에서는 쿼리만 작성하면 되고, 서버 측에서는 쿼리에 대한 동작만을 정의하면 됩니다. 하나의 엔트리 포인트로 작동하기 때문에 기능이 추가될 때 마다 API를 새로 작성할 필요가 없는 것이 특징입니다.

공식적인 설명에서 GraphQL은 언어에 대한 명세와 서버측 런타임(쿼리 실행기)만을 언급합니다. 그 외에는 명세하고 있는 것이 없기 때문에, 어떤 데이터베이스를 사용할지, 어떻게 쿼리를 주고 받을지는 개발자가 결정할 몫입니다.

이러한 특징 덕분에 GraphQL을 사용하기 위해 특별히 준비해야 할 것이 별로 없습니다. 기존에 작성한 API와 동시에 사용할 수 있고 심지어 GraphQL에서 기존의 API를 사용할 수도 있습니다.

기본 문법

GraphQL 문법은 크게 질의를 위한 문법과 스키마 정의 문법 두 가지가 있습니다.

우선 질의에 대한 문법부터 살펴보겠습니다.

{
  myFavoriteSubway {
    name
    bread
    price
    sources {
      id
      name
    }
  }
}

GraphQL 쿼리는 중첩 된 괄호쌍으로 표현됩니다. 필요한 데이터를 필드로 명시합니다.

데이터가 계측 혹은 관계를 갖는 경우, 중첩된 필드를 이용해 필요한 데이터를 명시합니다.

위 쿼리는 name, bread, price 필드와 sources라는 중첩된 필드를 요청하고 있습니다. sources라는 데이터는 id와 name이라는 필드를 갖고있고 이를 요청합니다.

위의 쿼리가 서버에서 제공하고 있는 스키마에 일치한다면 다음과 같은 데이터를 얻을 수 있습니다. JSON으로 표현된 결과값과 질의에 사용한 쿼리는 같은 구조를 갖습니다.

특별한 부분은 sources가 배열로 이뤄진 필드라는 것입니다. 질의에 대한 문법에서는 따로 배열을 명시하지 않기 때문에 배열로 이뤄진 필드는 복수형으로 표현합니다.

{
  "data": {
    "myFavoriteSubway": {
      "name": "Subway Melt",
      "bread": "Hearty Italian",
      "price": 9900,
      "sources":[
        { 
          "id": 7,
          "name": "Vinegar"
        },
        { 
          "id": 9,
          "name": "Oil"
        }
      ]
    }
  }
}

다음은 스키마에 대한 문법입니다. 스키마에 대한 문법은 데이터를 제공하는 측에서 사용합니다.

스키마는 타입으로 표현되고 서버가 제공할 데이터를 결정합니다. 실질적인 GraphQL 설계는 스키마를 작성하는 것으로 이뤄집니다.

type Subway {
  id: ID!
  name: String!
  bread: String!
  price: Int!
  sources: [Source!]!
  toppings: [Topping!]!
}

type Source {
  id: ID!
  name: String!
}

type Topping {
  id: ID!
  name: String!
}

필드의 이름과 타입을 표시합니다. 타입 뒤에 !는 그 필드가 null이 될 수 없다는 것을 의미하고, []는 배열을 의미합니다.

복잡한 부분은 sources: [Source!]! 입니다. sources은 배열이고 Source에 !가 붙었기 때문에 원소는 null이 아닌 Source 타입입니다. 추가적으로 배열 자체에 !가 붙었기 때문에 배열이 비어있을 수는 있지만 배열 자체가 null이 될 수는 없습니다.

위 코드를 보시면 Subway 타입은 질의에 사용했던 것 보다 많은 데이터를 제공하고 있다는 것을 알 수 있습니다. GraphQL은 스키마에서 명시하는 데이터의 일부만을 가져올 수 있기 때문에 복잡한 데이터를 요청하는 경우 중복을 줄여 효율적으로 동작할 수 있습니다.

GraphQL이 만능은 아니다

항상 GraphQL이 좋은 것은 아닙니다. 기존의 방식이 나을때도 분명히 있습니다.

가장 대표적인 것이 캐싱입니다. GraphQL도 서버나 클라이언트 수준에서 캐시를 사용할 수 있지만, 복잡한 쿼리를 만들어 데이터를 요청하기 때문에 GET 방식으로 요청해도 CDN에 캐싱하기가 까다롭습니다.

복잡한 Ajax가 필요한 경우에도 GraphQL은 적합하지 않습니다. GraphQL은 단순히 요청, 실행, 반환만을 담당하도록 설계하는 것이 좋습니다. 파일 업로드와 같은 특별한 기능을 GraphQL로 작성하면 클라이언트의 구현이 복잡해질 뿐만 아니라, 기능이 GraphQL에 물려있기 때문에 서버를 효율적으로 스케일링 할 수 없습니다. 스케일링 문제는 Remote Schema와 Schema Stitching 기능으로 해결할 수 있지만 번거롭습니다.

GraphQL과 rest API는 항상 동시에 사용할 수 있기 때문에 굳이 모든 기능을 GraphQL로 제공할 필요가 없습니다.