Channels 라이브러리가 개선됨에 따라 해당 시리즈의 내용이 유효하지 않은것 같습니다.

참고용으로만 봐주시길 바라며, 공식 문서를 참고해주세요!

 


어떤 프로젝트에서 챗봇을 구현하던 중, 클라이언트와 통신할 방법으로 WebSocket과 Redis pubsub을 생각하고 있었습니다.

여러 정보를 검색하던 중에, WebSocket과 Redis를 사용하여 통신을 하는 Channels 라이브러리를 알게 되었고, 좋은 라이브러리인 것 같아 정리를 하려 합니다.

 

튜토리얼이 잘 나와있어서 쉽게 적용할 수가 있었는데, 한글로 된 문서가 없는 것 같아서 정리를 하려고 합니다.

번역기의 힘을 빌려가며 해석을 했지만, 맞지 않는 부분이 있을 수 있기 때문에 원문과 참고하여 보시길 바랍니다.

 

이 글은 Django Channles 공식 문서를 참고하여 정리한 것입니다. ( 링크 )

 

 

Channels 소개

 

Django Channels 공식 문서에 따르면 Channles를 다음과 같이 소개하고 있습니다.

1) Web socket, Redis를 사용하여 채널을 관리

2) Django 자체는 동기식이지만, Channels를 사용하면 연결과 소켓을 비동기 처리

3) 현재 버전인 Channels 2는 python3.5 이상에서만 동작

4) ASGI( Async Server Gateway Interface )프로토콜은 WSGI와 잘 호환되도록 설계

 

ASGI( Asynchronous Server Gateway Interface )는 WSGI를 계승한 것으로 비동기 방식으로 실행되며,

웹 서버와 python 응용프로그램 간의 표준 인터페이스를 제공하기 위해 Django Channels와 배포에 사용되는 Daphne 서버에서 정의한 사양으로서 HTTP, HTTP/2 및 WebSocket와 같은 프로토콜을 지원합니다.

ASGI는 비동기 요청인 웹 소켓을 처리하는 이벤트로서 connect, send, receive, disconnect가 있습니다.

 

 

 

 

 

1. 프로젝트 및 애플리케이션 생성

$ django-admin.py startproject mysite $ python manage.py chat

생성된 chat 앱에서 __int__.py와 views.py 파일을 제외한 나머지 파일은 삭제합니다.

 

settings.py 파일에서 chat 앱을 추가합니다.

mysite/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'chat',
]

 

 

 

2. 준비작업 - 기본 설정

chat 앱에 templates 디렉터리와 그 안에 chat 디렉터리를 생성한 후, index.html 파일을 생성합니다.

 

 

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>

 

 

이어서 View를 작성합니다.

chat/views.py

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

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

 

 

URL 매핑을 위해 chat앱 내에 urls.py 파일을 생성한 후, 아래와 같이 작성합니다.

chat/urls.py

# chat/urls.py
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

 

 

chat/urls.py을 프로젝트의 urls.py에서 알 수 있도록 urlpatterns를 수정합니다.

mysite/urls.py

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^chat/', include('chat.urls')),
    url(r'^admin/', admin.site.urls),
]

 

 

 

 

3. 테스트

$ python manage.py runserver

브라우저에서 http://127.0.0.1:8000/chat/ 경로에 접속하면 아래와 같은 화면이 출력됩니다.

 

 

여기서 lobby를 입력한 후, enter를 누르면 URL이 http://127.0.0.1:8000/chat/lobby/으로 이동하는 것을 확인할 수 있습니다.

하지만 이에 대한 View를 작성하지 않았으므로 404를 반환합니다.

 

여기까지가 Channels을 사용하기 위한 Django 기본 작업입니다.

이제 Channels를 적용해보겠습니다.

 

 

 

 

4. Channels 라이브러리 통합

먼저 channels 패키지를 설치합니다.

$ pip install -U channels

 

그 다음 라우팅 config를 작성하겠습니다.

mysite/routing.py 파일을 생성 하여 아래와 같이 작성

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

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

 

 

다음으로 settings.py 파일에서 channels 앱을 등록하고, ASGI_APPLICATION을 추가합니다.

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',
]

# Channels
ASGI_APPLICATION = 'mysite.routing.application'

 

주의 할 것은 Channel 개발 서버가 다른 서드 파티 앱과 충돌이 발생할 수 있으므로, channels 앱을 INSTALLED_APPS에서 가장 위에 작성하는 것이 좋습니다.

이제 Channels가 chat 앱에 포함되므로, 이 채널은 runserver 명령을 제어하여, 표준 Django 개발 서버를 Channel 개발 서버로 대체하게 됩니다.

 

 

 

지금까지 잘 되었는지 테스트를 해보겠습니다.

$ python manage.py runserver

( ** No module named 'win32api' 에러가 발생한다면, pypiwin32 모듈을 설치합니다. 

     pypiwin32 모듈을 설치해도 에러가 발생하면 python manage.py migrate 명령을 실행하면 될 것입니다. )

 

 

서버를 실행했을 때, warning 메시지는 무시해도 됩니다.

주목할 것은 표준 Django 개발 서버가 아닌 ASGI/Channels 개발 서버가 시작됐다는 것입니다.

우선 브라우저에서 http://127.0.0.1:8000/chat/ 접속이 잘 되는지 확인만 하도록 합니다.

 

 

 

이상으로 Django Channels 튜토리얼 Part 1을 마치도록 하겠습니다.

Part 2에서는 본격적으로 Channels를 구현하겠습니다.

 

[ 참고 ]

https://channels.readthedocs.io/en/latest/index.html#django-channels