Notice
                              
                          
                        
                          
                          
                            Recent Posts
                            
                        
                          
                          
                            Recent Comments
                            
                        
                          
                          
                            Link
                            
                        
                    | 일 | 월 | 화 | 수 | 목 | 금 | 토 | 
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 | 
| 12 | 13 | 14 | 15 | 16 | 17 | 18 | 
| 19 | 20 | 21 | 22 | 23 | 24 | 25 | 
| 26 | 27 | 28 | 29 | 30 | 31 | 
                            Tags
                            
                        
                          
                          - #크랙미2번
- #크랙미 9번
- #abex크랙미4번
- #보안뉴스
- #abex크랙미
- 리버싱
- #abex
- #크랙미
- #고클린
- GraphQL
- #크랙미 5번
- #리버싱
- #크랙미 10번
- Easy
- Spring
- java8
- java
- #크랙미3번
- #크랙미4번
- leetcode
- #파밍
- #심플즈 크랙미
- #심플즈
- springframework
- #보안이슈
                            Archives
                            
                        
                          
                          - Today
- Total
Halo World
[GraphQL] GraphQL 서버 깊이 파보기 (1) 본문
본 포스팅은 Inflearn 얄코님 강의를 수강하며 복습용으로 작성하였습니다.
https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard
[무료] 얄팍한 GraphQL과 Apollo - 인프런 | 강의
⚡ 짧고 굵은 전체 90분 강좌! 사이트의 코드들을 복붙하며 빠르게 GraphQL을 배우고 아폴로 사용법을 익히세요., - 강의 소개 | 인프런...
www.inflearn.com
서버 구성요소 모듈화
이전 강의에서 살펴본 typeDefs와 Resolver는 모두 index.js 한 파일에 작성을 한 형태였는데,
각각을 모듈별로 쪼개어 파일을 구성하여 사용할 수 있다.
https://www.apollographql.com/docs/apollo-server/api/apollo-server/
아폴로 서버 문서를 보면, 배열 형태로 typeDefs와 Resolvers를 구성할 수 있도록 되어있다.
- typeDefs : 단일 변수 또는 배열로 지정 가능
- resolvers : 단일 Object 또는 Merge된 배열로 가능
- 각각의 파일에 query 및 mutation 루트 타입 정의
//typedefs-resolvers/_queries.js
// ...
const typeDefs = gql`
    type Query {
        equipments: [Equipment]
    }
`
// ...//typedefs-resolvers/_mutations.js
// ...
const typeDefs = gql`
    type Mutation {
      deleteEquipment(id: String): Equipment
    }
`
// ...- equipments 데이터의 typeDefs와 resolver 별도 정의
//typedefs-resolvers/equipments.js
// ...
const typeDefs = gql`
    type Equipment {
        id: String
        used_by: String
        count: Int
        new_or_used: String
    }
`
const resolvers = {
    Query: {
        equipments: (parent, args) => dbWorks.getEquipments(args),
    },
    Mutation: {
        deleteEquipment: (parent, args) => dbWorks.deleteItem('equipments', args),
    }
}
// ...- index.js에서 각각의 파일들을 import 해준 후, typeDefs와 resolvers 선언 시 배열로 넣어주어 모듈화 가능
//typedefs-resolvers/index.js
// ...
const queries = require('./typedefs-resolvers/_queries')
const mutations = require('./typedefs-resolvers/_mutations')
const equipments = require('./typedefs-resolvers/equipments'
// ...
const typeDefs = [
    queries,
    mutations,
    equipments.typeDefs,
]
const resolvers = [
    equipments.resolvers
]
// ...- 추가로 supply 라는 새로운 모듈을 추가 한다면, Equipment와 동일하게 해당 typeDef와 resolver를 supplies.js 라는 파일에 정의하고, query와 mutation 파일에 해당 쿼리를 정의해주는 방식으로 추가 가능하다.
 https://www.yalco.kr/@graphql-apollo/3-1/
GraphQL의 기본 타입들
1. 스칼라 타입
GraphQL 내장 자료형
    type EquipmentAdv {
        id: ID!
        used_by: String!
        count: Int!
        use_rate: Float
        is_new: Boolean!
    }- ID : 기본적으로는 String이나, 고유 식별자 역할임을 나타냄
- String : UTF-8 문자열
- Int : 부호가 있는 32비트 정수
- Float : 부호가 있는 부동소수점 값
- Boolean : 참/거짓
- ! 은 Non null을 의미하며, null인 경우 서버 내부에서 오류 반환
//equipment.js 내부에 equipmentAdvs를 위한 resolver 정의
//user_rate, is_new를 해당하는 스칼라 타입으로 변환
const resolvers = {
    Query: {
        // ...
        equipmentAdvs: (parent, args) => dbWorks.getEquipments(args)
            .map((equipment) => {
                if (equipment.used_by === 'developer') {
                    equipment.use_rate = Math.random().toFixed(2)
                }
                equipment.is_new = equipment.new_or_used === 'new'
                return equipment
            }),
    },
    // ...
}//_queries.js
    type Query {
        ...
        equipmentAdvs: [EquipmentAdv]
        ...
    }- playground에서 테스트
query {
    equipmentAdvs {
        id
        used_by
        count
        use_rate
        is_new
    }
}
2. 열거 타입
- Enum 타입의 데이터인 경우 enum 타입을 생성하여 데이터 타입을 지정해 줄 수 있다.
- 객체에 데이터가 Enum 타입에 정의되어 있지 않은 타입으로 지정되는 경우 Error가 발생한다.
//_enums.js  enum 예제
//Role 타입으로 설정된 데이터는 developer, desiner, planner로만,
//NewOrUsed 타입으로 설정된 데이터는 new, used 두 가지 값만 가능하다.
const { gql } = require('apollo-server')
const typeDefs = gql`
    enum Role {
        developer
        designer
        planner
    }
    enum NewOrUsed {
        new
        used
    }
`
module.exports = typeDefs//index.js의 typeDefs에 enums 타입 추가
// ...
const enums = require('./typedefs-resolvers/_enums')
// ...
const typeDefs = [
    // ...
    enums,
    // ...
]//equipments.js
const typeDefs = gql`
    type Equipment {
        id: ID!
        used_by: Role! //Role 타입에 설정되어있는 값만 들어갈 수 있다.
        count: Int!
        new_or_used: NewOrUsed! //NewOrUsed 타입에 설정되어있는 값만 들어갈 수 있다.
    }
    type EquipmentAdv {
        id: ID!
        used_by: Role!
        count: Int!
        use_rate: Float
        is_new: Boolean!
    }
`- playground에서 쿼리를 실행하여 결과를 확인해 볼 수 있다.
- db에 enums에 설정되어있지 않은 값이 들어있으면 (예를 들어, used_by 값이 manager로 설정되어있으면) 쿼리 실행 중 에러가 발생한다.
query {
  equipments {
    id
    used_by
    count
    new_or_used
  }
equipmentAdvs {
    id
    used_by
    count
    use_rate
    is_new
  }
}
3. 리스트 타입
- 특정 타입의 배열을 반환
//equipments.js
const typeDefs = gql`
    // ...
    type EquipmentAdv {
        id: ID!
        used_by: Role!
        count: Int!
        use_rate: Float
        is_new: Boolean!,
        users: [String!]
    }
`
// ...
const resolvers = {
    Query: {
        // ...
        equipmentAdvs: (parent, args) => dbWorks.getEquipments(args)
            .map((equipment) => {
                if (equipment.used_by === 'developer') {
                    equipment.use_rate = Math.random().toFixed(2)
                }
                equipment.is_new = equipment.new_or_used === 'new'
                
                // 리스트 예제 
                // equipment 결과값의 1/2을 대상으로 
                // user라는 배열을 추가하고, 
                // db에 저장된 equipment.used_by와 같은 role을 갖고 있는 사람 중 1/5 확률로 
                // user 배열에 추가함
                if (Math.random() > 0.5) {
                    equipment.users = []
                    dbWorks.getPeople(args).forEach((person) => {
                        if (person.role === equipment.used_by && Math.random() < 0.2) {
                            equipment.users.push(person.last_name)
                        }
                    })
                }
                return equipment
            }),
    },
    // ...
}
| 선언부 | users: null | users: [] | users[..., null] | 
| [String] | 가능 | 가능 | 가능 | 
| [String!] | 가능 | 가능 | 불가능 | 
| [String]! | 불가능 | 가능 | 가능 | 
| [String!]! | 불가능 | 가능 | 불가능 | 
4. 객체 타입
- 사용자에 의해 정의된 타입들
- ex) typeDefs, equipment 등..
'개발 지식 > DEVELOPMENT' 카테고리의 다른 글
| [GraphQL] GraphQL 클라이언트 만들어보기 (0) | 2022.02.13 | 
|---|---|
| [GraphQL] GraphQL 서버 깊이 파보기 (2) (0) | 2022.02.13 | 
| [GraphQL] Apollo-server 셋팅 (0) | 2022.02.08 | 
| [GraphQL] GraphQL 기초 (REST API와 비교, GraphQL 강점, Apollo란?) (0) | 2022.02.05 | 
 
                   
                  