FastAPI 및 Django에서 Strawberry를 사용한 최신 GraphQL API 구축
Emily Parker
Product Engineer · Leapcell

소개
오늘날의 데이터 중심 세계에서 효율적이고 유연한 API 설계는 매우 중요합니다. 널리 채택된 기존 REST API는 종종 데이터의 과다 검색 또는 과소 검색과 같은 문제에 직면하여 클라이언트와 서버 간의 비효율적인 통신으로 이어집니다. 이것이 바로 GraphQL이 빛을 발하는 곳입니다. API를 위한 강력한 쿼리 언어를 제공하여 클라이언트가 더 적은 것도, 더 많은 것도 아닌, 필요한 데이터를 정확하게 요청할 수 있습니다.
Python은 다재다능함과 풍부한 생태계를 통해 백엔드 개발에 인기 있는 선택이 되었습니다. FastAPI와 같은 고성능 프레임워크 또는 Django와 같은 강력한 프레임워크 내에서 Python으로 최신 GraphQL API를 구축하는 경우 Strawberry 라이브러리는 우아하고 Pythonic한 솔루션을 제공합니다.
이 기사는 Strawberry가 일반적인 API 설계 함정을 해결하면서 정교한 GraphQL API 생성을 어떻게 촉진하고 데이터 상호 작용에 대한 더 많은 제어를 개발자에게 제공하는지 살펴봅니다.
핵심 개념 설명
구현 세부 사항을 자세히 살펴보기 전에 관련된 핵심 개념에 대한 명확한 이해를 확립해 봅시다.
- GraphQL: API를 위한 쿼리 언어이자 데이터에 대해 정의한 유형 시스템을 사용하여 쿼리를 실행하는 서버 측 런타임입니다. 특정 데이터와 스키마를 클라이언트에서 요청할 수 있도록 하는 REST의 대안입니다.
- Strawberry: "코드 우선(code-first)" Python GraphQL 라이브러리입니다. 즉, 표준 Python 유형 및 데코레이터를 사용하여 Python 코드에서 직접 GraphQL 스키마를 정의합니다. 이 접근 방식은 SDL(Schema Definition Language)을 작성한 다음 코드를 생성하는 스키마 우선 접근 방식에 비해 종종 더 나은 개발자 경험과 유형 안전성을 제공합니다.
- FastAPI: Python 3.7+를 기반으로 표준 Python 유형 힌트를 사용하여 API를 구축하기 위한 현대적이고 빠른(고성능) 웹 프레임워크입니다. Starlette와 Pydantic 덕분에 자동 대화형 API 문서(Swagger UI/ReDoc)와 우수한 성능으로 유명합니다.
- Django: 신속한 개발 및 깔끔하고 실용적인 설계를 장려하는 수준 높은 Python 웹 프레임워크입니다. ORM, 관리자 패널, 템플릿 엔진 등을 제공하는 "배터리 포함" 프레임워크로, 복잡한 데이터베이스 기반 응용 프로그램에 적합합니다.
- 스키마: GraphQL에서 스키마는 데이터의 모양과 클라이언트가 수행할 수 있는 작업을 설명합니다. 유형, 필드 및 해당 관계를 정의합니다.
- 쿼리: GraphQL의 읽기 작업입니다. 클라이언트는 쿼리를 사용하여 서버에서 데이터를 가져옵니다.
- 뮤테이션: GraphQL의 쓰기 작업입니다. 클라이언트는 뮤테이션을 사용하여 서버의 데이터를 수정합니다(예: 생성, 업데이트, 삭제).
- 리졸버: 스키마의 특정 필드에 대한 데이터를 가져오는 것을 담당하는 GraphQL의 함수입니다. 클라이언트가 필드를 요청하면 해당 리졸버가 실행됩니다.
Strawberry를 사용한 GraphQL API 구축
Strawberry의 "코드 우선" 접근 방식은 Python의 유형 힌트를 활용하여 스키마 정의를 단순화합니다. 이렇게 하면 스키마 정의가 자연스럽고 IDE 기능(예: 자동 완성 및 유형 검사)과 잘 통합됩니다.
원칙 및 구현
Strawberry는 @strawberry.type
으로 장식된 Python 클래스로 GraphQL 유형을 정의할 수 있도록 하여 작동합니다. 이러한 유형 내의 필드는 유형 힌트가 있는 클래스 속성으로 정의됩니다. 뮤테이션의 입력 유형은 @strawberry.input
으로 유사하게 정의됩니다.
핵심 아이디어는 GraphQL 스키마의 루트 유형 역할을 할 Query
및 Mutation
클래스를 정의하는 것입니다. 이러한 클래스에는 클라이언트가 호출할 수 있는 메서드(리졸버)가 포함됩니다.
FastAPI 예제
책을 관리하는 간단한 예를 통해 설명해 보겠습니다.
먼저 필요한 라이브러리를 설치합니다.
pip install fastapi "uvicorn[standard]" strawberry-graphql strawberry-graphql-fastapi
이제 Strawberry 스키마를 정의하고 FastAPI와 통합합니다.
import strawberry from fastapi import FastAPI from strawberry.asgi import GraphQL # 단순화를 위한 인메모리 데이터베이스 BOOKS_DB = [] @strawberry.type class Book: id: strawberry.ID title: str author: str year: int @strawberry.input class BookInput: title: str author: str year: int @strawberry.type class Query: @strawberry.field def hello(self) -> str: return "Hello World" @strawberry.field def books(self) -> list[Book]: return BOOKS_DB @strawberry.field def book(self, id: strawberry.ID) -> Book | None: for book in BOOKS_DB: if book.id == id: return book return None @strawberry.type class Mutation: @strawberry.mutation def add_book(self, book_data: BookInput) -> Book: new_book = Book(id=strawberry.ID(str(len(BOOKS_DB) + 1)), **book_data.__dict__) BOOKS_DB.append(new_book) return new_book @strawberry.mutation def update_book(self, id: strawberry.ID, book_data: BookInput) -> Book | None: for i, book in enumerate(BOOKS_DB): if book.id == id: updated_book = Book(id=id, **book_data.__dict__) BOOKS_DB[i] = updated_book return updated_book return None @strawberry.mutation def delete_book(self, id: strawberry.ID) -> bool: global BOOKS_DB initial_len = len(BOOKS_DB) BOOKS_DB = [book for book in BOOKS_DB if book.id != id] return len(BOOKS_DB) < initial_len schema = strawberry.Schema(query=Query, mutation=Mutation) app = FastAPI() app.add_route("/graphql", GraphQL(schema)) # To run this: uvicorn main:app --reload
이 FastAPI 예제에서:
@strawberry.type
을 사용하여 SQLAlchemy 유형으로Book
을 정의합니다.Query
및Mutation
클래스는 사용 가능한 작업을 정의합니다.Query
및Mutation
내의 각 필드는@strawberry.field
또는@strawberry.mutation
으로 장식되어 GraphQL에서 노출되는 필드/작업이 됩니다.- 유형 힌트는 Strawberry가 GraphQL 유형을 추론하는 데 중요합니다.
strawberry.asgi
의GraphQL
은 Strawberry 스키마를 FastAPI에 통합하는 데 사용됩니다.
그러면 일반적으로 http://127.0.0.1:8000/graphql
에서 GraphQL Playground에 액세스하여 쿼리와 뮤테이션을 보낼 수 있습니다.
예제 쿼리:
query { books { id title author } }
예제 뮤테이션:
mutation AddNewBook { addBook(bookData: {title: "The Great Gatsby", author: "F. Scott Fitzgerald", year: 1925}) { id title author } }
Django 예제
Django와의 Strawberry 통합은 마찬가지로 간단하며 종종 유형 정의를 위해 Django 모델을 활용합니다.
먼저 필요한 라이브러리를 설치합니다.
pip install django strawberry-graphql "strawberry-graphql-django>=0.9"
Djanggo 프로젝트와 books
라는 앱이 있다고 가정해 보겠습니다. Book
모델을 정의합니다.
# books/models.py from django.db import models class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=200) year = models.IntegerField() def __str__(self): return self.title
이제 books/schema.py
와 같은 파일에 Strawberry 스키마를 정의합니다.
# books/schema.py import strawberry from strawberry_django.views import GraphQLView from .models import Book # Django 모델에서 유형을 자동으로 생성하기 위해 strawberry_django 사용 @strawberry.django.type(Book) class BookType: id: strawberry.ID title: str author: str year: int @strawberry.input class BookInput: title: str author: str year: int @strawberry.type class Query: @strawberry.field def hello(self) -> str: return "Hello from Django!" @strawberry.field def books(self) -> list[BookType]: return Book.objects.all() @strawberry.field def book(self, id: strawberry.ID) -> BookType | None: try: return Book.objects.get(pk=id) except Book.DoesNotExist: return None @strawberry.type class Mutation: @strawberry.mutation def add_book(self, book_data: BookInput) -> BookType: new_book = Book.objects.create(**book_data.__dict__) return new_book @strawberry.mutation def update_book(self, id: strawberry.ID, book_data: BookInput) -> BookType | None: try: book_to_update = Book.objects.get(pk=id) for key, value in book_data.__dict__.items(): setattr(book_to_update, key, value) book_to_update.save() return book_to_update except Book.DoesNotExist: return None @strawberry.mutation def delete_book(self, id: strawberry.ID) -> bool: try: book_to_delete = Book.objects.get(pk=id) book_to_delete.delete() return True except Book.DoesNotExist: return False schema = strawberry.Schema(query=Query, mutation=Mutation)
마지막으로 Djanggo urls.py
를 구성하여 GraphQL 엔드포인트를 노출합니다.
# myproject/urls.py (or your app's urls.py) from django.contrib import admin from django.urls import path from strawberry_django.views import GraphQLView from books.schema import schema urlpatterns = [ path("admin/", admin.site.urls), path("graphql", GraphQLView.as_view(schema=schema)), ]
Django 애플리케이션을 실행하려면:
python manage.py makemigrations books python manage.py migrate python manage.py runserver
Django 통합은 Django 모델을 GraphQL 유형으로 자동 매핑하는 @strawberry.django.type
과 같은 도우미 함수를 제공하는 strawberry-graphql-django
의 이점을 누립니다. 이렇게 하면 상용구 코드가 줄어듭니다.
애플리케이션 시나리오
- 단일 페이지 애플리케이션(SPA) 및 모바일 앱: GraphQL은 필요한 모든 데이터를 단일 요청으로 가져와 네트워크 왕복을 줄이고 성능을 향상시킬 수 있으므로 이러한 애플리케이션에 이상적입니다.
- 마이크로서비스 아키텍처: GraphQL은 API 게이트웨이 역할을 하여 다양한 마이크로서비스에서 데이터를 집계하고 클라이언트에 통합된 API를 노출할 수 있습니다.
- 공개 API: REST와 함께 또는 그 대신 GraphQL 엔드포인트를 제공하면 소비자가 수신하는 데이터에 대한 더 많은 유연성과 제어를 얻을 수 있습니다.
- 실시간 데이터: Strawberry는 WebSocket을 사용하여 실시간 데이터 업데이트를 지원하는 구독을 지원하며, 이는 채팅 애플리케이션, 라이브 대시보드 또는 알림에 적합합니다.
결론
Strawberry는 Pythonic하고 효율적인 방식으로 강력한 GraphQL API를 구축하는 방법을 제공하며, FastAPI 및 Django와 같은 인기 있는 프레임워크와 완벽하게 통합됩니다. 코드 우선 접근 방식, 강력한 유형 힌트 및 뛰어난 커뮤니티 지원을 통해 개발자는 유연하고 성능이 뛰어난 데이터 가져오기 계층을 만들 수 있습니다.
Strawberry를 활용함으로써 개발자는 기존 REST API의 한계를 극복하고 클라이언트에게 정확한 데이터 가져오기 기능을 제공하면서 깔끔하고 유지보수 가능한 백엔드 코드베이스를 유지할 수 있습니다. 궁극적으로 Strawberry는 강력하고 사용하기 즐거운 미래 지향적인 API를 구축하는 데 도움이 됩니다.