백엔드 개발을 하다 보면 실시간 데이터 처리가 필요한 경우가 많습니다. 특히 채팅 앱과 같은 어플리케이션에서는 실시간으로 메시지를 주고받는 것이 중요한 요소입니다. 이번 포스팅에서는 Django와 Redis를 활용하여 간단한 실시간 채팅 앱을 만드는 방법을 안내하겠습니다.
환경 설정
먼저, Django 프로젝트를 생성하고 필요한 라이브러리를 설치해야 합니다. 아래 명령어를 통해 Django와 Redis 패키지를 설치합니다.
pip install django channels channels_redis
Django Channels는 Django에서 WebSocket을 사용할 수 있게 해주는 라이브러리이며, channels_redis는 Redis를 백엔드로 사용하는 Channels의 데이터베이스입니다.
Django 프로젝트 생성
Django 프로젝트를 생성하고 기본 설정을 마무리합니다.
django-admin startproject chat_project
cd chat_project
python manage.py startapp chat
settings.py 파일에 chat 앱을 추가하고, Channels와 Redis 설정을 추가합니다.
INSTALLED_APPS = [
...
'channels',
'chat',
]
ASGI_APPLICATION = 'chat_project.asgi.application'
# Redis 설정
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
Redis 서버가 로컬에서 실행되고 있어야 합니다. Docker를 사용하여 Redis를 실행할 수 있습니다.
docker run -d -p 6379:6379 redis
ASGI 설정
ASGI 설정을 위해 asgi.py 파일을 수정합니다. Django Channels가 WebSocket 통신을 처리할 수 있도록 라우팅을 설정합니다.
# asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from chat.routing import websocket_urlpatterns
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chat_project.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns
)
),
})
WebSocket 라우팅 설정
chat 앱 내에 routing.py 파일을 만들고 WebSocket 라우팅을 설정합니다.
# chat/routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
Consumer 작성
이제 실제로 메시지를 처리할 Consumer를 작성합니다. chat 앱 내에 consumers.py 파일을 생성합니다.
# chat/consumers.py
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 = 'chat_%s' % 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_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# 방 그룹에 메시지 전송
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
async def chat_message(self, event):
message = event['message']
# WebSocket에 메시지 전송
await self.send(text_data=json.dumps({
'message': message
}))
HTML 템플릿 작성
채팅 방을 표시할 HTML 템플릿을 작성해야 합니다. chat/templates/chat 디렉토리를 만들고 room.html 파일을 생성합니다.
<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ room_name }}</title>
<script>
const roomName = "{{ room_name }}";
const chatSocket = new WebSocket("ws://" + window.location.host + "/ws/chat/" + roomName + "/");
chatSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
document.querySelector('#chat-log').value += (data.message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
document.querySelector('#chat-message-input').focus();
document.querySelector('#chat-message-input').onkeyup = function(e) {
if (e.keyCode === 13) { // Enter key
const messageInputDom = document.querySelector('#chat-message-input');
const message = messageInputDom.value;
chatSocket.send(JSON.stringify({'message': message}));
messageInputDom.value = '';
}
};
</script>
</head>
<body>
<textarea id="chat-log" cols="100" rows="20" readonly></textarea><br>
<input id="chat-message-input" type="text" size="100"><br>
</body>
</html>
뷰와 URL 설정
마지막으로 채팅 방을 렌더링할 뷰를 작성합니다. views.py 파일을 수정합니다.
# chat/views.py
from django.shortcuts import render
def room(request, room_name):
return render(request, 'chat/room.html', {
'room_name': room_name
})
이제 urls.py 파일에 URL 패턴을 추가합니다.
# chat/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('chat/<str:room_name>/', views.room, name='room'),
]
메인 urls.py 파일에 chat URL을 포함합니다.
# chat_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('chat.urls')),
]
실행하기
모든 설정이 완료되었습니다. 이제 Django 서버를 실행하여 채팅 앱을 확인할 수 있습니다.
python manage.py runserver
브라우저에서 http://localhost:8000/chat/room_name/에 접속하면 채팅 방에 입장할 수 있습니다. 여러 개의 브라우저 창에서 접속하여 실시간으로 메시지를 주고받는 기능을 확인해 보세요.
마무리
이번 포스팅을 통해 Django와 Redis를 사용하여 간단한 실시간 채팅 앱을 만드는 방법을 소개했습니다. 이 구조를 바탕으로 더 많은 기능을 추가하거나 UI를 개선하여 여러분만의 독창적인 채팅 앱으로 발전시킬 수 있습니다. 실시간 데이터 처리가 필요한 다양한 애플리케이션에 이와 같은 접근 방식을 활용해 보세요!