[Python/Django]
파이썬 장고 Channels 웹소켓 실시간 채팅 웹서비스 개발 I

2020. 1. 20. 10:04


728x90

기본 설정

이 튜토리얼에서는 파이썬 장고의 웹소켓 Channels를 이용하여 실시간 채팅 웹서비스를 개발합니다.

해당 튜토리얼은 Django 사이트를 구축하기위한 기본 개념에 익숙하다고 가정합니다.
만약 Django가 아직 익숙하지 않다면, Django 튜토리얼을 먼저 완료 한 다음 이 튜토리얼을 학습하는것이 좋습니다.

Django가 이미 설치되어 있다고 가정합니다. 명령창에서 다음 명령을 실행하여 Django가 설치되어있는지, 설치되어있다면 어떤 버전인지 알 수 있습니다.

$ python3 -m django --version

Django가 설치되어있다면, Channel을 설치합니다. 아래 명령을 통해 설치할 수 있습니다.

$ pip3 install -U channel

이 튜토리얼은 Python 3.5 이상 및 Django 1.11 이상을 지원하는 Channels 2.0 용으로 작성되었습니다.
이 튜토리얼은 Redis를 설치하고 실행합니다. Redis를 채널 레이어의 백업 저장소로 사용합니다.

Windows 사용자의 경우 아래 Redis 설치파일을 이용하여 Redis를 설치할 수 있습니다.

Redis-x64-3.2.100.msi
5.80MB

Mac 사용자의 경우 brew가 설치되어있다는 가정 하에 아래 명령을 터미널에서 실행하여 Redis를 설치할 수 있습니다.

$ brew install redis

만약 brew가 설치되어있지 않다면 아래 명령을 터미널에서 실행하여 brew를 설치할 수 있습니다.

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

위의 과정을 마쳐 Redis가 정상적으로 설치되었을 경우 아래 명령을 실행하여 Redis가 인터페이스를 사용할 수 있도록 합니다.

$ pip install channels_redis

 

프로젝트 만들기

Django 프로젝트가 없는 경우 프로젝트를 생성해야합니다.

명령창에서 프로젝트를 저장하고자 하는 디렉토리로 이동 한 후 다음 명령을 실행합니다.

$ django-admin startproject mysite

프로젝트가 정상적으로 생성될 경우 아래와 같은 구조를 가진 디렉토리가 생성됩니다.

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py

 

채팅 앱 만들기

명령창에서 생성한 프로젝트의 디렉터리로 들어갑니다.
이후 해당 디렉토리에 "manage.py" 파일이 존재하는지 확인하고 다음 명령을 실행합니다.

$ python3 manage.py startapp chat

정상적으로 명령이 실행되었을 경우 다음과 같은 구조를 지닌 디렉토리가 생성됩니다.

chat/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

 

이후 프로젝트에 chat앱이 설치되었음을 명시해야합니다.
따라서 "mysite/settings.py"파일의 INSTALLED_APPS 항목을 다음과 같이 수정합니다.

# mysite/settings.py
INSTALLED_APPS = [
    'chat',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Index View 추가

이제 대화방의 이름을 입력 할 수 있는 인덱스 페이지를 만듭니다.

"chat/templates/chat/" 디렉토리를 생성합니다 "chat"앱의 디렉토리는 이제 다음과 같아야 합니다.

chat/
    __init__.py
    templates/
        chat/
            index.html
    views.py

"chat/templates/chat/index.html" 파일을 생성합니다.

<!-- chat/templates/chat/index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Rooms</title>
</head>
<body>
    What chat room would you like to enter?<br/>
    <input id="room-name-input" type="text" size="100"/><br/>
    <input id="room-name-submit" type="button" value="Enter"/>

    <script>
        document.querySelector('#room-name-input').focus();
        document.querySelector('#room-name-input').onkeyup = function(e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#room-name-submit').click();
            }
        };

        document.querySelector('#room-name-submit').onclick = function(e) {
            var roomName = document.querySelector('#room-name-input').value;
            window.location.pathname = '/chat/' + roomName + '/';
        };
    </script>
</body>
</html>

Index HTML 페이지에 대한 view 기능을 만듭니다. "chat/views.py" 파일을 다음과 같이 수정합니다.

# chat/views.py
from django.shortcuts import render

def index(request):
    return render(request, 'chat/index.html', {})

해당 view를 호출하려면 view를 URL에 매핑해야합니다. 이를 위해 "chat" 디렉토리에 "urls.py"라는 파일을 생성해야 하며 정상적으로 생성했을 경우 "chat"디렉토리의 구조는 다음과 같습니다.

chat/
    __init__.py
    templates/
        chat/
            index.html
    urls.py
    views.py

이제 이 "urls.py" 파일을 다음과 같이 수정합니다.

# chat/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

"chat/urls.py" 파일을 수정하여 URL을 맵핑하고 나서 해주어야 할 것은 앱의 URL을 맵핑했으니 루트 urls.py("mysite/urls.py") 역시 수정해주어야합니다.

# mysite/urls.py
from django.conf.urls import include
from django.urls import path
from django.contrib import admin

urlpatterns = [
    path('chat/', include('chat.urls')),
    path('admin/', admin.site.urls),
]

위 과정이 끝났다면, 명령창에서 다음 명령을 실행합니다.

$ python3 manage.py runserver

브라우저에서 http://127.0.0.1:8000/chat/ 으로 이동하면 채팅방의 이름을 입력하기 위한 텍스트 입력 페이지로 접속할 수 있습니다.

방 이름으로 "lobby"를 입력하고 Enter 키를 누르면 http://127.0.0.1:8000/chat/lobby/로 리디렉션되지만, 아직 채팅방에 대한 코드를 작성하지 않았기 때문에 "페이지를 찾을 수 없음" 이라는 오류 페이지가 표시됩니다.

Channel 라이브러리 통합

지금까지 일반 Django 앱을 만들었습니다. 아직까지는 Channel 라이브러리를 전혀 사용하지 않았습니다.
이제 채널을 통합 할 차례입니다.

Channel에 대한 루트 라우팅 구성을 만들어 보겠습니다. Channel 라우팅 구성은 채널 서버에서 HTTP 요청을 수신 할 때 실행할 코드를 채널에 알려준다는 점에서 Django URLconf와 유사합니다.

빈 라우팅 구성으로 시작하겠습니다. "mysite/routing.py"파일을 생성 및 작성합니다.

# mysite/routing.py
from channels.routing import ProtocolTypeRouter

application = ProtocolTypeRouter({
    # (http->django views is added by default)
})

이제 설치된 라이브러리 목록에 채널 라이브러리를 추가합니다. "mysite/settings.py" 파일을 편집합니다.
"settings.py"파일의 INSTALLED_APPS 항목에 channels를 추가합니다.

# mysite/settings.py
INSTALLED_APPS = [
    'channels',
    'chat',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

루트 라우팅 구성에서 채널을 가리켜야합니다. "mysite/settings.py"파일의 하단에 다음을 추가합니다.

# mysite/settings.py
# Channels
ASGI_APPLICATION = 'mysite.routing.application'

이제 runserver 명령을 사용하여 서버를 부팅할 때 channel로 인해 표준 Django 개발 서버가 아닌 채널 개발 서버로 전환됩니다.

모든 설정이 끝났으면 채널 개발 서버가 올바르게 작동하는지 확인하기 위해 다음 명령을 실행합니다.

$ python3 manage.py runserver