graphql 데이터 api만들고 연동 , 타입관 관계형성하기
api를 만들기 위해서 json-server사용한다.
fake db를 만들어보자
db.json
{
"Users":[
{
"id":"1","firstName":"Hwi","age":31
},
{
"id":"2","firstName":"Yunji","age":25
}
]
}
이후 package.json 에서
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"json:server":"json-server --watch db.json"
},
해당 json:server 스크립트를 넣어주고
두번째 터미널을 열어 (server돌아가는중) npm run json:server를 실행한다.
이와같이 3000포트로 api 를 만들수있다. /Users/1 이렇게 id 로도 접근할수있다.
const RootQuery = new GraphQLObjectType({
name:'RootQueryType',
fields:{
user:{
type:UserType,
args:{id:{type:GraphQLString}},
resolve(parentValue,args){
return axios.get(`http://localhost:3000/users/${args.id}`)
.then(res=>{
console.log(res);
return res.data;
})
}
}
}
})
지난번 만들었던 RootQuery 에서 resolve 함수를 바꿔보자
axios 를 통해 api에 접근해서 데이터를 리턴하면 된다.
만약 두개의 데이터 타입이있고 두개가 연관이있다면 어떻게 스키마를 정의해야할까
예로 user가있고 그들이 일하는 companies 가있다고 해보자
먼저 CompanyType을 만든다
const CompanyType = new GraphQLObjectType({
name:'Company',
firstName:{
id:{type:GraphQLString},
name:{type:GraphQLString},
description:{type:GraphQLString}
}
})
그리고 user에 companyType 필드를 넣어주자
const UserType = new GraphQLObjectType({
name:'User',
fields:{
id:{type:GraphQLString},
firstName:{type:GraphQLString},
age:{type:GraphQLInt},
company:{type:CompanyType}
}
})
하지만 실 데이터를 보면 user 데이터에서는 companyId 만 제공하고있다.
해당 companyId 를 통해 company의 정보를 가져와 User를 쿼리할때 보여주려한다.
{
"users":[
{
"id":"1","firstName":"Hwi","age":31,"companyId":11
},
{
"id":"2","firstName":"Yunji","age":25,"companyId":22
}
],
"companies":[
{"id":"11","name":"apple","description":"iphone"},
{"id":"22","name":"samsung","description":"galaxy"}
]
}
우선 companyId를 불러와보자
resolve함수에서 제공되는 parentValue 를 콘솔에 찍어보면
company:{
type:CompanyType,
resolve(parentValue,args){
console.log(parentValue);
}
}
이렇게 해당 User의 정보를 한번에 얻을수있다.
parentValue.companyId 를 http 리퀘스트에 사용하면 원하는 정보를 얻어 company필드에 적용하면된다.
const UserType = new GraphQLObjectType({
name:'User',
fields:{
id:{type:GraphQLString},
firstName:{type:GraphQLString},
age:{type:GraphQLInt},
company:{
type:CompanyType,
resolve(parentValue,args){
console.log(parentValue);
return axios.get(`http://localhost:3000/companies/${parentValue.companyId}`)
.then((res)=>res.data);
}
}
}
})
user 말고 company 자체를 쿼리하고 싶다면 Rootquery에 필드 추가하면된다.
const RootQuery = new GraphQLObjectType({
name:'RootQueryType',
fields:{
user:{
type:UserType,
args:{id:{type:GraphQLString}},
resolve(parentValue,args){
return axios.get(`http://localhost:3000/users/${args.id}`)
.then(res=>{
console.log(res);
return res.data;
})
}
},
company:{
type:CompanyType,
args:{id:{type:GraphQLString}},
resolve(parentValue,args){
return axios.get(`http://localhost:3000/companies/${args.id}`)
.then(res=>{
return res.data;
})
}
}
}
})
이번에는 company 쿼리를 통해 해당 회사에 소속되어있는 users 를 불러올것이다.
const CompanyType = new GraphQLObjectType({
name:'Company',
fields:{
id:{type:GraphQLString},
name:{type:GraphQLString},
description:{type:GraphQLString},
user:{
type: new GraphQLList(UserType),
resolve(parentValue,args){
console.log(parentValue);
return axios.get(`http://localhost:3000/companies/${parentValue.id}/users`);
}
}
}
})
field에 user를 추가하고 원하는 데이터가있는 url 을 추가했다. (parentValue .id 에는 해당 회사의 id가 들어있다)
여러 user를 데려올거기 때문에 GraphQLList 타입을 사용했다.
하지만 참조하고있는 userType 이 (코드가) 그 아래에 선언되었기떄문에 에러가 발생한다.
이는 화살표함수로 해결가능하다 ( 다 선언된 후에 함수가 실행됨)
const CompanyType = new GraphQLObjectType({
name:'Company',
fields:()=>({
id:{type:GraphQLString},
name:{type:GraphQLString},
description:{type:GraphQLString},
user:{
type: new GraphQLList(UserType),
resolve(parentValue,args){
console.log(parentValue.id);
return axios.get(`http://localhost:3000/companies/${parentValue.id}/users`)
.then((res)=>res.data);
}
}
})
})