GraphQL - Query, Mutation, Subscription
목차
FastAPI + Strawberry
Strawberry를 설치하기 위해서 pip install 'strawberry-graphql[fastapi]'
를 실행합니다.
간단한 예시를 통해서 Graph의 Query, Mutation, Subscription에 대해서 알아보도록 하겠습니다.
GraphQL 스키마 객체 타입
1
2
3
4
5
6
@strawberry.type
class Book:
id: int
title: str
author: str
publisher_id: int
Python 타입 힌트를 이용해서 class를 GraphQL 스키마 객체 타입으로 사용이 가능합니다.
@strawberry.type
데코레이터를 사용하면 class에 정의된 필드들이 자동으로 GraphQL 필드로 변환되어 API에서 사용할 수 있게 됩니다.
이를 통해서 GraphQL 스키마를 보다 직관적이고 간편하게 작성할 수 있습니다.
Query
GraphQL에서의 Query는 클라이언트가 서버에 데이터를 요청하는 진입점 역할을 합니다.
클라이언트는 이 Query를 통해 원하는 데이터의 구조와 필드를 명시적으로 선택하여 요청할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@strawberry.type
class Query:
@strawberry.field
def books(self) -> list[Book]:
"""모든 책 목록을 반환하는 쿼리"""
return books
@strawberry.field
def book(self, id: int) -> Book | None:
"""ID로 특정 책을 찾는 쿼리"""
for book in books:
if book.id == id:
return book
return None
Mutation
GraphQL에서 Mutation은 데이터를 수정, 추가 또는 삭제하는 작업을 수행하기 위한 진입점입니다.
Mutation은 서버의 상태를 변경하는 작업(생성, 수정, 삭제)을 수행합니다.
각 Mutation 필드에는 해당 작업을 실행할 수 있는 Resolver 함수가 연결되어 있어서 클라이언트가 요청한 작업을 처리한 후 결과 데이터를 반환할 수 있습니다.
Mutation은 순차적으로 실행되며 이를 통해 데이터 무결성과 일관성을 유지할 수 있습니다.
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
@strawberry.type
class Mutation:
@strawberry.mutation
async def insert_book(self, book_input: BookInput) -> Book:
new_id = len(books) + 1
new_book = Book(id=new_id,
title=book_input.title,
author=book_input.author,
publisher_id=book_input.publisher_id)
books.append(new_book)
await book_event_queue.put(books.copy())
return new_book
@strawberry.mutation
async def update_book(self, id: int, book_update: BookUpdate) -> Book | None:
for i, book in enumerate(books):
if book.id == id:
if book_update.title is not None:
book.title = book_update.title
if book_update.author is not None:
book.author = book_update.author
if book_update.publisher_id is not None:
book.publisher_id = book_update.publisher_id
await book_event_queue.put(books.copy())
return book
return None
@strawberry.mutation
async def delete_book(self, id: int) -> bool:
for i, book in enumerate(books):
if book.id == id:
books.pop(i)
await book_event_queue.put(books.copy())
return True
return False
Subscription을 위해서 Mutation에 await book_event_queue.put(books.copy())
를 추가해놓았습니다.
Subscription
GraphQL에서 Subscription은 클라이언트와 서버 간의 실시간 통신을 위한 진입점입니다.
클라이언트는 특정 이벤트나 데이터 변경 사항에 대해 구독할 수 있으며 해당 이벤트가 발생할 때마다 서버가 자동으로 업데이트 정보를 푸시합니다.
주로 WebSocket과 같은 프로토콜을 사용하여 지속적인 연결을 유지하며 실시간 데이터 피드가 필요할 때 유용하게 활용됩니다.
1
2
3
4
5
6
7
@strawberry.type
class Subscription:
@strawberry.subscription
async def on_book_event(self) -> AsyncGenerator[List[Book], None]:
while True:
event = await book_event_queue.get()
yield event
실행
1
2
3
4
5
6
7
schema = strawberry.Schema(query=Query, mutation=Mutation, subscription=Subscription)
graphql_app = GraphQLRouter(schema)
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")
이렇게 한 다음 FastAPI 서버를 올려서 /graphql 경로에 가면 Strawberry GraphiQL을 확인할 수 있다.
1
2
3
4
5
query GetBook{
books {
title
}
}
이런 내용을 입력해서 GraphQL 구현 테스트를 간단하게 해볼 수 있다.
다음글에는 PostgreSQL ORM과 GrpahQL을 연동해보겠습니다.