이전 글에서는 wsgi, asgi에 대해 다루었다.
오늘은 동기 메서드를 코루틴처럼 비동기로 쓸 수 있도록 변환해주는 callable object,
asgiref 패키지의 sync_to_async에 대해 알아보도록 한다.
🤚 이전 글에서 다뤘던 주요 내용에 대해 다시 정리해보자.
파이썬 어플리케이션과 서버를 연결해주는 "WSGI" 동기 함수만을 처리해 여러 작업 동시 수행에는 한계가 있었다. 이르 보완하기 위한 것이 바로 "ASGI"였다.
ASGI는 기본적으로 요청을 비동기로 처리한다. 이 ASGI의 대표적인 예가 uvicorn이었다.
본론으로 들어가서, Django Ninja의 Async 예제를 살펴보자.
기본적으로 장고의 ORM은 sync(동기적)로 작동한다. 우리는 async로 작동하도록 구현하기 위해 기존 방법과는 다르게 아래와 같이 2가지 방법을 통해 Sync(동기) -> Async(비동기) 로 설정 가능하다.
아래 2가지 모두 동일하게 asgiref 에서 제공하는 sync_to_async 모듈을 import 해준다.
from asgiref.sync import sync_to_async
async_function = sync_to_async(sync_function, thread_sensitive=False)
async_function = sync_to_async(sensitive_sync_function, thread_sensitive=True)
동기화 함수는 모두 메인 스레드에서 실행된다고 가정하며, 2가지 스레드 모드가 있다.
여기서 thread_sensitive 라는 값이 있는데, 기본 값은 True이다.
True로 설정하면 다른 기능들과 동일한 기존 스레드에서 실행되고, False로 설정하면 완전히 새로운 스레드에서 실행되며 호출이 완료되면 닫힌다.
from asgiref.sync import sync_to_async
@sync_to_async
def sync_function(...):
...
이렇게 sync 함수 상단에 데코레이터로 선언해주고 sync 함수 그대로 작성하면 해당 함수가 async로 작동하기 때문에 더욱 간편하게 사용 가능하다.
Django-ninja에서는 router를 이용해 URL을 설정한다.
이 때, sync_to_async 데코레이터와 함께 사용하려면 다음과 같은 순서에 맞춰 적용한다.
sync_to_async 데코레이터를 먼저, path를 나중에 작성!
@sync_to_async
@router.get("/test", response=TestSchema)
def test_func(request, input):
...