장고 채팅 서비스 박치기 05 - 로비 만들기

김민규·2025년 2월 25일
0

이번에는 gpt의 도움을 몇번 받았다.
channels의 공식 문서를 참고하였는데 아직도 잘 모르겠다...

생각할 수 있는 시나리오가 많아서 고민했었는데, 채팅 시 카카오톡의 오픈 채팅처럼 무작위 채팅에 들어갈 수 있는 형태의 서비스를 생각해보았다.
채팅방의 경우, 생성한 시간순으로 정렬되는 느낌으로...

config/settings.py

LOGIN_REDIRECT_URL = "chat-lobby"

로그인 시 redirect 위치를 로비로 수정해주었다.

templates/ws_chat/chatLobby.html

{% for room in rooms %}
    <a href="{% url 'chat_room' room.id %}">{{ room.title }}</a><br>
{% endfor %}

채팅 로비의 경우, 임시로 채팅방 이름만 출력하도록 해두었다. 지금보니 url-name이 잘못되어있다...

consumer는 아래와 같이 수정해줬다.

import json
from channels.generic.websocket import AsyncWebsocketConsumer

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = f'chat_{self.room_name}'
        
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )
        await self.accept()
    
    async def disconnect(self, close_code):
        await self.channel.name.group_discard(
            self.room_group_name,
            self.channel_name
        )
        
    async def receive(self, text_data):
        data = json.loads(text_data)
        message = data["message"]
        username = data["username"]
        
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                "type" : "sendMessage",
                "message" : message,
                "username" : username,
            } )
    
    async def sendMessage(self, event):
        message = event["message"]
        username = event["username"]
        
        await self.send(text_data = json.dumps(
            {"message" : message, "username" : username}))

형태는 크게 바뀌지 않았다. 채팅방 이름을 채널 레이어에 저장할 수 있게 만들었다!

models.py

from django.db import models
from django.contrib.auth.models import User
# Create your models here.

class ChatRoom(models.Model):
    title = models.CharField(max_length = 255)
    description = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)
    
    def __str__(self) -> str:
        return self.title

class Message(models.Model):
    chatroom = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name="messages")
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.user.username}: {self.content[:20]}"

DB에 저장해야 하기 때문에 모델을 추가해주었다. 채팅방과 메시지를 기록해준다.

채팅 로비또한 수정했기 때문에 url도 수정해야 한다.
먼저 routing.py의 path를 수정해주었다.

websocket_urlpatterns = [
   path("chat/<str:room_name>/" , ChatConsumer.as_asgi()) , 
] 

다음으로 urls.py이다. 여기도 비슷하게 추가 및 수정해주었다.

    path("", chat_views.chatLobby, name='chat-lobby'),
    path("chat/<str:room_name>/", chat_views.chatPage, name="chat-page"),

채팅방을 보여줄 채팅 로비 또한 만들어주어야 한다. views.py를 통해 만들어 주었다.

def chatLobby(request, *args, **kwargs):
    if not request.user.is_authenticated:
        return redirect("login-user")
    
    # order by recently
    rooms = ChatRoom.objects.order_by("-created_at")
    return render(request, "ws_chat/chatLobby.html", {"rooms": rooms})

채팅 로비의 경우 아직 보여주는 것만 존재하고 생성이 안되기 때문에 현재 서버를 키게 되면 아무것도 없는 빈 화면이 출력된다.
다음에는 채팅방의 CRUD 기능을 추가해야 할 것 같다.

profile
공부 기록용

0개의 댓글

관련 채용 정보