GraphQL 스터디

GraphQL 쿼리어

막이86 2023. 11. 10. 16:21
728x90

웹 앱 API 개발을 위한 GraphQL 을 요약한 내용입니다.

SQL(구조화된 쿼리 언어)는 도메인에 종속된 언어로, 데이터베이스안의 데이터에 ㅓㅂ근하거나, 데이터를 관리하거나 조작하는데 사용합니다.

명령어 한번으로 복수의 레코드에 접근한다는 아이디어는 SQL에서 나온 것입니다.

SQL을 사용한다면 ID 뿐만 아니라 다른 키 값을 사용해 레코드에 접근할 수 있습니다.

  • GraphQL은 쿼리 데이터베이스용으로 만들어진 개념을 가져다가 인터넷에 적용해 만들어진 것입니다.
  • GraphQL 쿼리 하나로 여지저기 흩어져 있는 데이터를 한데 모아 받습니다.
  • SQL처럼 GraphQL 쿼리도 데이터를 변경하거나 삭제할 때 사용합니다.
  • SQL의 QL과 GraphQL의 QL은 둘다 마찬가지로 쿼리 언어(Query Language)라는 뜻입니다.
  • GraphQL과 SQL은 둘다 쿼리 언어이기는 하나, 사용 환경이 완전히 다릅니다.
    • SQL 쿼리는 데이터베이스로 보내는 반면, GraphQL 쿼리는 API로 보냅니다.
    • SQL 데이터는 데이터 테이블 안에 저장되어 있으나 GraphQL 데이터는 저장 환경을 가리지 않습니다.
    • 단일 데이터베이스, 여러 개의 데이터베이스, 파일 시스템, REST API, 웹소켓(WebSocket), 심지어 또 다른 GraphQL API로부터 데이터를 받아 올 수 있습니다.
    • SQL은 데이터베이스용 쿼리 언어이고, GraphQL은 인터넷용 쿼리 언어입니다.
  • GraphQL과 SQL의 구문은 매우 다릅니다.
    • GraphQL에서는 SELECT 대신 Query를 사용해 데이터 요청을 보냅니다.
    • INSERT, UPDATE, DELETE를 사용하는 대신 GraphQL은 Mutation 이라는 데이터 타입을 가지고 데이터를 조작합니다.
    • GraphQL은 인터넷에서 사용될 요량으로 만들어졌기 때문에 Subscription 타입도 존재합니다.
  • GraphQL은 명세에 따라 표준화되어 있습니다. (프로그래밍 언어에 종속되어 있지 않습니다.)
  • 쿼리는 단순한 문자열로, POST 요청 본문에 담겨 GraphQL 엔드포인트로 보내집니다.
{
	allLifts {
		name
	}
}
  • 데이터를 수정하려면 뮤테이션(mutation)을 사용하며 됩니다.
mutation {
	setLiftStatus(id: "panorama" status: OPEN) {
		name
		status
	}
}

3.1 GraphQL API 툴

  • GraphQL 쿼리를 작성하여 GraphQL 엔드포인트로 보내고, 돌아오는 JSON 응답 분석 작업을 할 수 있습니다.
  • GraphiQL과 GraphQL플레이크라운드가 널리 사용되는 툴입니다.

3.1.1 GraphiQL

  • GraphiQL은 브라우저 안에서 사용하는 IDE(통합 개발 환경)으로 페이스북에서 만들었습니다.
  • 구문 하이라이트 기능, 코드 자동 완성 기능 및 에러경고 기능이 지원됩니다.
  • 브라우저에서 바로 쿼리문을 실행하고 결과를 받아 보는 기능도 있습니다.
  • 다수의 공용 API는 실제 데이터에 대한 쿼리를 작성할 수 있도록 GraphiQL 인터페이스를 함께 제공합니다.
  • Query, Mutation, Subscription을 사용해볼 수 있습니다.

3.1.2 GraphQL 플레이그라운드

  • GraphQL API 탐색 용도로 사용할 수 있는 또 다른 툴입니다.
  • 프리스마(Prisma, 데이터베이스 툴) 개발자들이 만들었습니다.
  • 가장 손쉽게 사용해 보려면 브라우저에소 https://www.graphqlbin.com/v2/new 에 접속하면 됩니다.
  • 여러분이 만든 bin의 링크를 다른 사람에게 공유할 수 있습니다.
  • 데스크톱 버전도 잇습니다.
    • Homebrew를 사용해 설치 할 수 있습니다.
    • brew cask install graphql-playground

3.1.3 공용 GraphQL API

  • GraphQL에 익숙해질 수 있는 좋은 방법중 하나는 바로 공용 API를 사용해 쿼리 작성 연습을 하는 것입니다.
  • 일부 회사와 단체에서는 공용 데이터 쿼리에 사용할 수 있는 GraphiQL 인터페이스를 제공하고 있습니다.
  • SWAPI(스타워즈 API)https://graphql.github.io/swapi-graphql
  • GraphQL로 SWAPI REST API 래퍼(wrapper)를 페이스북에서 만들었습니다.
  • GitHub API데이터를 가지고 작업해 보려면 깃허브계정으로 로그인해야 합니다.
  • https://developer.github.com/v4/explorer/
  • 대규모 공용 GraphQL API 중 하나이며, 깃허브에 있는 실시간 데이터에 대해 쿼리를 날려보고 view에 뮤테이션을 가할 수 있는 기능을 제공합니다.
  • Yelp옐프 개발자 계정이 있어야 옐프 API를 통한 데이터 조작이 가능합니다.
  • https://www.yelp.com/developers/graphql/guides/intro
  • 옐프에서는 GraphiQL로 쿼리를 작성할 수 있는 GraphQL API를 제공해줍니다.

3.2 GraphQL 쿼리

  • 스노투스(Snowtooth) 산에는 가상의 스키 리조트가 있습니다. 스키 리조트 데이터를 가지고 실습해 보겠습니다. (http://snowtooth.moonhighway.com/)
  • 쿼리 작업으로 API에 데이터를 요청할 수 있습니다. 쿼리 안에는 GraphQL 서버에서 받고 싶은 데이터를 써 넣습니다.
  • 쿼리를 보낼 때는 요청 데이터를 필드로 적어 넣습니다. 필드는 서버에서 받아 오는 JSON 응답 데이터의 필드와 일치합니다.
query {
  allLifts {
    name
    status
  }
}

<aside> 💡 정상적인 쿼리를 보내면 data 키가 들어있는 JSON 문서가 응답으로 돌아옵니다. 비정상적인 쿼리에는 응답으로 error 키가 들어 있는 JSON 문서가 돌아옵니다. 이 키의 값으로는 에러에 대한 세부적인 내용이 들어갑니다. data와 error 키가 응답 겍체에 동시에 포함된 경우도 있습니다.

</aside>

  • 쿼리 문서에는 쿼리를 여러 개 추가할 수도 있습니다. 그러나 작업은 한번에 한 쿼리에 대해서만 이루어집니다.
query lifts {
  allLifts {
    name
    status
  }
}

query trails {
  allTrails {
    name
    difficulty
  }
}
  • 한 번에 모두 받아 오고 싶으면 같은 쿼리 안에 전부 써 주면 됩니다.
    • 쿼리 한 번에 여러 종류의 데이터를 모두 받을 수 있습니다.
query liftsAndTrails {
  liftCount(status: OPEN)
  allLifts {
    name
    status
  } 
  allTrails {
    name
    difficulty
  }
}
  • Query는 GraphQL 타입입니다. 이는 루트 타입이라고도 하는데, 타입 하나가 곧 하나의 작업을 수행하며, 작업이 곧 쿼리 문서의 루트를 의미하기 때문입니다.
  • 쿼리 작성 시 중요한 것은 필요한 필드만 요청하는 것입니다.
  • 쿼리를 작성할 때는 필요한 필드를 중괄호로 감쌉니다. 이 중괄호로 묶인 블록을 **셀렉션 세트(selection set)**라고 부릅니다.
  • 응답 객체의 필드명을 다르게 받고 싶다면, 아래와 같은 쿼리 안의 필드명에 별칭을 부여하면 됩니다.
query liftsAndTrails {
  open: liftCount(status: OPEN)
  chairlifts: allLifts {
    name
    status
  }
  skiSlopes: allTrails {
    name
    difficulty
  }
}
  • 쿼리 결과에 대한 필터링 작업을 하고 싶다면 **쿼리 인자(query arguments)**를 넘기면 됩니다.
    • 쿼리 필드와 관련 있는 키-값 쌍을 하나 이상 인자로 넣을 수 있습니다.
query closeLifts {
  allLifts(status: CLOSED) {
    name
    status
  }
}
  • 리프트의 아이디를 사용해 해당 리프트를 선택할 수 있습니다.
query jazzCatStatus {
  Lift(id: "jazz-cat") {
    name
    status
    night
    elevationGain
  }
}

3.2.1 엣지와 연결

  • 쿼리어에서 필드는 스칼라(scalar) 타입과 객체(object) 타입 둘 중 하나에 속하게 됩니다.
  • 다섯 가지 스칼라 타입이 내장 되어 있습니다.
    • 정수(Int), 실수(Float), 문자열(String), 불(Boolean), 고유 식별자 (ID)
    • 정수와 실수 타입은 JSON 숫자 타입 데이터를 돌려줍니다.
    • 문자열과 ID 타입은 JSON 문자열 데이터를 돌려줍니다.
    • ID 타입은 반드시 유일한 문자열을 반환하도록 되어 있습니다.
  • 객체 타입은 스키마에 정의한 필드를 그룹으로 묶어 둔 것입니다.
  • 객체의 세부 정보를 얻어내는 쿼리를 작성해 이들 객체를 서로 연결할 수 있습니다.
  • 특정 리프트에서 접근할 수 있는 코스 목록들 받아 보고 싶다면 다음과 같은 코드를 작성합니다.
query jazzCatStatus {
  Lift(id: "jazz-cat") {
		capacity
    trailAccess {
      name
      difficulty
    }
  }
}
  • capacity 필드는 스칼라 타입 데이터 입니다.
  • trailaccess 필드는 Trail 타입(객체 타입)입니다.
  • trailAccess는 Lift 타입 안에 있는 필드여서 API에서는 부모 객체인 재즈 캣 Lift의 정보를 활용해 특정 코스만 필터링합니다.
  • 리프트와 코스 데이터 타입 사이의 일대다(one-to-many) 연결 관계에 대한 쿼리입니다.
  • Lift 노드에서 그래프 횡단을 시작한다면 trailAcess 엣지로 연결된 Trail 노드를 하나 이상 거치게 됩니다.
  • 그래프가 방향성이 없다면 Trail 노드에서 Lift 노드로 거슬러 올라갈 수도 있어야 합니다.
query liftToAccessTrail {
  Trail(id: "dance-fight") {
    groomed
    accessedByLifts {
      name
      capacity
    }
  }
}
  • dance-fight라는 Trail을 타깃으로 정햇습니다.
  • groomed 필드는 불 스칼라 타입 데이터를 반환해서, 이 값을 보면 dance-fight 코스까지 데려다주는 리프트에 대한 정보를 반환해 줍니다.

3.2.2 프래그먼트

  • 쿼리 안에는 각종 작업에 대한 정의와 프래그먼트에 대한 정의가 들어갈 수 있습니다.
  • 프래그먼트는 셀렉션 세트의 일종이며, 여러번 재사용할 수 잇습니다.
query {
  Lift(id: "jazz-cat") {
    name
    status
    capacity
    night
    elevationGain
    trailAccess {
      name
      difficulty
    }
  }
  Trail(id: "river-run") {
    name
    difficulty
    accessedByLifts {
      name
      status
      capacity
      night
      elevationGain
    }
  }
}
  • jazz-cat 리프트와 river-run 코스에 대한 정보를 요청하는 쿼리입니다.
  • Lift의 셀렉션 세트 안에는 name, status, capacity, night, elevationGain이 들어 있습니다.
  • river-run 코스에서 얻고자하는 필드와 Lift 타입에서 필요한 필드 중에서 중복되는 것이 있습니다.
  • 이럴 때 프래그먼트로 쿼리에서 중복되는 부분을 줄일 수 있습니다.
fragment liftInfo on Lift {
  name
  status
  capacity
  night
  elevationGain
}

query {
  Lift(id: "jazz-cat") {
    ...liftInfo
    trailAccess {
      name
      difficulty
    }
  }
  Trail(id: "river-run") {
    name
    difficulty
    accessedByLifts {
      ...liftInfo
    }
  }
}
  • fragment 식별자를 사용하여 만듭니다.
  • 프래그먼트는 특정 타입에 대한 셀렉션 세트이므로, 어떤 타입에 대한 프래그먼트인지 정의에 꼭 써줘야 합니다.
  • fragment를 liftInfo라고 정의 하였습니다.
  • Lift 타입에 대한 셀렉션 세트입니다.
  • liftInfo 프래그먼트 필드를 다른 셀렉션 세트에 추가하려면 fragment 이름 앞에 점 세 개를 찍어 주면 됩니다.
  • 자바스크립트의 spread 연산자와 비슷해 보이는 구문입니다.
  • liftInfo 프래그먼트를 Trail안에 넣는 것은 불가능합니다.
fragment liftInfo on Lift {
  name
  status
  capacity
  night
  elevationGain
}

fragment tailInfo on Trail {
  name
  difficulty
  accessedByLifts {
    ...liftInfo
  }
}

query {
  Lift(id: "jazz-cat") {
    ...liftInfo
    trailAccess {
      ...tailInfo
    }
  }
  Trail(id: "river-run") {
    ...tailInfo
    groomed
    trees
    night
  }
}
  • trailInfo 프래그먼트를 만들어서 쿼리 안에 두 군데에서 사용했습니다.
  • 코스까지 운행하는 리프트 정보를 얻어 오고자 trailInfo 프래그먼트 안에서 liftInfo 프래그먼트를 사용했습니다.
  • 프래그먼트는 원하는 만큼 얼마든지 많이 만들어서 여기저기 사용할 수 있습니다.
  • 같은 타입에 대한 프래그먼트를 여러 개 쓸 수도 있습니다.
query {
  allTrails {
    ...trailStatus
    ...trailDetails
  }
}

fragment trailStatus on Trail {
  name
  status
}

fragment trailDetails on Trail {
  groomed
  trees
  night
}
  • 한차례의 수정으로 여러 쿼리의 셀렉션 세트를 한 번에 바꿀 수 있다는 것이 프래그먼트의 장점입니다.

유니언 타입

  • 객체 리스트를 반환하는 방법은 이미 봤는데, 이들을 모두 한 가지 타입만 리스트로 반환합니다.
  • 타입 여러 개를 한번에 리스트에 담아 반환하고 싶다면 **유니언 타입(union type)**을 만들면 됩니다.
  • 두 가지 타입을 하나의 집합으로 묶는 것입니다.
  • 대학생을 타깃으로 한 일정 앱을 만들고 있다고 가졍해 봅시다. (https://www.graphqlbin.com/v2/ANgjtr, https://github.com/gratiaa/union_types_example)
  • 일정에는 Workout과 StudyGroup 이벤트를 추가할 예정입니다.
query schedule {
  agenda { 
  	... on Workout {
      name
      reps
    }
    ...on StudyGroup {
      name
      subject
      students
    }
  }
}
  • AgendaItem 이 유니언 타입으로 나옵니다.
  • 여러 타입을 한 번에 반환한다는 뜻입니다.
  • AgendaItem은 Workout 또는 StudyGroup 타입을 반환합니다.
  • ... on Workout 은 인라인 프래그먼트(inline fragment) 입니다.
  • 인라인 프래그먼트는 이름이 없습니다.
  • 이름이 붙는 프래그먼트를 사용해 유니언 타입 쿼리를 작성할 수 있습니다.
query {
  agenda {
    ...workout
    ...study
  }
}

fragment workout on Workout {
  name
  reps
}

fragment study on StudyGroup {
  name
  subject
  students
}

인터페이스(interface)

  • 인터페이스(interface)는 필드 하나로 객체 타입을 여러 개 반환할 때 사용합니다.
  • 추상적인 타입이며, 유사한 객체 타입을 만들 때 구현해야하는 필드 리스트를 모아둔 것입니다.
  • 인터페이스를 가지고 타입을 구현할 때는 인터페이스에 정의된 필드는 모두 넣어야하고, 몇 가지 고유한 필드도 추가로 넣을 수 있습니다.
  • 예제 실습 (https://github.com/gratiaa/interface_example)
  • GraphQL 플레이그라운드 문서에 따르자면 agenda 필드의 항목은 ScheduleItem 인터페이스를 반환한다고 합니다.
  • name, start 시간, end 시간 필드가 정의되어 있습니다.
  • StdudyGroup과 Workout 타입이 이 인터페이스를 바탕으로 만들어졌다고 문서에 나와 있습니다.
const typeDefs = `
  interface ScheduleItem {
    name: String!
    start: Int
    end: Int
  }
  type StudyGroup implements ScheduleItem {
      name: String!
      start: Int
      end: Int
      subject: String!
      students: Int!
  }
  type Workout implements ScheduleItem {
      name: String!
      start: Int
      end: Int
      reps: Int!
  }
  type Query {
      agenda: [ScheduleItem!]!
  }
`;
query {
  agenda {
    name
    start
    end
  }
}
  • 프래그먼트를 사용하면 특정 객체 타입이 반환될 때, 필드가 더 들어갈 수 있게 인터페이스 관련 쿼리를 작성할 수 있습니다.
query {
  agenda {
    name
    start
    end
    ...on Workout {
      reps
    }
  }
}
  • schedule 쿼리를 수정하여 ScheduleItem이 Workout일 때 reps 필드를 추가로 요청하도록 했습니다.

3.3 뮤테이션

  • 데이터를 새로 쓰려면 뮤테이션(mutation)해야 합니다.
  • 데이터를 뮤테이션 하는 방법은 쿼리를 작성하는 방법과 비슷하며, 이름을 붙여야 합니다.
  • 객체 타입이나 스칼라 타입의 반환 값을 가지는 셀렉션 세트가 들어갑니다.
  • 다만 쿼리와 다른점을 데이터를 뮤테이션 하면 백엔드데이터에 영향을 준다는 것입니다.
  • 위험한 뮤테이션의 예를 들자면 다음과 같습니다.
  • 데이터를 모두 지워버리는 위력을 지닌 deleteAllData라는 필드를 사용했습니다.
mutation burnItDown {
  deleteAllData
}
  • Mutation은 루트 객체 타입입니다.
  • API 스키마에느 뮤테이션 타입에서 사용할 수 있는 필드를 정의해 둡니다.
  • 삭제할지 여부는 API를 만들 때 정할 수 있는ㄷ, 이에 대해서는 5장에서 다루도록 하겠습니다.
  • 새로운 음악 데이터를 생성하는 예제입니다.
mutation createSong {
  addSong(title: "No Scrubs", numberOne: true, performerName: "TLC") {
    id
    title
    numberOne
  }
}
  • title, numberOne 여부, performerName이 뮤테이션에 인자로 넘어가므로 여기서 만들어진 새 음악 데이터가 데이터베이스에 추가될 것임을 예상할 수 있습니다.
  • 만약 뮤테이션 필드가 객체를 반환하도록 만들려면 셀렉션 세트를 추가해야 합니다.
  • 예제의 경우 음악 데이터 생성이 완료되면 뮤테이션은 Song 타입의 객체를 반환합니다.
  • 그러면 뮤테이션 실행이 완료된 후 id, title, 신곡의 numberOne 여부를 받아 볼 수 있습니다.
  • 작업이 무언가 잘못되면 새로운 Song 객체 대신에 에러가 담긴 JSON 응답이 반환됩니다.
  • 뮤테이션으로 기존 데이터 변경도 가능합니다.
mutation closeLift {
  setLiftStatus(id: "jazz-cat", status: CLOSED) {
    name
    status
  }
}
  • jazz-cat 리프트를 개시에서 닫힘 상태로 바꾸는 뮤테이션입니다.
  • 뮤테이션 작업이 끝나면, 셀렉션 세트에 들어가서 변경된 Lift 타입의 관련 필드를 받을 수 있습니다.

3.3.1 쿼리 변수 사용하기

  • 지금까지 새 문자열 값을 뮤테이션의 인자로 넘겨 데이터 변경 작업을 했습니다.
  • 변수를 사용해서도 같은 결과를 얻을 수 있습니다.
  • 쿼리에 있는 정적(static) 값을 변수로 대체하여 계속해서 바꾸는 동적인(dynamic) 값을 넣을 수도 있습니다.
  • GraphQL은 언제나 변수명 앞에 $문자가 붙습니다.
mutation createSong($title:String! $numberOne:Int $by:String!) {
  addSong(title: $title, numberOne:$numberOne, performerName:$by) {
    id
    title
    numberOne
  }
}
  • 정적 값을 빼고 $변수를 그자리에 썼습니다.
  • 그리고 뮤테이션이 $변수를 받을 수 있다고 했습니다.
  • 플레이그라운드를 보면 쿼리 변수용 창이 따로 있습니다. (하단 Query Variables 클릭)
{
  "title": "No Scrube",
  "numberOne": true,
  "by": "TLC"
  
}
  • 변수인자는 데이터를 보낼 때 굉장히 유용합니다.
  • 테스트할 때 뮤테이션을 깔끔하게 관리하는 데 도움이 될 뿐만아니라, 클라이언트 인터페이스와 연결하는 경우에도 매우 유용하게 사용할 수 있습니다.

3.4 서브스크립션

  • 서브스크립션(subscription) 구독은 GraphQL에서 수행할 수 있는 세번째 타입입니다.
  • 서버에서 푸시 중인 업데이트의 내역을 실시간으로 클라이언트에서 받아야 할 때가 있습니다.
  • 데이터 서브스크립션을 하면 GraphQL API를 사용해 실시간 데이터 변경 내용을 받을 수 있습니다.
  • 이 기능은 실제 페이스북에서 사용되던 것을 바탕으로 만들어졌습니다.
  • 뮤테이션과 쿼리처럼 서브스크립션도 루투 타입이 있습니다.
  • 클라이언트에서 받을 수 있는 데이터변경 내용은 subscription 타입 아래 필드로 정의되어 API 스키마에 들어갑니다.
subscription {
  liftStatusChange {
    name
    capacity
    status
  }
}
  • 플레이그라운드의 재생 버튼을 눌러도 바로 데이터가 반환되지는 않습니다.
  • 플레이그라운드에서 서브스크립션을 실행한 상태라면 새로운 탭에서 실행을 해야합니다.
mutation closeLift {
  setLiftStatus(id: "astra-express", status: OPEN) {
    name
    status
  }
}
  • 뮤테이션을 실행하면 astra-express의 상태 값이 변경되므로 이 리프트의 name, capacity, status값이 서브스크립션에 전송됩니다.
  • 맨 마지막으로 변경한 리프트이며 해당 리프트의 상태가 받는 쪽으로 푸시됩니다.
{
  "data": {
    "liftStatusChange": {
      "name": "Astra Express",
      "capacity": 3,
      "status": "HOLD"
    }
  }
}
  • 쿼리와 퓨테이션과는 달리, 서브스크립션은 일회성으로 끝나지 않고 계속 열려 있게 됩니다.
  • 리프트의 상태에 변경이 생길 때마다 받는 쪽으로 새로운 데이터가 푸시 됩니다.
  • 상태 변경 알림을 그만 받아 보고 싶으면 이를 해지해야합니다.

3.5 인트로스펙션(introspection)

  • 인트로스펙션은 GraphQL에서 제공하는 강력한 기능으로, 이를 사용하면 현재 API 스키마의 세부 사항에 관한 쿼리를 작성 할 수 있습니다.
  • 이 덕분에 GraphQL 플레이그라운드 인터페이스에서 솜씨 좋게 GraphQL 문서를 보여 줄 수 있는 것입니다.
  • GraphQL API 인트로스펙션 쿼리를 사용하면 주어진 API 스키마를 통해 어떤 데이터를 반환받을 수 있는지 조사할 수 있습니다.
  • 예를 들어 스노투스에서 어떤 GraphQL 타입을 사용할 수 있는지 알고 싶다면 __schema 쿼리를 실행하여 정보를 받습니다.
  • 이 쿼리를 실행하면 API에서 사용할 수 있는 타입은 모두 볼 수 있습니다.
    • 루트 타입, 커스텀 타입, 심지어 스칼라 타입까지 나옵니다.
query {
  __schema {
    types {
      name
      description
    }
  }
}
  • 특정 타입에 관한 세부 사항만 보고 싶다면 __type 쿼리에 타입명을 인자로 넘기고 작성해 실행하면 됩니다.
  • 이 쿼리로 Lift 타입 관련 쿼리를 작성할 때 넣을 수 있는 필드 정보를 받아 볼 수 있습니다.
query liftDetails{
  __type(name: "Lift") {
    name
    fields {
      name
      description
      type {
        name
      }
    }
  }
}
  • GraphQL API를 처음 사용할 때는 루트 타입에서 사용할 수 있는 필드가 무엇이 있는지 알아보는 편이 좋습니다.
query roots {
  __schema {
    queryType {
      ...typeFields
    }
    mutationType {
      ...typeFields
    }
    subscriptionType {
      ...typeFields
    }
  }
}

fragment typeFields on __Type {
  name
  fields {
    name
  }
}
  • 인트로스펙션 쿼리문은 GraphQL 쿼리 언어의 규칙을 따릅니다. 따라서 플래그먼트를 사용하여 쿼리문 안의 중복되는 부분을 없앨 수 잇습니다.

3.6 추상 구문 트리(abstract syntax tree)

  • 문자열은 추상 구문 트리로 파싱되어 명령 실행 전에 유효성 검사를 거칩니다.
  • 추상 구문 트리 줄여서 AST는 계층 구조를 지닌 객체로 쿼리를 표현하는데 사용합니다.
  • AST는 계층 구조를 지닌 객체로 쿼리를 표현하는데 사용합니다.
  • AST는 객체이며 GraphQL 쿼리에 관한 부가 정보 필드가 중첩된 구조로 들어갑니다.

어휘화(lexing), 어휘 분석(lexical analysis)

  • 첫 번째로 거치는 작업은 문자열을 더 작은 여러 개의 조각으로 쪼개어 분석하는 작업입니다.
  • 키워드, 인자, 심지어 괄호나 콜론까지 하나하나 독립적인 토큰으로 분해됩니다.
  • 쿼리에는 최소한 정의가 하나이상 들어가며, 여러 개의 리스트로 들어 있을 수도 있습니다.
  • 정의는 두 타입이 있는데, 하나는 OperationDefinition 이고 다른 하나는 FragmnetDefinition 입니다.
  • 다음 예시는 세가지의 정의가 들어 있는 문서 입니다.
    • 데이터 작업 정의가 두개, 플래그먼트 정의는 한개 들어 있습니다.
    query jazzCatStatus {
      Lift(id: "jazz-cat") {
        name
        night
        elevationGain
        trailAccess {
          name
          difficulty
        }
      }
    }
    
    mutation closeLift($lift: ID!) {
      setLiftStatus(id: $lift, status: CLOSED) {
        ...liftStatus
      }
    }
    
    fragment liftStatus on Lift {
      name
      status
    }
    
    • OperationDefinition에는 mutation, query, subscription 작업 타입만 들어갈 수 있습니다.
    • 각 작업 정의에는 OperationType과 SelectionSet가 들어갑니다.
    • 각 작업 정의에는 중괄호 안에 SelectionSet가 들어갑니다.
      • 여기 안에 들어가는 필드가 인자를 받아 쿼리 작업이 진행되는 실제 필드입니다.
      • 에를 들어 Lift 필드는 jazzCatStatus 쿼리의 SelectionSet이고, SetLiftStatus 필드는 closeLift 뮤테이션의 SelectionSet 입니다.
    • SelectionSet는 중첩시킬 수 있는데, jazzCatStatus 쿼리에는 SelectionSet가 세 번 중첩되어 있습니다.
    • 쿼리 바로 빝에 들어간 SelectionSet에는 name, night, elevationGain, trailAccess 필드가 들어 있습니다.
    • trailAccess 필드 밑에는 또 다른 SelectionSet가 들어 있습니다.
    • AST를 횡단하며 GraphQL 언어와 현재 스키마와 비교해 유효성 검사를 실시합니다.
    • 쿼리어 구문에 오류가 없고 요청에서 요구한대로 스미카에 필드와 타입이 다 들어 있다면 작업이 실행됩니다.
    • 그렇지 않다면 에러가 반환됩니다.
728x90

'GraphQL 스터디' 카테고리의 다른 글

GraphQL API 만들기  (0) 2023.11.10
스키마 설계하기  (0) 2023.11.10
GraphQL에 오신 것을 환영합니다.  (0) 2023.11.10