292번째 줄: |
292번째 줄: |
| 레디스 서버를 이용한 실시간 채팅 구현. | | 레디스 서버를 이용한 실시간 채팅 구현. |
| | | |
− | 꽤 오래된 버전인 5를 사용하는데, 아마도 이는.. 5에서 처음으로 consumer groups이 구현된 버전인데, 이걸로 구현했기 때문이 아닐까 싶다. | + | 꽤 오래된 버전인 5를 사용하는데, 아마도 이는.. 5에서 처음으로 consumer groups이 구현된 버전인데, 이걸로 구현했기 때문이 아닐까 싶다.(최신버전에서도 될진.. 검증이 필요하다.) |
| ===사전설정=== | | ===사전설정=== |
| {| class="wikitable" | | {| class="wikitable" |
301번째 줄: |
301번째 줄: |
| | 서버 설치 | | | 서버 설치 |
| |설치 후 딱히 옵션을 변경할 내용은 없다. | | |설치 후 딱히 옵션을 변경할 내용은 없다. |
| + | 어차피 로컬에서 모든 작동이 수행되기 때문에. |
| | | |
− | 어차피 로컬에서 모든 작동이 수행되기 때문에.
| + | 네이티브로 설치하는 게 아니라 도커를 사용할 거라면 아래로 넘어가자. |
| |[http://id8436.iptime.org:8080/mediawiki/index.php/Radis Redis] 문서 참조. | | |[http://id8436.iptime.org:8080/mediawiki/index.php/Radis Redis] 문서 참조. |
| |- | | |- |
− | |서버 테스트 | + | |도커 |
− | |서버가 잘 설치되었는지 테스트. | + | |도커가 설치되어 있다면 아래 명령으로 바로 설치, 서비스가 시작된다. |
− | 서버 구동에 대한 메시지가 뜬다.
| + | |
− | |redis-server
| + | docker run -p 6379:6379 -d redis:5 |
| + | |아래 문서를 통해 도커 설치를 참고하자. |
| + | http://id8436.iptime.org:8080/mediawiki/index.php/Docker |
| |- | | |- |
| |연동 라이브러리 설치 | | |연동 라이브러리 설치 |
327번째 줄: |
330번째 줄: |
| } | | } |
| </syntaxhighlight>을 추가해준다. | | </syntaxhighlight>을 추가해준다. |
− | |- | + | |} |
− | |기능 확인
| + | ==기존 컨슈머 변형== |
− | |리눅스 기반의 OS에서 개발과 서비스를 하고 있다면 기능의 확인이 수월하겠지만... 윈도우 기반의 OS에서 개발이 진행된다면 쉽지 않다.
| + | 위에서 작성한 컨슈머는 중간 확인을 위한 동기식 함수인데, 비동기식으로 다시 쓰이면 성능이 좋아진다. 아래와 같이 변형하자.<syntaxhighlight lang="python"> |
− | 우측과 같이 파이썬 쉘을 통해 서버의 실행을 점검해보자.
| + | import json |
− | |<syntaxhighlight lang="bash">
| + | |
− | python3 manage.py shell
| + | from channels.generic.websocket import AsyncWebsocketConsumer |
− | >>> import channels.layers
| + | |
− | >>> channel_layer = channels.layers.get_channel_layer()
| + | |
− | >>> from asgiref.sync import async_to_sync
| + | class ChatConsumer(AsyncWebsocketConsumer): |
− | >>> async_to_sync(channel_layer.send)('test_channel', {'type': 'hello'})
| + | async def connect(self): |
− | >>> async_to_sync(channel_layer.receive)('test_channel')
| + | self.room_name = self.scope["url_route"]["kwargs"]["room_name"] |
− | {'type': 'hello'} | + | 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})) |
| </syntaxhighlight> | | </syntaxhighlight> |
− | |}
| |
| ==모델작성== | | ==모델작성== |
| chat 앱의 models.py 작성<syntaxhighlight lang="python"> | | chat 앱의 models.py 작성<syntaxhighlight lang="python"> |