GraphQL
Facebook에서 처음으로 개발했고, Graph + Query Language의 줄임말로 Server API 를 통해 정보를 주고받기 위해 사용하는 Query Language를 의미한다.

GraphQL의 특징

  1. GraphQL은 HTTP를 통해 API 서버로 요청을 보내고 응답을 받는다.
  2. 응답을 받을 시, 데이터 결과를 JSON 형식으로 받는다.
  3. GraphQL은 서버 개발자가 작성한 각 필드에 대응하는 resolver 함수로 각 필드의 데이터를 조회할 수 있다.
  4. GraphQL은 GraphQL 라이브러리가 조회 대상 schema가 유효한지 검사한다.

Graph를 사용하는 이유

GraphQL은 클라이언트 요청에 따라 유연하게 트리 구조의 JSON 데이터를 응답으로 전송할 수 있다. REST API 방식의 고정된 자원이 아닌 클라이언트 요청에 따라 유연하게 자원을 가져올 수 있다는 점에서 엄청난 이점을 갖기 때문에 사용한다.

GraphQL Keywords 및 예시

Query: 저장된 데이터 가져오기
Mutation: 저장된 데이터 수정하기
Create: 새로운 데이터 생성
Update: 기존의 데이터 수정
Delete: 기존의 데이터 삭제
Subscription: 특정 이벤트가 발생 시 서버가 대응하는 데이터를 실시간으로 클라이언트에게 전송

Query-저장된 데이터 가져오기

1. field

//실행
{
  hero {
    name
    # 이런 식으로 GraphQL 내에서 주석도 작성할 수 있다.
    friends {
      name
    }
  }
}
//결과
{
  "data": {
    "hero": {
      "name": "R2-D2",
      "friends": [
        {
          "name": "Luke Skywalker"
        },
        {
          "name": "Han Solo"
        },
        {
          "name": "Leia Organa"
        }
      ]
    }
  }
}

2. 전달인자(Arguments)
필드에 인수를 전달하는 부분을 추가하면 원하는 데이터만 받아올 수 있다.

{//id가 1000인 human의 name과 height를 쿼리
  human(id: "1000") {
    name
    height
  }
}
//쿼리 결과
{
  "data": {
    "human": {
      "name": "Luke Skywalker",
      "height": 1.72
    }
  }
}

3. 별명(Aliases)
필드 이름을 중복해서 사용할 수 없으므로, 필드 이름을 중복으로 사용해야 할 때는 별명을 붙여서 쿼리를 해준다.

//이런식으로 hero필드 앞에 별명을 붙여준다.
{
  empireHero: hero(episode: EMPIRE) {
    name
  }
  jediHero: hero(episode: JEDI) {
    name
  }
}
//쿼리 결과
{
  "data": {
    "empireHero": {
      "name": "Luke Skywalker"
    },
    "jediHero": {
      "name": "R2-D2"
    }
  }
}

4. 오퍼레이션 네임
여태 쿼리와 쿼리 네임을 모두 생략하는 축약형 구문을 사용했지만, 실제 앱에서는 코드를 모호하지 않게 작성하는 것이 중요하다. query는 오퍼레이션 타입으로, query 뿐만 아니라 mutation, subscription, describes 등이 있다. 쿼리를 약식으로 작성하지 않는 한 이런 오퍼레이션 타입은 반드시 필요하다.

//이런식으로 query keyword와 query name을 작성한다.
query HeroNameAndFriends {
  hero {
    name
    friends {
      name
    }
  }
}

5. 변수(Variables)
실제 앱을 사용할 때는 고정된 인수를 받는 것보다 동적으로 인수를 받아 쿼리하는 경우가 대다수이다. 변수는 그런 인수들을 동적으로 받고 싶을 때 사용한다.

//변수를 사용한 쿼리 예시
query HeroNameAndFriends($episode: Episode) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}

Mutation

저장된 데이터 수정하기 GraphQL은 mutation이라는 키워드를 사용하여 서버 측 데이터를 수정한다.

mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}

스키마/타입(Schema/Type)

스키마의 가장 기본적인 구성 요소는 서비스에서 가져올 수 있는 객체의 종류, 그리고 포함하는 필드를 나타내는 객체 유형이다.

type Character {
  name: String!
  appearsIn: [Episode!]!
}

1. Character는 GraphQL 객체 타입이며 필드가 있는 타입임을 의미한다. 스키마에 있는 대부분의 타입은 객체 타입이다.

2. name 과 appearIn 은 GraphQL 쿼리의 Character 타입 어디서든 사용할 수 있는 필드다.

3. String은 내장된 스칼라 타입 중 하나로, 단일 스칼라 객체로 확인되는 유형이며 쿼리에서 하위 선택을 가질 수 없다. 스칼라 타입에는 ID, Int도 있다.

4. !가 붙는다면 이 필드는 반드시 값이 들어온다는 의미다. 반드시 값을 받을 수 있을 것이란 예상을 할 수 있습니다.

5. [ ]는 배열을 의미한다. 여기서는 ! 이 뒤에 붙어 있어 null 값을 허용하지 않으므로 항상 0개 이상의 요소를 포함한 배열을 기대할 수 있게 된다.

리졸버(Resolver)

위와 같이 스키마를 정의하면 그 스키마 필드에 사용되는 함수의 실제 행동을 Resolver에서 정의한다. 또한 이러한 함수들이 모여 있기 때문에 보통 Resolvers라 부른다.

//GraphQL에서는 데이터를 가져오는 구체적인 과정을 직접 구현해야 하는데 
이와 같은 작업(e.g. 데이터베이스 쿼리, 원격 API 요청)을 Resolver가 담당하게 됩니다.
const db = require("./../db")
const resolvers = {
 Query: { // **Query :** 저장된 데이터 가져오기 (REST 에 GET 과 비슷합니다.)
		getUser: async (_, { email, pw }) => {
			db.findOne({
				where: { email, pw }
			}) ... // 실제 디비에서 데이터를 가져오는 로직을 작성합니다. 
			...
		}
 },
 Mutation: { // **Mutation :** 저장된 데이터 수정하기 ( Create , Update , Delete )
		createUser: async (_, { email, pw, name }) => {
			...
		}
 }
 Subscription: { // **Subscription :** 실시간 업데이트
   newUser: async () => {
     ...
		}
 }
};

0개의 댓글

Powered by GraphCDN, the GraphQL CDN