개발

graphql 데이터 api만들고 연동 , 타입관 관계형성하기

덤벨로퍼 2020. 2. 11. 20:06

 

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);
            }
        }
    })  
})