처음 보면 sql과 비슷하여 데이터베이스와 관련된 언어라고 생각할 수 있지만, 방향이 다르다.
데이터 질의어는 물론이고, 서버 api를 구축하는 하나의 런타임으로 볼 수 있는데, rest api와 비슷하게 데이터를 주고 받을 수 있는 구조이다.
soap -> rest -> graphql 이렇게 발전해오고 있다.
그렇다면 rest에 익숙한 개발자들이 처음에 이해하기 살짝은 까다로운 graphql의 구조에 대해서 알아보자.
graphql은 기본적으로 schema + resolver 로 구성된다.
schema는 변수와 함수를 정의한다.
java에서의 interface 역할(내 생각)
req.body / req.params 에서 사용되는 데이터를 미리 정의한다.
위와 같이 rest api는 매번 호출을 해야하는 대신, graphql은 한번의 호출로 처리가 가능하다.
그럼 이제 schema를 한번 짜보자.
schema는 client에서 server에 어떻게 data를 요청할지 정의한 파일이다. 그렇기 때문에 반드시 schema에 정의된 형태로 서버에 요청해야 한다.
마치 req.body와 비슷한 느낌이다.
기본적으로 type Query 와 type Mutation 은 디폴트로 꼭 필요한 구성요소인 듯 하다.
Query는 read 형식이고, Mutation은 create, update, delete 형식으로 주로 쓰인다고 한다.
이제 resolver를 보자.
resolver는 schema에서 정의한 함수 및 변수를 구현한다.
showUser는 매개변수 없이 모든 user를 보여주는 함수이고, addUser는 새로 저장할 user의 정보를 매개변수로 통해 새로운 user를 저장하는 함수이다.
object type에는 크게 보면 input type, output type 이 존재한다. 말 그대로 object이 어떻게 쓰이냐에 따라 다르게 사용되는 것 같다. 함수의 파라미터로 사용하면 input type, 함수의 반환값으로 사용되면 output type. 그렇다면 object에는 어떤 타입이 있는지 보자.
{
user {
name
}
}
여기서 name 필드가 스칼라 타입이라고 할 수 있다. 이렇게 쿼리의 끝을 가리키는 필드를 스칼라 타입이라고 한다.
object type을 interface와 같이 사용할 수 있다.
input type은 쿼리의 파라미터 역할을 하며 payload 성격을 보인다.
graphql의 object type에는 input과 output이 있다. output type은 리졸버 함수를 통해 반환되는 타입이고, input type은 리졸버 함수의 파라미터 값으로 들어간다.
input type으로는 1.scalar 2.list 3.input type들만 가능하다.
type Users {
id : Int!,
name : String!,
age : Int!
}
input newUser {
id : Int,
name : String,
age : Int
}
type Mutation {
addUser(id : Int!, name : String!, age : Int!) : Users!
addUser2(input : newUser) : Users!
}
Mutation : {
addUser : (_, {id, name, age}) => {
if (Users.find(user => user.name === name)) return null
const newUser = {
id : id,
name : name,
age : age
}
Users.push(newUser);
return newUser;
},
addUser2 : (_, {input}) => {
if (Users.find(user => user.name === input.name)) return null
const user = {
input
}
console.log(user)
Users.push(user);
console.log(Users)
return user.input;
}
}
위와 같이 type User 은 output type이고 input newUser은 output type임을 알 수 있다.
여기서 중요한 점은 반드시 input json object으로 변수를 설정해줘야 하고, 리졸버 함수의 반환값을 user.input으로 넘겨줘야 한다.(X)
Users.push(user.input)으로 넣어주는 것이 이상적이다.
위 결과는 User.push(user) 이고, 아래 결과는 User.push(user.input) 이다.
input type으로 입력을 넣어주면 user : "input" : { "id" : 12, ~~ 와 같은 형태를 띈다고 볼 수 있다.
https://atheros.ai/blog/input-object-type-as-an-argument-for-graphql-mutations-and-queries
https://graphql.org/graphql-js/mutations-and-input-types/
https://graphql.org/learn/schema/