세월호 고인의 명복을 빕니다.
이번에는 channel layer와 consumer를 작성해서 채팅이 가능하게 만들어 보겠다.
먼저 consumer를 작성해 주는데 consumer는 websocket에 연결 및 전반적인 부분을 담당한다.
# chat/consumers.py
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
import json
class ChatConsumer(WebsocketConsumer):
def connect(self):
# chat/routing.py 에 있는
# url(r'^ws/chat/(?P<room_name>[^/]+)/$', consumers.ChatConsumer),
# 에서 room_name 을 가져옵니다.
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# 그룹에 join
# send 등 과 같은 동기적인 함수를 비동기적으로 사용하기 위해서는 async_to_sync 로 감싸줘야한다.
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name
)
# WebSocket 연결
self.accept()
def disconnect(self, close_code):
# 그룹에서 Leave
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name
)
# WebSocket 으로부터 메세지 receive
def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# room group 에게 메세지 send
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
# room group 에서 메세지 receive
def chat_message(self, event):
message = event['message']
# WebSocket 에게 메세지 전송
self.send(text_data=json.dumps({
'message': message
}))
이제 이 소비자를 라우팅 해주어야 하는데 django의 url과 다른 곳에서 처리해준다. 방식은 비슷하다.
# chat/routing.py
from django.conf.urls import url
from . import consumers
websocket_urlpatterns = [
url(r'^ws/chat/(?P<room_name>[^/]+)/$', consumers.ChatConsumer.as_asgi()),
]
# mysite/routing.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import chat.routing
# 클라이언트와 Channels 개발 서버가 연결 될 때, 어느 protocol 타입의 연결인지
application = ProtocolTypeRouter({
# (http->django views is added by default)
# 만약에 websocket protocol 이라면, AuthMiddlewareStack
'websocket': AuthMiddlewareStack(
# URLRouter 로 연결, 소비자의 라우트 연결 HTTP path를 조사
URLRouter(
chat.routing.websocket_urlpatterns
)
),
})
이렇게 하면 컨슈머를 통해 내가 보낸 채팅이 나의 room.html에 뿌려 진다. 하지만 공유는 되지 않는다. 공유를 위해서는 channel layer를 추가해 주어야 한다. 각 컨슈머들은 하나의 채널을 가지고 channel layer를 통해 채팅을 하는 구조이다.
channel layer를 추가해 주고
# settings.py
ASGI_APPLICATION = 'mysite.routing.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
이렇게 channel layer를 연결해 주면 채팅이 가능하게 된다. 다음에는 nginx에 channels를 연결하는 부분을 포스팅하겠다.
'Python' 카테고리의 다른 글
[pandas] 여러개의 csv 파일 하나로 합치기 (0) | 2021.06.08 |
---|---|
[django] Rest Framework tutorial #3 views - 2 (0) | 2021.05.06 |
[django] Rest Framework tutorial #2 views - 1 (0) | 2021.05.03 |
[django] Rest Framework tutorial #1 Serialization (0) | 2021.04.26 |
[django] channels tutorial #1 (0) | 2021.04.14 |
댓글