Django에서 실시간 알람을 구현하기위해서는 웹소켓을 통해서 사용자와 서버와의 실시간 연결을 통해 메세지를 보내야합니다. 이거를 하기위해서 asgi서버인 daphne 서버 세팅을 하고 알림의 조건에 맞추어서 ws로 메세지를 보내면됩니다
이거를 하기위해서 메세지 브로커인 redis를 settings에 설정을 해주고 INSTALLED_APPS에 daphne를 추가시켜줍니다
INSTALLED_APPS = [
"daphne",
...
]
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("redis", 6379)],
},
},
}
ASGI_APPLICATION = "프로젝트.asgi.application"
그후 asgi.py에서
import os
from channels.routing import ProtocolTypeRouter
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
application = ProtocolTypeRouter(
{
"http": get_asgi_application(),
"websocket": AllowedHostsOriginValidator(
AuthMiddlewareStack(URLRouter(chat.routing.websocket_urlpatterns))
),
}
)
설정을 해주면되는데 저희 프로젝트는 jwt token을 이용해서 로그인을 구현했기때문에 websocket를 따로 커스텀을 해가지고 구현을 했습니다
application = ProtocolTypeRouter(
{
"http": get_asgi_application(),
"websocket": JwtAuthMiddlewareStack(
URLRouter(alarm.routing.websocket_urlpatterns),
),
}
)
그후 alarm앱에서 라우팅을 해준다음에 comsumer에서
from django.urls import path
from . import consumers
websocket_urlpatterns = [
path("ws/alarm/", consumers.AlarmConsumer.as_asgi()),
]
import json
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer
from .models import Alarm
from .serializers import AlarmSerializer
def get_alarm(user):
notifications = Alarm.objects.filter(user=user)
serializer = AlarmSerializer(notifications, many=True)
return serializer.data
class AlarmConsumer(AsyncWebsocketConsumer):
async def connect(self):
user = self.scope.get("user")
self.group_name = f"user{user.id}"
await self.channel_layer.group_add(self.group_name, self.channel_name)
await self.accept()
alarms = await database_sync_to_async(get_alarm)(user)
if alarms:
await self.channel_layer.group_send(
self.group_name, {"type": "send_alarm", "message": alarms}
)
async def disconnect(self, close_code):
await self.channel_layer.group_discard(self.group_name, self.channel_name)
async def send_alarm(self, event):
message = event["message"]
await self.send(text_data=json.dumps({"message": message}))
위 처럼 ws가 연결되었을때 메세지를 보낼때 끊길때를 작성해 주면 프론트에서 웹소켓으로 ws/alarm으로 연결했을때 connect가 실행이되고 끊길때 disconnect가 실행이되게됩니다
'내일배움 캠프 > TIL' 카테고리의 다른 글
Django, Celery, rabbitmq를 docker compose로 deploy하기 (0) | 2023.07.20 |
---|---|
django-channels middleware custom (0) | 2023.07.20 |
django-channels (0) | 2023.07.20 |
asgi 서버랑 wsgi서버의 차이점 (0) | 2023.07.19 |
simple jwt token 커스터마이징 (0) | 2023.06.15 |