GraphQL 키워드

Query

  • 저장된 데이터 가져오기 (REST의 GET에 해당)
  • GraphQL은 거의 Query를 위한 언어...

Mutation

  • 저장된 데이터 수정하기
    • Create: 새로운 데이터 생성
    • Update: 기존의 데이터 수정
    • Delete: 기존의 데이터 삭제

Subscription (구독)

  • 특정 이벤트가 발생 시 서버가 대응하는 데이터를 실시간으로 클라이언트에게 전송 (업데이트)
  • 전통적인 Client(요청)-Server(응답) 모델을 따르는 Query 또는 Mutation과 달리, 발행/구독(pub/sub) 모델을 따름.

GraphQL 구조

쿼리 (Query, 데이터 조회)

1) 쿼리(요청)와 결과는 정확하게 같은 모양이다.

✅ hero의 name을 요청하는 쿼리 ✅

{
  hero {
    name
  }
}

👉🏽 hero의 name을 요청한 쿼리의 결과

{
  "data": {
    "hero": {
      "name": "R2-D2"
    }
  }
}
  • 필드를 중첩해 쿼리하는 것도 가능하다.
    (원하는 항목 여러 개를 한꺼번에 쿼리)

✅ hero의 name과 hero의 friends의 name을 요청한 쿼리 ✅

{
  hero {
    name
    # 이런 식으로 GraphQL 내에서 주석도 작성할 수 있습니다.
    friends {
      name
    }
  }
}

👉🏽 hero의 name과 hero의 friends의 name을 요청한 쿼리의 결과

{
  "data": {
    "hero": {
      "name": "R2-D2",
      "friends": [
        {
          "name": "Luke Skywalker"
        },
        {
          "name": "Han Solo"
        },
        {
          "name": "Leia Organa"
        }
      ]
    }
  }
}

1. 필드(field)

  • 쿼리를 통해 요구하는 항목
{
  hero {
    name
  }
}
  • hero, name은 필드

2. 전달인자(Arguments)

  • 필드에 전달하는 인수
  • 해당 필드 중 원하는 데이터만 지정할 때 사용
{
  human(id: "1000") {
    name
    height
  }
}
  • id가 1000인 human에 대해서만 쿼리(요청)

3. 별명(Aliases)

  • 필드 이름을 중복해서 사용해아 할 경우, 필드 앞에 별명을 붙여서 쿼리해야 한다.
  • 쿼리 결과는 중복된 필드 대신 별명으로 받아볼 수 있다.

❌ 잘못된 예 ❌

{
  hero(episode: EMPIRE) {
    name
  }
  hero(episode: JEDI) {
    name
  }
}
  • 이런 식으로 필드를 중복해 쿼리할 수 없다.

✅ 별명을 사용한 쿼리 ✅

{
  empireHero: hero(episode: EMPIRE) {
    name
  }
  jediHero: hero(episode: JEDI) {
    name
}

👉🏽 별명을 사용한 쿼리의 결과

{
  "data": {
    "empireHero": { // 필드 대신 별명으로 결과를 받아볼 수 있다. 
      "name": "Luke Skywalker"
    },
    "jediHero": {
      "name": "R2-D2"
    }
  }
}

4. 오퍼레이션 네임(Operation name)

  • 쿼리(요청)하는 내용을 나타내는 이름
  • 오퍼레이션 타입에 맞고 요청하는 데이터가 무엇인지 잘 나타내는 이름으로 임의로 정하면 된다.
  • 오퍼레이션 네임 앞에 오퍼레이션 타입인 query를 붙여준다.
  • 쿼리를 약식(축약형)으로 작성하지 않는 한 오퍼레이션 타입과 오퍼레이션 네임을 꼭 작성해준다.

참고: 오퍼레이션 타입(Operation type)

  • query 외에도 mutation, subscription, describes 등이 있다.
query HeroNameAndFriends {
  hero {
    name
    friends {
      name
    }
  }
}
  • 오퍼레이션 타입 : query
  • 오퍼레이션 네임 : HeroNameAndFriends

5. 변수(Variables)

  • 인수를 동적으로 받고 싶을 때 변수를 사용한다.

변수 사용법

  • 사용할 변수들을 오퍼레이션 네임 옆에 $변수 이름 : 타입 형태로 정의한다.
  • 인수의 값으로 $변수 이름을 넣어준다.
  • $변수 이름 : 타입에서 타입 뒤에 !가 붙는다면 해당 변수는 반드시 해당 타입이어야 한다는 뜻이다.
query HeroNameAndFriends($episode: Episode) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}

뮤테이션(mutation, 데이터 수정)

  • GraphQL은 데이터를 가져오는 데에 중점을 두고 있지만 서버측 데이터를 수정하기도 한다.
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}

[백엔드] 스키마/타입(Schema/Type)

  • 스키마 : 데이터 타입의 집합
  • 타입 : 스키마의 핵심 단위. 커스텀 객체.

타입(Type) 예시

type Character {
  name: String!
  appearsIn: [Episode!]!
}
  • Character는 GraphQL의 객체 타입. (앱의 데이터를 상징)
  • name, appearsInCharacter 타입의 필드(field).
  • String은 GraphQL에 내장된 스칼라 타입(기본 타입)
  • !가 붙는다면 해당 필드는 nullable하지 않고 반드시 값이 들어온다는 의미. (해당 필드에 대한 값을 반드시 받을 수 있을 것이란 예상을 할 수 있다.
  • [ ]는 배열을 의미다. 배열에도 !가 붙을 수 있다. (이 경우 항상 0개 이상의 요소를 포함한 배열을 기대할 수 있다)

[백엔드] 리졸버(Resolver)

  • 요청에 대한 응답을 결정해주는 함수
  • 클라이언트가 보낸 쿼리의 타입(Query, Mutation, Subscription)에 따른 로직(함수)을 작성
  • 각 타입에 따른 로직(함수)들이 모여있는 것을 리졸버라고 부른다.
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개의 댓글