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 |
Tags
- #보안이슈
- #크랙미4번
- Easy
- 리버싱
- #abex크랙미4번
- #심플즈 크랙미
- #심플즈
- #파밍
- GraphQL
- Spring
- java
- #abex
- #크랙미
- leetcode
- #크랙미3번
- #보안뉴스
- #크랙미 9번
- java8
- #크랙미 5번
- #고클린
- #abex크랙미
- springframework
- #크랙미 10번
- #리버싱
- #크랙미2번
Archives
- Today
- Total
Halo World
[GraphQL] GraphQL 서버 깊이 파보기 (2) 본문
본 포스팅은 Inflearn 얄코님 강의를 수강하며 복습용으로 작성하였습니다.
https://www.inflearn.com/course/%EC%96%84%ED%8C%8D%ED%95%9C-graphql-apollo/dashboard
유니언과 인터페이스
- 이전 예제에서는 각각의 배열이 특정 스칼라 타입이나 특정 커스텀 데이터 타입을 반환했지만,
- Union타입은 타입 여럿을 한 배열에 반환이 가능함
1. Equipment와 Supply를 함께 반환하기
- given 데이터 타입 정의
//given.js
//equipment와 supply를 함께 반환할 데이터 타입
const { gql } = require('apollo-server')
const dbWorks = require('../dbWorks.js')
const typeDefs = gql`
union Given = Equipment | Supply //Given 타입에 Equipment 또는 Supply를 받을 수 있음
`
const resolvers = {
Query: {
//한 배열에 equipment와 supply를 둘다 넣어서 반환
givens: (parent, args) => {
return [
...dbWorks.getEquipments(args),
...dbWorks.getSupplies(args)
]
}
},
Given: {
__resolveType(given, context, info) {
//해당 부분의 결과로 쿼리시 __typename 지정됨
if (given.used_by) {
return 'Equipment'
}
if (given.team) {
return 'Supply'
}
return null
}
}
}
module.exports = {
typeDefs: typeDefs,
resolvers: resolvers
}
- 정의한 resolver를 루트 쿼리에 추가
//_queries.js
const typeDefs = gql`
type Query {
// ...
givens: [Given]
}
`
- index.js에 given 모듈 추가
//index.js
// ...
const givens = require('./typedefs-resolvers/givens')
// ...
const typeDefs = [
// ...
givens.typeDefs
]
// ...
const resolvers = [
// ...
givens.resolvers
]
// ...
- playground에서 테스트
- givens 쿼리의 결과로 equipment와 supply 모두 반환
query {
givens {
__typename //해당 데이터가 equipment인지 supply인지 나타내주기 위해 사용
... on Equipment { //해당 데이터가 equipment인 경우 반환할 항목
id
used_by
count
new_or_used
}
... on Supply { //해당 데이터가 supply인 경우 반환할 항목
id
team
}
}
}
2. 인터페이스
- 유사한 객체 타입을 만들기 위한 공통 필드 타입
- 추상 타입 - 다른 타입에 implement 되기 위한 타입
- Java의 인터페이스와 비슷한 역할
//공통으로 갖고있는 필드 : id, user_by
type Equipment {
id: ID!
used_by: Role!
count: Int
new_or_used: NewOrUsed!
}
...
type Software {
id: ID!
used_by: Role!
developed_by: String!
description: String
}
- 공통 필드를 갖고있는 tools.js (인터페이스) 정의
//tools.js
const { gql } = require('apollo-server')
const typeDefs = gql`
interface Tool { //interface 정의
id: ID!
used_by: Role!
}
`
const resolvers = {
Tool: {
__resolveType(tool, context, info) {
//들어온 데이터가 어떤 타입인지 구분
if (tool.developed_by) {
return 'Software'
}
if (tool.new_or_used) {
return 'Equipment'
}
return null
}
}
}
module.exports = {
typeDefs: typeDefs,
resolvers: resolvers
}
//Tool을 implement한 Equipment
type Equipment implements Tool {
id: ID!
used_by: Role!
count: Int
new_or_used: NewOrUsed!
}
//Tool을 implement한 Software
type Software implements Tool {
id: ID!
used_by: Role!
developed_by: String!
description: String
}
- index.js에 tools import
//index.js
// ...
const tools = require('./typedefs-resolvers/tools')
// ...
const typeDefs = [
// ...
tools.typeDefs
]
// ...
const resolvers = [
// ...
tools.resolvers
]
// ...
- People 쿼리에 적용
//peopls.js 정의
const { gql } = require('apollo-server')
const dbWorks = require('../dbWorks.js')
const typeDefs = gql`
type People {
id: ID!
first_name: String!
last_name: String!
sex: Sex!
blood_type: BloodType!
serve_years: Int!
role: Role!
team: ID!
from: String!
tools: [Tool] //tool 인터페이스 타입
givens: [Given] // given 유니언 타입
}
`
const resolvers = {
Query: {
people: (parent, args) => dbWorks.getPeople(args),
person: (parent, args) => dbWorks.getPeople(args)[0]
}
}
module.exports = {
typeDefs: typeDefs,
resolvers: resolvers
}
//_queries.js 루트 쿼리에 추가
const typeDefs = gql`
type Query {
people: [People],
// ...
}
`
//index.js에 모듈 추가
// ...
const people = require('./typedefs-resolvers/people')
// ...
const typeDefs = [
// ...
people.typeDefs
]
// ...
const resolvers = [
// ...
people.resolvers
]
// ...
- playground에 쿼리 테스트
query {
people {
id
first_name
last_name
givens { //given 타입 쿼리
__typename
... on Equipment {
id
used_by
count
new_or_used
}
... on Supply {
id
team
}
}
tools { //tools interface 타입에 대한 쿼리
__typename
... on Equipment {
id
used_by
count
new_or_used
}
... on Software {
id
used_by
description
developed_by
}
}
}
}
+ 추가
Interface 타입과 Union 타입은 공통 필드를 갖고 있는지 없는지에 차이가 있음
Interface 타입을 구현한 객체는 Interface에 정의된 모든 필드를 갖고 있어야 함.
또한, 인터페이스 타입은 쿼리시 공통 부분으로 쿼리가 가능하다.
예를 들어, Equipment와 Software이 공통으로 갖고있는 id, used_by를 사용해 특정 쿼리를 만들 수 있음
참고 : https://devport.tistory.com/21
인자와 인풋타입
People 데이터 조건들로 필터 넣어 받아오기
//_queries.js
type Query {
...
peopleFiltered(
team: Int,
sex: Sex,
blood_type: BloodType,
from: String
): [People]
...
}
- __queries.js에서 정의한 대로 인자들을 받아와서 args로 인자들을 넘겨줄 수 있음
- 받아서 처리하는 곳에서 sql 등 쿼리문을 사용하여 args를 기반으로한 where절 구현
//people.js
Query: {
// ...
peopleFiltered: (parent, args) => dbWorks.getPeople(args),
}
- playground에서 쿼리 호출
query {
peopleFiltered (
team: 1 //1 팀에 속하고
blood_type: B //b형인
from: "Texas" //Texas 출신만 쿼리
) {
id
first_name
last_name
sex
blood_type
serve_years
role
team
from
}
}
데이터를 페이지로 나누어 받아오기
- paging 처리 방식
//__queries.js
type Query {
...
peoplePaginated(
page: Int!,
per_page: Int!
): [People]
...
}
//people.js
Query: {
// ...
peoplePaginated: (parent, args) => dbWorks.getPeople(args), //내부에서 별도로 페이징 쿼리 진행
// ...
}
- playground에서 쿼리 테스트
query {
//첫 페이지를 받아오고, 한 페이지당 7개의 결과를 받아와라
peoplePaginated(page: 1, per_page: 7) {
id
first_name
last_name
sex
blood_type
serve_years
role
team
from
}
}
별칭으로 데이터 받아오기
- 한 요청으로 데이터를 받아오는 경우, 데이터를 특정 기준으로 분리해서 받아오고 싶을 때 유용
query {
badGuys: peopleFiltered(sex: male, blood_type: B) {
first_name
last_name
sex
blood_type
}
newYorkers: peopleFiltered(from: "New York") {
first_name
last_name
from
}
}
인풋 타입
- mutation에 들어가는 인자들이 많아지는 경우, 이를 보다 깔끔하게 하기 위해 인자들을 묶어서 실어보내는 방식
//people.js
const typeDefs = gql`
....
//실제 정보를 입력할 때 요구되는 필드들
input PostPersonInput {
first_name: String!
last_name: String!
sex: Sex!
blood_type: BloodType!
serve_years: Int!
role: Role!
team: ID!
from: String!
}
`
const resolvers = {
// ...
Mutation: {
postPerson: (parent, args) => dbWorks.postPerson(args),
}
}
//_mutation.js
type Mutation {
//mutation의 postPerson 명령 실행시 들어가는 인자 정의 - 깔끔하게 묶어서 전달할 수 있음!
postPerson(input: PostPersonInput): People!
...
}
- playground 쿼리 테스트
mutation {
//인자로 input을 전달
//이전에 정의한 postPersonInput 형식으로 서버에 데이터 전송
postPerson(input: {
first_name: "Hanna"
last_name: "Kim"
sex: female
blood_type: O
serve_years: 3
role: developer
team: 1
from: "Pusan"
}) {
id
first_name
last_name
sex
blood_type
role
team
from
}
}
* Apollo 서버를 사용해 graphQL로 백앤드단을 구현하는 방법 간단 연습 끝
추가 정보는 아래 공식 사이트에서 튜토리얼로 배워볼 수 있음
https://www.apollographql.com/docs/apollo-server/#:~:text=Apollo+Server+is+an+open,use+data+from+any+source.
'개발 지식 > DEVELOPMENT' 카테고리의 다른 글
[GraphQL] GraphQL 클라이언트 만들어보기 (0) | 2022.02.13 |
---|---|
[GraphQL] GraphQL 서버 깊이 파보기 (1) (0) | 2022.02.13 |
[GraphQL] Apollo-server 셋팅 (0) | 2022.02.08 |
[GraphQL] GraphQL 기초 (REST API와 비교, GraphQL 강점, Apollo란?) (0) | 2022.02.05 |