"2016-01-01" 이라는 문자열을 아래와 같이 사용하면 datetime 객체로 변환 가능

1
2
3
4
import date
 
test_date="2016-01-01"
convert_date = datetime.datetime.strptime(test_date, "%Y-%m-%d").date()
cs

"20160101"이라는 문자열을 아래와 같이 사용하면 역시 변환 가능

1
2
3
4
import date
 
test_date="20140206"
convert_date = datetime.datetime.strptime(test_date, "%Y%m%d").date()
cs

결과 값은 전부 "2016-01-01"의 datetime 객체 형태로 반환된다.


아래와 같이 strftime을 사용하여 현재일의 년월일을 문자열로 구할 수 있다.

1
today = datetime.datetime.today().strftime("%Y-%m-%d").split('-')
cs



Django는 파이썬에서 제공하는 웹프레임워크입니다. Django에는 코드를 자체적으로 테스트하기 위한 간단한 웹서버를 가지고 있고, 이를 실행하는 명령어는 runserver입니다. 

제품출시를 할 때에는 Django에서 제공하는 간단한 웹서버를 사용하는 것이 아닌, 보안이 더 좋고 강력한 웹서버가 필요합니다. 지금부터는 runserver로 Django 자체 웹서버를 실행하는 것이 아닌, uWSGI를 사용하여 Nginx와 연동하는 법을 설명하겠습니다.


사양

VIRTUAL BOXUbuntu-64bit 14.04 LTS
RAM2GB
HDD8GB
pythonpython 3.4.3
djangodjango 1.8.7


uWSGI 지원 플랫폼/시스템


개발에 앞서, uWSGI는 전 OS에 지원하는 것이 아닌, 특정 OS/System에만 지원을 합니다. 윈도우의 경우, uWSGI를 지원하지 않아서 pip로 다운로드가 불가능하며 동작하지 않습니다. 따라서 Virtual Box에 우분투 14.04를 설치하여 테스트 하였습니다. 

Platforms/Systems

Linux 2.6/3.x

FreeBSD >= 7

NetBSD

OpenBSD

DragonFlyBSD

Windows Cygwin

Mac OSX

Solaris >= 10

NexentaOS

SmartOS

OpenSolaris

OpenIndiana

OmniOS

Debian/kFreeBSD

GNU/Hurd


virtualenv 세팅


먼저 virtualenv를 설정해야 합니다. virtualenv를 사용하는 이유는 각 프로젝트 별로 필요로 하는 개발 환경이 다르기 때문입니다. 만약 이를 나누지 않고 하나로 사용하게 되면 전체 시스템에 패키지가 전체 설치가 되어 새로운 프로젝트에선 사용하지 않는 패키지가 존재하는 모습이 됩니다.


아래 명령어를 실행시켜 pip을 설치합니다.

$ sudo apt-get update
$ sudo apt-get install python3-pip

(본 가이드는 파이썬 3.4.3 버전을 사용하기 때문에 python3-pip를 다운받아 pip가 아닌, pip3 명령어를 사용합니다.)


pip3이 설치가 되었으면 virtualenv를 설치할 수 있습니다.

$ sudo pip3 install virtualenv


설치가 완료된 다음, 다음과 같이 명령어를 작성하여 'uwsgi-tutorial'란 이름으로 virtualenv를 생성한 뒤, 해당 폴더로 들어가 활성화 시킵니다.

$ virtualenv uwsgi-tutorial
$ cd uwsgi-tutorial
$ source bin/activate

활성화가 제대로 되었을 경우, hostname@server:~/uwsgi-tutorial에서 (uwsgi-tutorial)hostname@server:~/uwsgi-tutorial 이렇게 바뀝니다.


env가 활성화 되어있는 상태에서 django를 설치해줍니다. 

$ pip3 install django==1.8.7


설치가 완료된 후, 프로젝트를 생성한 다음, 해당 프로젝트로 이동합니다.

$ django-admin.py startproject testproject
$ cd uwsgi


여기까지 정상적으로 진행했을 시, 파일은 다음과 같습니다.


uWSGI 세팅


먼저 uWSGI를 설치합니다. 이때, source bin/activate된 상태를 유지해야 됩니다.

$ pip3 install uwsgi


다음 test.py를 ~/uwsgi-tutorial에 생성합니다.

#sudo vi test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"] # python3


uwsgi로 test.py을 실행시켜 작동하는지 확인합니다.


$ uwsgi --http :8000 --wsgi-file test.py


127.0.0.1:8000을 접속하면 hello world가 생성되어 아래와 같은 구조로 통신하는 것을 확인할 수 있습니다.

Web Client <-> uWSGI <-> Python


testproject 프로젝트로 들어가 아래의 명령어를 실행시킨 후, 웹에서 확인을 해보면 It works라는 문구가 나오는 것을 알 수 있습니다.

$ cd testproject
$ python3 manage.py runserver 0.0.0.0:8000


runserver로 실행시킨 것을 중지한 후, 이를 uWSGI로 변경해 실행시켜봅니다.

$ uwsgi --http :8000 --module testproject.wsgi

runserver로 실행시킨 것과 같이 웹에서 확인해보면 같은 문구가 나오는 것과 아래와 같은 구조로 통신하는 것을 알 수 있습니다.

Web Client <-> uWSGI <-> Django


Nginx 세팅


이 가이드에서는 웹서버를 Nginx를 선택하였습니다.

Nginx설치 후, virtualenv 폴더로 이동해 testproject_nginx.conf를 작성합니다.

$ cd ~/uwsgi-tutorial
$ sudo vi testproject_nginx.conf


생성한 .conf파일에 필요한 부분을 고쳐줍니다.

 # testproject_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
    # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
    # the port your site will be served on
    listen      8000;
    # the domain name it will serve for
    server_name .jinhwan.com; # substitute your machine's IP address or FQDN
    charset     utf-8;
    # max upload size
    client_max_body_size 75M;   # adjust to taste
    # Django media
    location /media  {
        alias /home/jinhwan/uwsgi-tutorial/testproject/media;  # your Django project's media files - amend as required
    }
    location /static {
        alias /home/jinhwan/uwsgi-tutorial/testproject/static; # your Django project's static files - amend as required
    }
    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /home/jinhwan/uwsgi-tutorial/testproject/uwsgi_params; # the uwsgi_params file you installed
    }
}



다음 심볼릭 링크를 생성합니다.

$ cd /etc/nginx/sites-enabled
$ sudo ln -s /home/jinhwan/uwsgi-tutorial/testproject_nginx.conf /etc/nginx/sites-enabled/


다음 프로젝트 폴더로 이동한 다음 settings.py 파일을 아래와 같이 추가하고

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

아래 명령어를 실행시킵니다.

$ python3 manage.py collectstatic

실행시킨 후, yes를 입력하면 static 폴더가 생성됩니다.

해당 프로젝트 내에 uwsgi_params 파일을 만든 다음, https://github.com/nginx/nginx/blob/master/conf/uwsgi_params이 안에 있는 데이터를 넣고 저장합니다.

Port을 사용한 uWSGI


앞서 만들어 놓은 test.py로 nginx와 uWSGI 연동을 확인하는 명령어입니다. 

$ uwsgi --socket :8001 --wsgi-file test.py


웹에서 확인하기 위해선 URL:8001로 확인하는 것이 아닌, 8000 포트로 확인합니다. 아래와 같은 구조로 되어 있으면서 사용자가 8000번 포트로 접속하면 작성한 testproject_nginx.conf 파일 내용과 같이 소켓을 통해 8001번을 호출하게 됩니다. 8001번은 위 uWSGI에서 사용한 포트이므로 test.py을 실행하여 클라이언트에게 보여주게 됩니다.  

the web client <-> the web server <-> the socket <-> uWSGI <-> Python

Unix socket을 사용한 uWSGI


앞서 uWSGI를 사용한 방법은 TCP port socket을 사용한 방법이였습니다. 이 방법을 사용하는 이유는 간단하기 때문입이다. 하지만 포트를 사용하는 것보단 유닉스 소켓을 사용하는 것이 오버헤드가 더 적기 때문에 좋습니다.

앞에서 작성한 testproject_nginx.conf를 수정합니다.

server unix:///tmp/testproject.sock; # for a file socket
# server 127.0.0.1:8001; # for a web port socket (we'll use this first)

nginx를 재시작 한 다음, 아래의 명령어를 실행합니다.

$ uwsgi --socket /tmp/testproject.sock --wsgi-file test.py --chmod-socket=666

--chmod-socket=666을 사용하는 이유는 권한이 없어 Permission Denied를 방지하기 위해 모든 사용자가 해당 파일에 대해 쓰기, 읽기 권한을 줍니다.

(666 대신 664를 입력해도 되지만 664를 입력해도 에러가 나서 666밖에 사용하지 않았습니다.)


만약 에러코드에 대해 확인해 보고 싶은 경우 /var/log/nginx/error.log 에서 확인할 수 있습니다.


Unix Socket을 사용해 Django 실행


먼저 프로젝트로 이동한 후, 해당 명령어를 입력, 웹에서 8000포트를 입력하면 It worked라는 문구가 나옵니다.

$ cd testproject
$  uwsgi --socket /tmp/testproject.sock --module testproject.wsgi --chmod-socket=666

.ini파일을 사용하여 uWSGI 실행


.ini파일을 설정하여 사용하는 이유는 uWSGI를 실행시키기 위해  공통적으로 사용되는 옵션들을 정리하여 보다 쉽게 구성하기 위함입니다.

또한 매번 긴 파일 경로를 사용하지 않아도 됩니다.


먼저 testproject_uwsgi.ini를 생성한 다음, 내부를 아래와 같이 작성합니다.

# mysite_uwsgi.ini file
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir           = /home/jinhwan/uwsgi-tutorial/testproject/
# Django's wsgi file
module          = testproject.wsgi
# the virtualenv (full path)
home            = /home/jinhwan/uwsgi-tutorial
# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 1
# the socket (use the full path to be safe
socket          = /tmp/testproject.sock
# ... with appropriate permissions - may be needed
 chmod-socket    = 666
# clear environment on exit
vacuum          = true


다음, 아래의 명령어를 실행시켜 확인합니다.

$ uwsgi --ini testproject_uwsgi.ini


worker processes의 갯수는 어느정도가 적당할까?

프로세스나 쓰레드의 갯수를 설정하기위한 규칙이나 제한은 없습니다. 해당 갯수는 시스템이나 응용 프로그램에 매우 의존적입니다. 이것의 갯수를 정하는 것은 processes = 2 * cpucores와 같은 단순한 수식으로는 적합하지 않습니다.

항상 해당 app에 대해 다양한 설정과 끊임없는 모니터링을 하여 실험을 할 필요가 있습니다. uwsgitop은 이러한 것들을 도와주는 좋은 도구가 될 수 있습니다.

시스템 전체에 uWSGI 설치


시스템이 부팅되었을 때, 자동으로 uWSGI를 시작하기 위해선 virtualenv만 아닌, 시스템 전체에 설치가 되어야 합니다.


아래 명령어로 virtualenv를 나간 후, 설치합니다.

$ deactivate
$ sudo pip3 install uwsgi


다음 uWSGI사용방법은 동일합니다.

Emperor mode


uWSGI는 'emperor' 모드를 실행할 수 있습니다. 이 모드는 uWSGI config files들의 directory를 감시하고 설정 파일을 발견했을 때, 각각 ('vassals')이라는 인스턴스를 생성합니다.

config file들이 수정될 때마다, emperor는 vassal을 자동적으로 재시작 합니다. emperor mode를 사용하기 위해선 .ini파일을 생성해야 합니다.


아래와 같이 명령어를 실행시킵니다. (실행 위치 상관 X) 마지막 명령어를 실행시키면 /etc/uwsgi/vassals/ 안에 심볼릭 링크가 생성된 것을 볼 수 있습니다.

$ sudo mkdir /etc/uwsgi
$ sudo mkdir /etc/uwsgi/vassals
$  sudo ln -s /home/jinhwan/uwsgi-tutorial/testproject_uwsgi.ini /etc/uwsgi/vassals/


다음 아래 명령어로 웹서버를 실행시킵니다.

uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data

문서에서는 sudo를 사용해야 할지도 모른다고 나와있지만 직접 사용했을 때, sudo가 없어도 되는 것을 알 수 있습니다.

위 명령어의 옵션:

emperor : vassals(config files)가 어디에 있는지 

uid: 시작하고 난 뒤, 프로세스의 유저 id

gid: 시작하고 난 뒤, 프로세스의 그룹 id

시스템 부팅될 때, uWSGI 자동 실행


이를 사용하기 위해선,  virtualenv에 uwsgi만 깔려 있어야 하는 것이 아닌, 시스템 전체에 uwsgi가 깔려 있어야 합니다. 


/etc 폴더 안의 rc.local에 다음과 같이 경로를 작성합니다.

 #!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data daemonize /var/log/uwsgi-emperor.log
exit 0

(재부팅시 에러가 납니다. - 위 코드 확인 필요)

  1. rootlee 2016.07.17 19:05

    글 정말 잘 읽었습니다. ^^ 친절하게 잘 설명해주셔서 잘따라할 수 있었습니다.

    그런데 궁금한 것이 8000번 포트로 deploy하는 경우,
    www.mydomain.com:8000 과 같이 domain 뒤에 8000을 붙여서 접속을 하게 되는데,
    일반적으로 홈페이지에 접속할 때는 8000없이 접속을 하잖아요.

    80포트로 하면 뒤에 8000을 안붙여도 접속이 될거 같아서 80포트로 옮기려 하는데, 이게 맞는 방법인지 잘 모르겠네요.
    일반적으로 deploy해서 웹사이트를 서비스 하는 경우, 어떤식으로 포트를 관리하는지 궁금합니다.

    항상 좋은 글 감사합니다 ! 그럼 좋은하루 되세요^^

    • 불곰1 2016.07.20 15:12 신고

      보통 웹사이트에서 배포를 하는 경우는 HTTP 기본포트인 80을 사용해 서비스를 합니다. 80 포트는 포트번호를 명시해주지 않아도 알기 때문이죠ㅎ

  2. haruholic 2016.10.11 20:03

    안녕하세요 ini 파일을 이용해서 시작하는 부분에서 no modue named django 라고 에러가 뜨는데 이유가 무엇인지 알 수 있을까요?

    • 불곰1 2016.10.16 14:40 신고

      혹시
      # Django's wsgi file
      module = testproject.wsgi 이 부분이 생략되어 있는게 아닐까요?
      아니면 장고 프로젝트가 아닌 파이썬 단일 파일을 ini로 실행하고자 해서 나는 에러일 수도 있을거 같네요

  3. 에리크 2016.10.13 14:32

    안녕하세요...장고를 스터디중입니다..글 잘 읽었습니다ㅣ..도움이 많이되고 있습니다
    주신자료를 참조하여 ...ubuntu+django+ngix+gunicorn으로 설정은 했는대..

    이상하게 , 소스코드를 변경(모델에 필드추가)하고 저장하면 브라우에서 바로바로 변경이 않되고..우분투를 OS를 restart 해야 변경된 사항이 브라우져에서 보입니다.

    예전에..python manage.py runserver 0:8000 할때는 바로바로 ㅂ소스코드변경을 확인가능했느데..제가 뭘 setting을 잘 못했느지 잘 모르겠습니다
    ..아니면 restart django 같은것이 혹시 있느지요?

    • 불곰1 2016.10.16 14:50 신고

      setting 파일보단 nginx만 재부팅하여 uwsgi를 재실행 해주면 될 것 같아요

      저도 해당 문제에 대해서 찾아본건 아니고 제 생각이지만 runserver는 장고에서 기본으로 제공해주기 때문에 값을 수정하고 다시 실행할 때 자동적으로 웹서버에 반영이 되는거 같아요

  4. 황영재 2017.02.14 09:43

    안녕하세요
    포스팅 따라서 django과 uwsgi 연동중에 확장자가 .wsgi 파일이 보이지 않아 문의 드려요
    python 2.7.10버전 사용중이구 우분투입니다
    근데 testproject.wsgi 파일을 modules에 지정하신다고 하셔서 그 부분 따라해 보려고 했는데
    제가 생성한 프로젝트에서는 아무리 찾아도 wsgi.py 는 있는데 확장명이 wsgi로 끝나는 파일은 찾을수가 없어서요

    • dudwo56@gmail.com 2017.02.14 09:48

      아 죄송합니다
      그게 아니였네요

  5. 80포트 2017.02.28 17:12

    80포트로 설정하는 방법이 뭔가요?ㅠㅜㅜ

    • 불곰1 2017.03.04 11:18 신고

      웹서버의 config파일에 포트를 지정할 수 있는 부분이 있습니다.
      nginx 같은 경우 xxxx.conf 파일 내의
      ...
      server { # the port your site will be served on listen 8000; # 이부분
      ...
      에서 포트를 수정할 수 있습니다!

  6. emperor mode(황제모드?)가 정확히 무엇인가요?
    저거 몰라도 장고앱 배포하는데 지장이 없나요?
    아주 소규모의 2~30명이 사용하는 정도의 웹인데 필요할까요?
    아니면 스킵해도 괜찮나요?
    저로선 무슨 소리인지 모르겠어서 말이죠....

    • 불곰1 2017.04.06 14:08 신고

      emperor mode는 한 서버 내에서 여러 uWSGI를 실행한다고 가정할 때, 관리를 위해서 사용하는 모드이기 때문에 생략하고 배포해도 무관합니다.

+ Random Posts