- GraphQL
GraphQL은 Facebook에서 처음으로 개발
Graph + Query Language의 줄임말로 Query Language 중에서도 Server API 를 통해 정보를 주고받기 위해 사용하는 Query Language
쉽게 말해 API를 위한 쿼리 언어
GraphQL은 REST API 방식의 고정된 자원이 아닌 클라이언트 요청에 따라 유연하게 자원을 가져올 수 있다는 점에서 엄청난 이점을 갖는다.
-GraphQL vs REST API-
- REST API는 Resource에 대한 형태 정의와 데이터 요청 방법이 연결되어 있지만, GraphQL에서는 Resource에 대한 형태 정의와 데이터 요청이 완전히 분리되어 있습니다.
- REST API는 Resource의 크기와 형태를 서버에서 결정하지만, GraphQL에서는 Resource에 대한 정보만 정의하고, 필요한 크기와 형태는 클라이언트 단에서 요청 시 결정합니다.
- REST API는 URI가 Resource를 나타내고 Method가 작업의 유형을 나타내지만, GraphQL에서는 GraphQL Schema가 Resource를 나타내고 Query, Mutation 타입이 작업의 유형을 나타냅니다.
- REST API는 여러 Resource에 접근하고자 할 때 여러 번의 요청이 필요하지만, GraphQL에서는 한번의 요청에서 여러 Resource에 접근할 수 있습니다.
- REST API에서 각 요청은 해당 엔드포인트에 정의된 핸들링 함수를 호출하여 작업을 처리하지만, GraphQL에서는 요청 받은 각 필드에 대한 resolver를 호출하여 작업을 처리합니다.
-GraphQL 장점
- 하나의 endpoint 요청
/graphql이라는 하나의 endpoint 로 요청을 받고 그 요청에 따라 query , mutation을 resolver 함수로 전달해서 요청에 응답합니다. 모든 클라이언트 요청은 POST 메소드를 사용합니다.
No! under & overfetching
- 여러 개의 endpoint 요청을 할 필요없이 하나의 endpoint에서 쿼리를 이용해 원하는 데이터를 정확하게 API에 요청하고 응답으로 받을 수 있습니다.
강력한 playground
- graphql 서버를 실행하면 playground라는 GUI를 이용해 resolver 와 schema 를 한 눈에 보고 테스트 해 볼 수 있습니다. (POSTMAN 과 비슷합니다.)
- 클라이언트 구조 변경에도 지장이 없음
클라이언트 구조가 바뀌어도 필요한 데이터를 결정하고 받는 주체가 클라이언트이기 때문에 서버에 지장이 없습니다. 클라이언트에서는 무슨 데이터가 필요한 지에 대해서만 요구사항을 쿼리로 작성하면 됩니다.
-GraphQL 단점
- 캐싱이 REST보다 훨씬 복잡합니다.
HTTP에선 각 메소드에 따라 캐싱이 구현되어 있습니다. 하지만 GraphQL에선 POST 메소드만을 이용해 요청을 보내기 때문에 각 메소드에 따른 캐싱을 지원받을 수 없습니다. 그래서 이를 보안하기 위해 Apollo 엔진의 캐싱과 영속 쿼리 등이 등장하게 되었습니다.
- 고정된 요청과 응답만 필요할 경우에는 Query 로 인해 요청의 크기가 RESTful API 의 경우보다 더 커집니다.
- Query(GET): 저장된 데이터 가져오기 (REST의 GET과 비슷합니다.)
- Mutation: 저장된 데이터 수정하기
Create: 새로운 데이터 생성
Update: 기존의 데이터 수정
Delete: 기존의 데이터 삭제
- Subscription: 특정 이벤트가 발생 시 서버가 대응하는 데이터를 실시간으로 클라이언트에게 전송
1) Query
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
2) Mutattion
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
3) Schema/Type
type Character {
name: String!
appearsIn: [Episode!]!
}
- Character는 GraphQL 객체 타입이며, 즉 필드가 있는 타입임을 의미합니다. 스키마에 있는 대부분의 타입은 객체 타입입니다.
- name 과 appearIn 은 Character 타입의 필드 입니다. 즉 name 과 appearIn 은 GraphQL 쿼리의 Character 타입 어디서든 사용할 수 있는 필드입니다.
- String은 내장된 스칼라 타입 중 하나입니다. 이는 단일 스칼라 객체로 확인되는 유형이며 쿼리에서 하위 선택을 가질 수 없습니다. 스칼라 타입에는 ID, Int도 있습니다.
- !가 붙는다면 이 필드는 nullable하지 않고 반드시 값이 들어온다는 의미입니다. 이것을 붙여 쿼리한다면 반드시 값을 받을 수 있을 것이란 예상을 할 수 있습니다.
- [ ]는 배열을 의미합니다. 배열에도 !가 붙을 수 있습니다. 여기서는 ! 이 뒤에 붙어 있어 null 값을 허용하지 않으므로 항상 0개 이상의 요소를 포함한 배열을 기대할 수 있게 됩니다.
4) Resolver
요청에 대한 응답을 결정해주는 함수
- npx create-react-app 'app name'
- npm install @octokit/graphql
- import { graphql } from "@octokit/graphql";
예제1 )
query HeroNameAndFriends {
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}
//결과
{
"data": {
"empireHero": {
"name": "Luke Skywalker"
},
"jediHero": {
"name": "R2-D2"
}
}
}