TIL/Django

[Django] Channels 사용하기 - 3

oraange 2022. 10. 24. 12:49

이 글은 [Django] Channels 사용하기 - 2에서 이어집니다.

비동기 consumer 작성하기

기존에는 동기적인 consumer를 만들었다. 동기 consumer는 특별한 코드없이 Django 모델에 동기적으로 접근할 수 있어서 편리하지만, 비동기 consumer는 추가 스레드를 생성할 필요가 없다는 점에서 높은 성능을 자아낸다.

기존에 사용하던 sync_to_async를 사용해도 되지만 async-native 라이브러리를 사용하는 것이 더 성능이 좋다.

이제 ChatConsumer를 비동기 형태로 바꿔보자. chat/consumers.py를 다음과 같이 바꾸자.

# chat/consumers.py
import json

from channels.generic.websocket import AsyncWebsocketConsumer


class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
        self.room_group_name = "chat_%s" % self.room_name

        # Join room group
        await self.channel_layer.group_add(self.room_group_name, self.channel_name)

        await self.accept()

    async def disconnect(self, close_code):
        # Leave room group
        await self.channel_layer.group_discard(self.room_group_name, self.channel_name)

    # Receive message from WebSocket
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]

        # Send message to room group
        await self.channel_layer.group_send(
            self.room_group_name, {"type": "chat_message", "message", message}
        )

    # Receive message from room group
    async def chat_message(self, event):
        message = event["message"]

        # Send message to WebSocket
        await self.send(text_data=json.dumps({"message": message}))
  • 기존 WebsocketConsumer를 상속받던 방식에서 AsyncWebsocketConsumer를 상속받게 되었다.
  • 모든 메소드가 def에서 async def로 바뀌었다.
  • await는 I/O를 수행하는 비동기 함수를 호출하는데 사용된다.
  • async_to_sync는 channel layer의 메소드를 호출할 때 더 이상 필요하지 않는다.

 

이제 다시 서버를 실행하면 비동기로 작동하는 채팅 서버가 열릴 것이다.

반응형