본문 바로가기

Python/Django

[Django Channels 2.4.0] Building simple Chat Server / 채팅 서버 구현 튜토리얼 part.3 Rewrite Chat Server as Asynchronous

비동기적으로 동작하게 Consumer 수정

Synchronous consumers어떤 특별한 코드 없이 Django models에 접근할 수 있는 등, regular synchronous I/O functions을 호출할 수 있기에 편리하다는 장점이 있다.

반면에, Asynchronous consumers은 request를 다룰 때, 추가적인 threads를 만들 필요가 없기에 higher level of performance를 제공한다.

 

ChatConsumer은 async-native libraries(Channels and the channel layer)만을 사용하고, synchronous Django models에 접근하지 않는다. 그렇기에, 특별한 문제없이 asynchronous하게 바꿀 수 있다!

물론, synchronous django models를 사용하더라도, 추가적인 utility를 사용해서 바꿀 수 있지만, performance면에서는 조금 떨어질 수 있다.

 

chat/consumers.py를 다음 코드로 바꿔보자.

import json
from channels.generic.websocket import AsyncWebsocketConsumer # 그냥 WebsocketConsumer가 아님

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self): # 그냥 def가 아님
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'chat_%s' % self.room_name

        # Join room group
        # async_to_sync가 필요 없음(channel layer에서 method를 호출할 때)
        await self.channel_layer.group_add( # I/O를 수행할 때 await을 통해 async func을 호출한다.
            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
        }))

 

테스트를 해보자.

그전에!

Redis를 시작해야하는 것을 잊지 말자!

> python manage.py runserver

2개의 tab을 열고, 모두 http://127.0.0.1:8000/chat/lobby/ 에 들어가서 정상적으로 동작하는지 시험해보자.

 

이로써, chat server이 fully asynchronous 해졌다!