{
hero {
name
}
}
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
쿼리와 결과가 정확히 동일한 형태인 것을 볼 수 있습니다.
이것이 GraphQL의 핵심
입니다.
항상 기대 한 결과를 얻을 수 있습니다. 서버에서 클라이언트가 요청하는 필드를 정확히 알고있기 때문입니다.
rest api같은경우는 서버개발자가 docs를 내려주면 알수는 있지만 docs가 최신화가 되어있지 않거나 docs가 없을경우에는 서버에 요청을 해야지만 응답값을 알 수 있다.
하지만 GraphQL
을 사용하게 되면 어떤 응답값이 올지 예측이 가능하다.
만약 alias를 쓰지 않고 똑같은 person이라는 대상으로 요청을 해서 응답을 받아올 수 있다고 해도 어떤 person이 내가 기대한 값인지 알지 못하기때문에 별칭으로 구분해줘야한다.
alias 사용하지 않을 경우
프래그먼트를 사용하면 필드셋을 구성한 다음 필요한 쿼리에 포함시킬 수 있습니다.
fragment <name> on <대상> {}
query PersonInfo($first: Int =1){
Person1: person(personID: 1) {
...personInfo
}
Person2: person(personID:2) {
...personInfo
}
}
fragment personInfo on Person {
filmConnection(first: $first) {
edges {
node {
title
director
created
}
}
}
}
변수를 사용하기 위해서는 다음 세 가지 작업을 해야 합니다.
쿼리는 문자열로 전달된다. index.html -> graphQLFetcher에서 alert 짝어보기
동적으로 쿼리를 조회할 필요가 있음
동적 값을 별도로 전달할 방법인 '변수'제공(기본값 할당 가능)
graphiQL에서는 하단에 query variables 가 있다.
쿼리는 무시할 수 있다. 변수를 넣어주려면 필요
이름을 따로 정의 할수 도 있다
작업 타입 은 쿼리(query), 뮤테이션(mutation), 구독(subscription) 이 될 수 있으며, 어떤 작업의 타입인지를 기술합니다.
query -> 작업 타입 , PersonInfo -> 작업 이름(함수명)
작업 이름 은 의미있고 명시적인 작업의 이름입니다. 디버깅이나 서버 측에서 로깅하는데에 매우 유용 할 수 있습니다. 네트워크 로그나 GraphQL 서버에 문제가 발생하면 내용을 확인하는 대신 코드에서 쿼리 이름을 찾아내는 것이 더 쉽습니다.
지시어
변수를 사용하여 쿼리의 구조와 형태을 동적으로 변경하는 방법이 필요할때 사용한다.
지시어는 필드나 프래그먼트 안에 삽입될 수 있으며 서버가 원하는 방식으로 쿼리 실행에 영향을 줄 수 있습니다.
@include(if: Boolean): 인자가 true 인 경우에만 이 필드를 결과에 포함합니다.
@skip(if: Boolean) 인자가 true 이면 이 필드를 건너뜁니다.
boolean으로 줄때는 항상 기본값을 가지고 있어야한다.
정리
쿼리 -> 요청 , 결과가 동일한 형태, 주석가능, 작업 타입/이름을 줄 수있다.
필드 객체참조하기때문에 다중콜하지않는다. 인자를 넣어 사용, 별칭을 통해서 같은 것을 여러개 구분해서 가져올수았다.
Fragment -> 반복되는 필드셋 / 변수 전달 가능하다.
변수/지시어 -> 동적쿼리방법이다 . @include, @skip이 있다.
- 쿼리는 데이터를 가져오는 것이지만 뮤테이션은 데이터를 수정하는 것이다.
- 변경을 발생시키는 작업이 명시적으로 뮤테이션을 통해 전송되어야한다.
뮤데이션을 연습해보기 위해 아폴로 스튜디오를 통해서 작업해보기!
update test
mutation Mutation($where: users_bool_exp!) {
delete_users(where: $where) {
returning {
id
name
rocket
timestamp
}
}
}
뮤테이션의 다중 필드
뮤테이션은 쿼리와 마찬가지로 여러 필드를 포함할 수 있습니다. 쿼리와 뮤테이션 사이에 중요한 차이점이 있습니다.
쿼리 필드는 병렬로 실행되지만 뮤테이션 필드는 하나씩 차례대로 실행됩니다.
why? 동시에 일어나면 같은 데이터를 조작하면 에러가 발생할 수 있기 때문에!
mutation Insert_and_update_users($objects: [users_insert_input!]!, $where: users_bool_exp!, $set: users_set_input) {
insert_users(objects: $objects) {
returning {
id
name
rocket
timestamp
}
}
update_users(where: $where, _set: $set) {
returning {
id
name
rocket
timestamp
}
}
}
{
"objects": [
{
"name": "wooks",
"rocket": "test",
"id": "4e4fd694-5273-4e9f-885a-f7e7b917b441"
}
],
"where": {
"id": {
"_eq": "4e4fd694-5273-4e9f-885a-f7e7b917b441"
}
},
"set": {
"name": "sangwooks"
}
}
{
"data": {
"insert_users": {
"returning": [
{
"id": "4e4fd694-5273-4e9f-885a-f7e7b917b441",
"name": "wooks",
"rocket": "test",
"timestamp": "2022-03-28T13:28:25.078196+00:00"
}
]
},
"update_users": {
"returning": [
{
"id": "4e4fd694-5273-4e9f-885a-f7e7b917b441",
"name": "sangwooks",
"rocket": "test",
"timestamp": "2022-03-28T13:28:25.078196+00:00"
}
]
}
}
}
insert 한 즉시 update를 통해 wooks가 sangwooks로 변경
만약 query처럼 병렬로 처리했다면 where에 값이 없을거기 때문에 error가 발생할 수 있다.
GraphQL 스키마에는 인터페이스와 유니온 타입을 정의하는 기능
인터페이스나 유니언 타입을 반환하는 필드를 쿼리하는 경우, 인라인 프래그먼트 을 사용해야한다.
query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
name
... on Droid {
primaryFunction
}
... on Human {
height
}
}
}
Droid or Human 타입에 따라서 동적으로 요청
GraphQL 서비스에서 리턴될 타입을 모르는 상황이 발생하면 클라이언트에서 해당 데이터를 처리하는 방법을 결정할 방법이 필요합니다.
GraphQL을 사용하면 쿼리의 어느 지점에서나 메타 필드인 __typename
을 요청하여 그 시점에서 객체 타입의 이름을 얻을 수 있습니다.
{
search(text: "an") {
__typename
... on Human {
name
}
... on Droid {
name
}
... on Starship {
name
}
}
}
{
"data": {
"search": [
{
"__typename": "Human",
"name": "Han Solo"
},
{
"__typename": "Human",
"name": "Leia Organa"
},
{
"__typename": "Starship",
"name": "TIE Advanced x1"
}
]
}
}
정리
뮤테이션 -> 데이터의 수정을 가하는 방법
Apollo graphQL -> 다양한 기능이 추가된 라이브러리
뮤테이션 다중 필드 -> 순차 실행(쿼리는 병렬)
인라인 프래그먼트 -> inferface /union 일때 사용