일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- c++
- django widget
- 알고리즘 문제
- django rest framework
- 파이썬
- HTML
- PYTHON
- js
- API
- django ORM
- react
- Git
- Algorithm
- Django
- java
- 알고리즘 풀이
- CSS
- form
- Baekjoon
- 백준
- DRF
- javascript
- 알고리즘
- 알고리즘 연습
- MAC
- 장고
- es6
- AWS
- web
- 파이썬 알고리즘
- Today
- Total
수학과의 좌충우돌 프로그래밍
[Django] Channels, 비동기적 채팅 구현하기 - WebSocket (3) 본문
- 소비자 개선
앞선 포스팅 WebSocket (2) 에서 작성했던 소비자는 동기적으로 작성되어 있습니다. 이렇게 함으로서 django 의 I/O 함수를 쉽게 호출할 수 있어 편리했습니다. 소비자를 비동기식으로 작성하게 되면 요청을 처리할 때, 추가적인 쓰레드를 생성하지 않습니다. 즉 성능 개션을 불러올 수 있는 것이죠. 실시간 채팅같은 경우에는 성능이 굉장히 중요한 요소이기 때문에 이 과정이 필요합니다.
앞에서도 한 번 언급했던
sync_to_async
를 통해서 django 의 동기적인 코드를 비동기적으로 수행하도록 할 수 있지만 지금 사용할async-native
라이브러리보다 성능이 떨어집니다.
# chat/consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
import json
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
}))
이전 글과 비교해보면 알 수 있겠지만, ChatConsumer
가 상속받는 것이 WebsocketConsumer
에서 AsyncWebsocketConsumer
으로 바뀌었습니다. 또한 메소드 선언 시, async
가 붙고, 메소드를 호출 하는 경우에도 await
를 붙여서 비동기 처리를 했습니다. 그 대신 앞에서 사용하던 async_to_sync
는 필요가 없어졌습니다.
-
Database Access
Django ORM은 동기식 코드이기 때문에 위와 같이 소비자를 비동기식으로 작성한 상태에서 접근하기 위해서는 해줘야할 작업이 있습니다.
# 방법 1 from channels.db import database_sync_to_async async def connect(self): self.username = await database_sync_to_async(self.get_name)() def get_name(self): return User.objects.all()[0].name
첫번째 방법은 database에 접근할 경우
database_sync_to_async
를 함께 호출해주는 것입니다. 위에서 봤던 것 처럼 메소드에async
와await
도 사용해주었습니다.# 방법 2 from channels.db import database_sync_to_async async def connect(self): self.username = await self.get_name() @database_sync_to_async def get_name(self): return User.objects.all()[0].name
두번째 방법은 데코레이터로서
database_sync_to_async
를 사용해주었습니다. 나머지는 위와 동일합니다.
'웹프로그래밍 > Django' 카테고리의 다른 글
[Django] model 더 알아보기, ORM, model의 option, migrate (0) | 2019.07.17 |
---|---|
[Django] visual studio code 를 이용한 debug (0) | 2019.07.14 |
[Django] Channels, 비동기적 채팅 구현하기 - WebSocket (2) (4) | 2019.07.11 |
[Django] Channels, 비동기적 채팅 구현하기 - WebSocket (1) (4) | 2019.07.10 |
[Django] ChoiceField 사용하기 (4) | 2019.07.06 |