GraphQL

Jaemin Jung·2022년 4월 19일
0

GraphQL

목록 보기
1/2
post-thumbnail

Introduction

GraphQl은 REST API를 대체하는 보다 효율적인 새로운 API 표준.
타입 시스템을 사용하여 쿼리를 실행하는 서버사이드 런타임이다.
Facebook이 개발하고 오픈 소스로 공개되었으며, 전세계의 수많은 사람들과 기업들로 구성된 거대한 커뮤니티에 의하여 유지 되고있음

GraphQL의 핵심은 클라이언트가 필요한 데이터를 정확하게 특정하여 API에 요청하는 선언적인 데이터 불러오기를 가능하게 만드는 것이다.

데이터베이스 종류와 상관 없이 작동하며(Agnostic), API가 사용되는 모든 맥락에서 효율적으로 사용될 수 있다.

REST API와 비교

REST API는 URL, METHOD등을 조합하기 때문에 다양한 Endpoint가 존재하며 고정된 형태의 데이터 구조를 반환한다.

GraphQL 서버는 단 하나의 엔드포인트만을 노출시키고,
클라이언트가 요청한 데이터들만을 정확하게 반환한다.

SDL

GraphQL은 API의 스키마를 정의하기 위한 고유의 타입 시스템을 갖추고 있다.

스키마를 작성하는 문법을 스키마 정의 언어(SDL)이라고 부른다.

타입 정의 예시

type Person {
  name: String!
  age: Int!
}

타입 간의 관계를 표현하는 것도 가능하다.
person이 post와 연관 관계를 가질 수 있다.

type Post {
  title: String!
  author: Person!
}
type Person {
  name: String!
  age: Int!
  posts: [Post!]!
}

기본적인 쿼리문 (Fields)

{
  allPersons {
    name
  }
}

해당 쿼리문에서 allPersons 필드는 쿼리문의 루트 필드라고 부른다.

루트 필드 아래에 있는 모든 값들은 쿼리문의 페이로드(payload)라고 부른다.
위의 쿼리문에 명시된 페이로드는 name 이다.

  • Root field: 가장 상위의 필드

  • Payload field: 루트 필드 아래에 있는 필드

  • response 예시

{
  "allPersons": [
    { "name": "Johnny" },
    { "name": "Sarah" },
    { "name": "Alice" }
  ]
}

response에서 각 사람들은 오직 name 값만을 가지고 있고
age 값은 서버로부터 반환되지 않았다.
이는 name 필드만이 쿼리문 상에 명시되었기 때문이다.

만약 클라이언트에서 각 사람들의 age 값도 필요하다면,
아래와 같이 쿼리문을 살짝 수정하여서 쿼리문의 페이로드에 새로운 필드를 추가하기만 하면 된다.

{
  allPersons {
    name
    age
  }
}

GraphQL의 가장 큰 장점 중 하나는 중첩된 정보를 자연스럽게 질의할 수 있다는 점이다.
예를 들어, 한 Person이 작성한 모든 posts를 불러오고 싶다면, 타입의 구조에 맞추어 아래와 같이 요청하기만 하면 된다.

{
  allPersons {
    name
    age
    posts {
      title
    }
  }
}

GraphQL 쿼리는 연관된 객체와 필드를 탐색 할 수 있으므로
클라이언트는 기존 REST 구조처럼 여러번 요청을 수행하는 대신
한번의 요청으로 많은 데이터를 가져올 수 있다.

인자(Arguments)

REST와 같은 시스템에서는 요청에 쿼리 파라미터와 URL 세그먼트 같은 단일 인자들만 전달할 수 있다.
하지만 GraphQL에서는 모든 필드와 중첩된 객체가 인자를 가질 수 있다.

allPersons 필드는 last 매개변수를 가지는 것으로 반환되는 사람 데이터의 수를 제한할 수 있다.

{
  allPersons(last: 2) {
    name
  }
}

뮤테이션 (Mutaion)

서버에 정보를 요청하는 것 다음으로, 대부분의 어플리케이션은 현재 백엔드에 저장된 데이터를 수정할 방법을 필요로 한다.
GraphQL에서는 이러한 작업을 Mutation이라고 부른다.
뮤테이션은 다음과 같은 3종류가 있다.

Create: 새로운 데이터 생성
Update: 기존의 데이터 수정
Delete: 기존의 데이터 삭제

뮤테이션은 쿼리문과 동일한 문법 구조를 가지지만,
반드시 mutation 키워드와 함께 시작해야 한다.

새로운 person을 생성하는 예시

mutation {
  createPerson(name: "Bob", age: 36) {
    name
    age
  }
}

쿼리문에서와 마찬가지로 뮤테이션에도 페이로드를 지정할 수 있다.
새롭게 생성되는 person 객체가 가지는 속성들 중에서 선택하여 값을 확인할 수 있다.

예시의 경우, name 과 age 정보를 요청하였다.

물론 인자로 값을 전달하는 시점에서 이미 각각의 값을 아는 상태이므로 쓸모는 없는데, 뮤테이션을 보냄과 동시에 정보를 불러오는 것은, 서버에 요청을 한번만 보내고도 새로운 정보를 받을 수 있다는 것.

  • response 예시
"createPerson" {
  "name": "Bob",
  "age": 36,
}

새로운 객체가 생성될 때, 서버가 생성해준 고유한 ID 값을 GraphQL 타입이 갖게 되는 것은 흔히 볼 수 있는 패턴이다.
Person 타입을 확장하여, 아래와 같이 id 값을 추가할 수 있습니다.

type Person {
  id: ID!
  name: String!
  age: Int!
}

새로운 Person이 생성되면, 뮤테이션의 페이로드를 통하여 id의 값을 직접 요청할 수 있게 된다.

mutation {
  createPerson(name: "Alice", age: 36) {
    id
  }
}

구독

클라이언트가 어떤 이벤트를 구독하면, 클라이언트는 서버와 지속적인 연결을 형성하고 유지하게 된다.
특정 이벤트가 발생하면, 서버는 대응하는 데이터를 클라이언트에 푸시해준다.

전형적인 요청-응답 순환을 따르는 쿼리문 또는 뮤테이션과 달리,
구독은 클라이언트를 향한 데이터 흐름을 나타낸다.

구독은 쿼리문과 뮤테이션과 동일한 문법을 사용하여 작성된다.
아래의 예시는 Person 타입에 대하여 발생하는 이벤트를 구독한다.

subscription {
  newPerson {
    name
    age
  }
}

클라이언트가 위와 같이 서버에 구독하면, 이 둘 간에 연결이 형성된다.
그러면 새로운 Person을 생성하는 새로운 뮤테이션이 이루어질 때마다 서버는 아래와 같이 새로 생성된 사람에 대한 정보를 클라이언트에 전송하게 된다.

{
  "newPerson": {
    "name": "Jane",
    "age": 23
  }
}

참고 사이트

https://graphql.org/learn/queries/
https://velog.io/@cadenzah/graphql-node-02-getting-started

profile
내가 보려고 쓰는 블로그

0개의 댓글