2020/04/13 - [Back-end/Python] - [GraphQL] 무작정 시작하기 (1) - Schema & Query
0. 서론
지난 포스트에서 GraphQL에 대해서 간략하게 알아보고 데이터를 조회하는 서버를 간단하게 만들어보았다. 이는 데이터의 기본적인 처리 프로세스인 CRUD(Create, Read, Update, Delete) 중 Read(조회)만 구현한 것이다. GraphQL에서 Read(조회)는 쿼리(Query)가 처리하며, Create(입력), Update(수정), Delete(삭제)는 뮤테이션(Mutation)이 처리한다.
그래서 이번 포스트에서는 데이터 변조를 위한 뮤테이션(Mutation)들을 구현해보도록 하겠다.
1. 프로젝트 준비
2020/04/13 - [Back-end/Python] - [GraphQL] 무작정 시작하기 (1) - Schema & Query
- 이전 포스트를 참조.
2. Mutation 소스 작성
2-1. 데이터 입력(Create) Mutation - api/mutation.py
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
32
33
34
35
36
37
38
39
40
41
|
# api/mutation.py
import datetime
import graphene
from api.models import RankModel, RankType
# Create Mutation 정의
class CreateRank(graphene.Mutation):
# 입력받을 파라미터 Field 정의
class Arguments:
mode = graphene.String(required=True)
name = graphene.String(required=True)
score = graphene.Int(required=True)
is_mobile = graphene.Boolean(default_value=False) # 생량 가능
# 반환 Field 정의
rank = graphene.Field(RankType)
success = graphene.Boolean()
# 실행할 Mutation 정의
def mutate(root, info, **kwargs):
# MongoDB Model 생성
model = RankModel(
mode=kwargs.get("mode"),
name=kwargs.get("name"),
score=kwargs.get("score"),
is_mobile=kwargs.get("is_mobile"),
reg_dttm=datetime.datetime.now().strftime("%Y%m%d%H%M%S") # 현재시간
)
# MongoDB에 저장
model.save()
# 결과 반환
return CreateRank(
rank=model,
success=True
)
# Mutation Field 정의
class Mutation(graphene.ObjectType):
create_rank = CreateRank.Field()
|
cs |
1) [ 7 ln ] - Mutation Class 생성.
2) [ 9~13 ln ] - 입력받을 Mutation의 파라미터를 정의.
: 이곳에 정의되지않은 파라미터를 받을 경우 오류가 발생함.
3) [ 15~17 ln ] - 처리 결과를 반환할 Field 정의.
: 반드시 한 개 이상 존재해야함.
4) [ 20~36 ln ] - mutate 함수에 데이터 입력(Create) 프로세스를 정의.
: [ 22~28 ln ] - 입력받은 파라미터로 MongoDB Model 객체 생성.
: [ 30 ln ] - MongoDB에 저장.
: [ 33~36 ln ] - 결과값을 반환.
: 3)에서 정의한 반환타입을 파라미터로 받는 Mutation을 반환.
5) [ 39~40 ln ] - Mutation Field 정의.
: 위에서 생성한 Mutation Class를 Field로 설정.
: 신규로 생성할 때마다 이곳에 추가.
* mutate 함수에 정의한 프로세스에 따라 Update, Delete를 구현할 수 있음.
2-2. Schema에 Mutataion 추가 - api/schema.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# api/schema.py
import graphene
from api.models import RankModel, RankType
from api.mutation import Mutation
# Query Field 정의
class Query(graphene.ObjectType):
'''중략'''
# Schema 생성
schema = graphene.Schema(
query=Query,
mutation=Mutation, # Mutation 추가
types=[
RankType
]
)
|
cs |
1) [ 14 ln ] - 앞서 정의한 Mutation을 Schema에 추가.
3. Flask App 실행
3-1. 실행
$ python app.py
3-2. 실행 결과
3-3. GraphQL View 실행
1) 브라우저 실행 후 http://localhost:3000/graphql 로 접속.
2) 오른쪽 상단에 Docs를 클릭하면 Schema의 정보를 확인 할 수 있음.
: Query와 Mutation이 등록된 것이 확인됨.
4. Mutation 테스트
4-1. 목록 확인
1) 현재 4개의 데이터가 출력되는 것이 확인됨.
4-2. 데이터 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# 데이터 추가 Mutation
mutation {
createRank(
mode: "2x2",
name: "heo",
score: 100
){
success
rank {
id
mode
name
score
isMobile
regDttm
}
}
}
|
cs |
1) [ 2 ln ] - Muatation 시작.
2) [ 3~7 ln ] - CreateRank Mutation에 저장할 데이터를 입력.
3) [ 7~17 ln ] - 결과 출력.
- [ 8 ln ] - success Field 출력 .
- [ 9~16 ln ] - rank Field의 상세 Field들을 출력.
4) 실행 결과.
: 데이터가 정상적으로 저장되면 요청한 결과값이 출력됨.
: [4-1]을 다시 실행해보면 목록에 추가된 것을 확인할 수 있음.
5. Update, Delete Mutation 소스 작성
5-1. 데이터 수정(Update) Mutation - api/mutation.py
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
# api/mutation.py
'''중략'''
# 상세 입력 Field 정의
class InuptUpdateRankData(graphene.InputObjectType):
score = graphene.Int()
is_mobile = graphene.Boolean()
# Update Mutation 정의
class UpdateRank(graphene.Mutation):
# 입력받을 파라미터 Field 정의
class Arguments:
mode = graphene.String(required=True)
name = graphene.String(required=True)
data = InuptUpdateRankData(required=True)
# 반환 Field 정의
rank = graphene.Field(RankType)
success = graphene.Boolean()
# 실행할 Mutation 정의
def mutate(root, info, mode, name, data):
# 수정할 MongoDB Model 조회
model = RankModel.objects(
mode=mode,
name=name
).first()
# 입력받은 파라미터로 수정
if data.score is not None:
model.score = data.score
if data.is_mobile is not None:
model.is_mobile = data.is_mobile
model.upd_dttm = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
# MongoDB에 저장
model.save()
# 결과 반환
return UpdateRank(
rank=model,
success=True
)
'''중략'''
|
cs |
1) [ 6~8 ln ] - 상세 입력 Field 정의.
: InputObjectType을 사용하면 파라미터를 Json형태로 받을 수 있음.
2) [ 13~16 ln ] - 입력받을 파라미터 Field를 정의.
: [ 16 ln ] - data를 상세 입력 Field로 정의.
3) [ 23~46 ln ] - mutate 함수에 데이터 수정(Update) 프로세스를 정의.
: [ 25~28 ln ] - MongoDB에서 mode와 name 조건에 일치하는 데이터를 1개 조회.
: [ 31~37 ln ] - 조회된 데이터를 입력받은 데이터로 수정.
: [ 40 ln ] - MongoDB에 저장.
: [ 43~45 ln ] - 결과 반환.
* Mutation Field 추가는 데이터 삭제(Delete)에서 처리.
5-2. 데이터 삭제(Delete) Mutation - api/mutation.py
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
32
33
34
35
36
37
|
# api/mutation.py
'''중략'''
# Delete Mutation 정의
class DeleteRank(graphene.Mutation):
# 입력받을 파라미터 Field 정의
class Arguments:
mode = graphene.String(required=True)
name = graphene.String(required=True)
# 반환 Field 정의
success = graphene.Boolean()
def mutate(root, info, mode, name):
# MongoDB에서 삭제
RankModel.objects(
mode=mode,
name=name
).delete()
# 삭제되었는지 확인
success = RankModel.objects(
mode=mode,
name=name
).first() == None
# 결과 반환
return DeleteRank(
success=success
)
# Mutation Field 정의
class Mutation(graphene.ObjectType):
create_rank = CreateRank.Field()
update_rank = UpdateRank.Field()
delete_rank = DeleteRank.Field()
|
cs |
1) [ 15~31 ln ] - mutate 함수에 데이터 수정(Update) 프로세스를 정의.
: [ 17~20 ln ] - MongoDB에서 mode와 name 조건에 일치하는 데이터 삭제.
: [ 23~26 ln ] - 삭제되었는지 확인.
: [ 29~31 ln ] - 결과 반환.
2) [ 34~37 ln ] - Mutation Field 정의.
: [ 35 ln ] - 데이터 입력(Create) Mutation Field 추가.
: [ 36 ln ] - 데이터 수정(Update) Mutation Field 추가.
: [ 37 ln ] - 데이터 삭제(Delete) Mutation Field 추가.
6. Mutation 테스트
6-1. 입력, 수정, 삭제 일괄 실행
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
mutation {
# 데이터 입력(Create)
createRank(
mode: "100x100",
name: "dochi",
score: 1,
isMobile: false
){
success
rank {
id
mode
name
score
isMobile
regDttm
}
}
# 데이터 수정(Update)
updateRank(
mode: "100x100",
name: "dochi",
data: {
score: 999999,
isMobile: true
}
){
success
rank {
id
mode
name
score
isMobile
regDttm
updDttm
}
}
# 데이터 삭제(Delete)
deleteRank(
mode: "100x100",
name: "dochi"
){
success
}
}
|
cs |
1) [ 3~18 ln ] - 데이터 입력(Create) Mutation 실행.
2) [ 21~39 ln ] - 데이터 수정(Update) Mutation 실행.
3) [ 42~47 ln ] - 데이터 삭제(Delete) Mutation 실행.
* GraphQL은 위와 같이 하나의 쿼리에 여러개의 이벤트를 발생시킬 수 있음.
마치며
- 지금까지 CRUD를 간략하게 구현해보았다. 목록을 조회할 때 페이징처리나 정렬, 예외처리 등 아직 부족한 점이 많기는 하지만 앞으로 좀 더 공부해가면서 살을 붙여나가도록 하겠다.
- 다음 포스트에서는 데이터를 조회할 때 페이징처리하여 조회하는 방법에 대해서 알아보도록 하겠다.
'Back-end > Python' 카테고리의 다른 글
[GraphQL] 무작정 시작하기 (4) - Relay와 Connection이란? (0) | 2020.04.21 |
---|---|
[GraphQL] 무작정 시작하기 (3) - Object Field를 이용한 Pagination (0) | 2020.04.20 |
[GraphQL] 무작정 시작하기 (1) - Schema & Query (0) | 2020.04.13 |
[SMTP] Python으로 메일 발송 하기. (With. 첨부파일 ) (1) | 2020.02.22 |
[Pyftpdlib] FTP 서버 만들기 (4) - SSL/TLS FTP 서버 (0) | 2020.02.18 |
댓글