Data를 Graph로 표현하는 Language이자 Runtime이다. QL의 Query Language에서 질의어라고 생각할 수 있다. 실제로 프론트엔드에서는 API 데이터를 query하는 언어가 맞다. 하지만 백엔드에서는 Runtime 계층의 역할을 하기도 한다.
Rest API가 존재하지만 왜 GraphQL을 써야 하는가 하면 바로 GraphQL의 장점은 표준이기 때문이다. Swagger를 쓰지 않아도 GraphQL은 schema를 통해 API의 기능 범위를 문서를 통해 공개한다. 또한 over-fetching이나 under-fetching이 일어나지 않는다. (쿼리를 통해 필요한 데이터를 추출하기 때문) 그리고 1개의 EndPoint를 가져 단순하게 사용할 수 있다. 결정적으로 그래프 구조를 가져 새 노드만 추가해주면 버전이 관리가 된다. 모바일 클라이언트에서는 앱이 설치되면 API를 업데이트하지 않는 이상 계속 사용하여야 하는데 GraphQL은 이를 해결할 수 있다. 하지만, 오래된 노드를 처리해야 하기도 하고 이에 대한 유지보수도 해야 한다.
{
person(personID: 4){
name
birthYear
}
}
위 쿼리는 ID가 4인 person의 name과 birthYear를 요청한다.
기본적인 GraphQL 요청을 문서(Document)라고 한다. 문서에는 Query, mutation, subscribe, fragment가 포함된다. 변수와 meta-data도 포함될 수 있다.
query GetEmployees($active: Boolean!){
allEmployees(active: $active){
...employeeInfo
}
}
fragment employeeInfo on Employee {
name
email
startDate
}
GraphQL에서 Query는 읽기 전용으로 데이터를 추출한다.
GraphQL에서 mutation은 데이터를 변경한 후 추출한다.
GraphQL에서 subscription은 실시간으로 데이터 변경 내용을 받는다 socket 통신을 한다. data polling보다 효율적이다.
GraphQL에서 Field는 추출해야 할 객체의 개별 정보 단위를 기술한 것이다. 스칼라 필드는 query에서 leaf값을 나타낸다. 스칼라 타입으로는 Int, String, Float, Boolean이 있다.
{
me { # 객체를 기술한 필드
email #스칼라 필드
birthday { # 객체를 기술한 필드
month # 스칼라 필드
year # 스칼라 필드
}
friends { #객체를 기술한 필드
name # 스칼라 필드
}
}
}
__type 또는 __schema라는 Root Field로 시작하는 필드를 메타 필드라고 한다. 이러한 쿼리를 내향성 쿼리(Introspective query)라고 한다.
위 쿼리는 해당 스키마가 지원하는 모든 타입을 반환하며 각 타입별 설명도 포함한다.
단일 타입에 대한 정보는 __type을 사용하여 확인한다.
위 쿼리는 Commit 타입을 지원하는 모든 필드를 인수와 함께 반환한다.
query UserInfo {
user(email: "jane@doe.name") {
firstName
lastName
username
}
}
user 필드의 괄호안의 email을 필드 인수(filed arguments)라고 한다.
단일 레코드를 표현하고, 인수값이 꼭 데이터베이스상에 존재하는 고유한 값이어야 한다.
GraphQL에서는 모든 객체를 단일 레코드 필드로 관리한다.
query OrgInfo {
organization(login: 'jscomplete') {
name
description
websiteUrl
repositoies (first: 10){
nodes {
name
}
}
}
}
위의 깃허브API(az.dev/github.api)에서는 user, repository, project, organization이 단일 레코드 필드에 해당한다.
레코드 수를 제한할 때는 인수(first or last)를 통해 제한할 수 있다.
레코드를 정렬할 때는 created_at, upated_at, pushed_at, Name, Stargazer 등 다양한 필드를 사용해서 정렬할 수 있다. (github api에서)
query orgReposByName {
organization(login: "jscomplete") {
repositories(first: 10, orderBy: {field: NAME, direction: ASC}) {
node {
name
}
}
}
}
...
edges {
cursor
node {
name
}
}
edge 필드는 부모 노드로 추가하면, 페이지 매김한 레코드의 리스트를 나타낸다. 이때, Connection은 서로 연결된 노드들을 가리킨다. (graph의 관계에서 유례)
graphql은 필드 인수를 통해 필터링 조건이나 검색어를 지정해서 list가 반환하는 결과의 범위를 좁힐수 있다.
@로 시작하는 문자열을 사용한다. 모든 schema는 3가지 기본 지시문을 사용할 수 있는데, 그것은 @include, @skip, @deprecated 이다.
query AllDirectives {
__schema {//내향성쿼리
directives {
name
description
locations
args {
name
description
defaultValue
}
}
}
}
내용의 결과를 보면 @include와 @skip은 if와 같은 조건을 인수로 사용하고, @deprecated 지시문은 reason이라는 인수를 필요로 한다.
재사용되는 값이 있을 때, 하드코딩 되는 일을 방지하기 위하여 변수를 사용한다. 덕분에 쿼리 또한 재사용할 수 있다. 앞에 $를 붙이고 타입을 선언할 수 있고, 값을 대입할 수도 있다.