Code

장고 도움말 페이지로 가기

mod_python에서 장고 운영하기

Apache with mod_python은 제품 서버(production server)에서 장고를 사용하기 위해 현재 가장 선호되는 설정입니다.

mod_python은 mod_perl과 유사합니다 : 아파치 내에서 파이썬을 임베딩하고, 아파치가 시작할때 파이썬 코드를 메모리에 로드합니다. 코드는 아파치 프로세스가 살아있는 동안 메모리에 남아 있으며, 이는 다른 서버구성보다 주목할만한 성능 향상을 이끌어 냅니다.

장고는 아파치 버전 2.x 이상과 mod_python 버전 3.x 이상을 필요로 하며, 반드시 worker MPM에 대신 prefork MPM 아파치를 사용해야 합니다.

FastCGI, SCGI 또는 AJP 에서 장고 운영하기?도 살펴보세요. (SCGI와 AJP 또한 다룹니다).

기본 설정

mod_python에서 장고를 설정하기 위해서, 먼저 mod_python 모듈이 활성화된 아파치가 설치되어 있어야 합니다,

그리고 나서 httpd.conf 파일을 열어서 다음을 추가하십시오

<Location "/mysite/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    PythonDebug On
</Location>

DJANGO_SETTINGS_MODULE에는 mysite.settings를 장고 프로젝트의 설정 파일의 파이썬 경로로 다시 설정하시기 바랍니다. 위 설정은, "장고에서는 mod_python 핸들러를 사용해서, '/mysite/' 아래 모든 URL에 대해서 mod_python을 사용한다."는 설정입니다. mod_python은 어떤 설정을 사용해야 하는지 DJANGO_SETTINGS_MODULE의 값으로 알수 있습니다.

<Directory> 지시자가 아니라, <Location> 지시자가 사용되고 있는 것에 주의하세요. <Directory>는 파일시스템상의 위치를 가리키는데 반해, <Location>은 웹사이트의 URL에서의 위치를 가리킵니다. 여기서는 <Directory> 가 의미 없습니다.

또, 만약 장고 프로젝트가 기본 PYTHONPATH 안에 없다면, 프로젝트를 어디서 찾아야 하는지를 mod_python에게 알려줘야 합니다.

<Location "/mysite/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    PythonDebug On
    PythonPath "['/path/to/project'] + sys.path"
</Location>

여기서 사용하는 PythonPath 값은 어플리케이션에서 import 하려고 하는 모든 모듈들의 부모 디렉토리를 반드시 포함해야 합니다. 또한 DJANGO_SETTINGS_MODULE 의 실제 경로도 포함해야 합니다. 이 점은 바로 파이썬을 대화형으로 사용할때 path를 설정하는 것과 똑같은 상황입니다. 파이썬에서는 import 할때마다, import가 성공할 때까지 sys.path 안의 모든 디렉토리를 처음부터 끝까지 차례로 시도해 봅니다.

다음 예를 보면 확실해 집니다. 가령 /usr/local/django-apps/ 디렉토리 아래에 어떤 어플리케이션 (/usr/local/django-apps/weblog/ 같은)이 있고, 설정 파일은 /var/www/mysite/settings.py 이라서 DJANGO_SETTINGS_MODULE 를 위의 예제처럼 설정했습니다. 이 경우, PythonPath 지시자를 아래와 같이 작성할 필요가 있습니다

	PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path"

이 path 에서, import weblogimport mysite.settings 둘 다 작동합니다. 만약 코드 어딘가에 import blogroll가 있고 blogrollweblog/ 디렉토리 아래에 위치하고 있다면, *또한* /usr/local/django-apps/weblog/PythonPath 안에 넣어야 합니다. 기억하십시오: 직접 import 하려고 하는 모든 것들의 부모 디렉토리는 반드시 파이썬 path 상에 있어야 합니다.

만약 Windows를 사용중이라면, 일반적으로 Windows는 역슬래시 문자(\)를
경로 구분자로 사용하지만, 우리는 여전히 슬래시(/)를 경로에 사용하기를 바랍니다.
 아파치는 경로 문자를 어떻게 운영체제에 맞게 변경할지 이미 알기 때문에,
슬래쉬를 사용하는 편이 간편하고(portable) 더 읽기 쉽습니다.
(이는 이중-이스케이프 역슬래시(\\) 문제를 피하는 꽁수입니다.)

Windows 시스템에서도 역시 마찬가지입니다.

PythonPath "['c:/path/to/project'] + sys.path"

또한 성능을 위해서 PythonAutoReload Off 지시자를 사용할 수도 있습니다. 전체 옵션들은 mod_python 문서에서 볼 수 있습니다.

실제로 외부로 서비스할 때는 반드시 PythonDebug Off로 설정해야 합니다. PythonDebug On 인 채로 두면, mod_python 안에서 뭔가 잘못 되었을때

사용자들은 보기 흉한(그리고 적나라한) 에러메세지를 보게 됩니다.

아파치를 재시작하면, 모든 요청을 장고가 처리를 합니다. 장고의 URLconf는 "/mysite/" 를 처리하지 않습니다.

장고를 mod_python으로 실행할 때, 파이썬 코드를 변경할때마다 아파치를 재시작(reload 또는 restart)할 필요가 있습니다.

한글 파일 경로를 사용할 경우 유의사항

(이 부분은 non-ascii 문자를 파일시스템에 사용하는 경우에만 해당합니다.)

한글과 같은 유니코드 영역 문자들을 파일시스템에서 사용하려고 할 경우 다음 사항에 주의해야 합니다.

  • Django 개발 서버로 실행할 때 : 해당 사용자 계정의 LANG 환경 변수가 올바르게 설정되었는지 확인 (보통 한국어의 경우 ko_KR.UTF-8)
  • Apache mod_python 또는 mod_wsgi 환경에서 실행할 때 : /etc/apache2/envvars에 다음과 같은 설정이 추가되어야 함
    export LANG=ko_KR.UTF-8
    export LC_ALL=ko_KR.UTF-8
    

이렇게 해야만 Python의 os, os.path 모듈에서 유니코드 문자열로 된 한글 경로명을 올바로 처리할 수 있습니다.

아파치 하나로 장고 여러개 실행하기

아파치 하나로 여러개의 장고를 실행 시킬 수 있습니다. 바로 VirtualHost를 사용하면 됩니다.

NameVirtualHost *

<VirtualHost *>
    ServerName www.example.com
    # ...
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</VirtualHost>

<VirtualHost *>
    ServerName www2.example.com
    # ...
    SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
</VirtualHost>

만약 같은 VirtualHost에서 장고를 하나 이상 실행해야 한다면, mod_python이 꼬이지 않도록 특별한 방법이 필요합니다. 다음과 같이 PythonInterpreter 지시자를 사용하여 각기 다른 <Location> 지시자들이 인터프리터를 분리하도록 하십시오

<VirtualHost *>
    ServerName www.example.com
    # ...
    <Location "/something">
        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
        PythonInterpreter mysite
    </Location>

    <Location "/otherthing">
        SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
        PythonInterpreter othersite
    </Location>
</VirtualHost>

각기 다른 두개의 Location 블럭 안에만 있으면, PythonInterpreter의 값은 전혀 문제되지 않습니다.

mod_python에서 개발 서버(developement server) 실행하기

만약 개발 서버(developement server)에서 mod_python을 사용한다면, 코드를 바꿀때마다 아파치를 재시작 해야하는 합니다. 아주 불편합니다. 코드를 조금만 바꿔도 아파치를 다시 재시작해야하니까요. 개발할 때, 이런 불편함을 피하는 방법이 있습니다. 바로 httpd.conf 파일에 MaxRequestsPerChild 1을 설정해서 매 요청마다 강제로 아파치가 모든 것을 다시 시작하도록 만들 수 있습니다.

하지만 실제 서비스에서는 이 방법은 당연히 성능에 문제를 일으킵니다. 사용하지 마십시오.

만약 여러분이 여기저기 흩어진 print 문을 사용하여 디버깅하는 데 익숙한 개발자라면, mod_python 환경에서는 print로 출력해도 그 결과를 확인할 수 없습니다.; 혹시 아파치 로그에 있지 않을까 생각했다면, 잘못 생각했습니다. 보이지 않습니다. mod_python 환경에서 디버깅 정보를 찍어야 할 때는,

assert False, 내가_알고_싶은_값

미디어 파일 처리하기

장고 자체는 고정된 파일들을 처리하지 않습니다; 장고는 웹 서버에게 넘깁니다.

우리는 분리된 웹서버 — 즉, 장고를 실행하지 않는 — 미디어 처리를 위한 별도의 웹서버를 사용할것을 권합니다. 여기 이런 용도에 맞는 좋은 서버들이 있습니다

그렇지만, 만약 선택의 여지가 없고 장고가 실행되는 아파치 VirtualHost에서 미디어 파일들을 처리해야 한다면, 사이트 특정 부분의 mod_python 을 끄는 방법이 있습니다

<Location "/media">
    SetHandler None
</Location>

바로 Location을 미디어 파일들의 루트 주소 URL로 변경하십시오. 정규 표현식으로 매치하기 위해 <LocationMatch>를 사용할 수도 있습니다.

아래 예는 다른 경로는 장고를 사용하지만 media 서브디렉토리와 .jpg, .gif 또는 .png로 끝나는 URL은 아파치에서 처리하도록 합니다.

<Location "/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</Location>

<Location "/media">
    SetHandler None
</Location>

<LocationMatch "\.(jpg|gif|png)$">
    SetHandler None
</LocationMatch>

admin 파일들 처리하기

장고 개발 서버는 자동으로 admin media 파일들을 처리하지만, 그 외에는 처리하지 않을 수도 있다는 점에 주의하세요. admin 파일들을 처리하기 위해, 아파치, 또는 사용 중인 미디어 서버에 대한 설정을 해야 합니다.

admin 파일은 장고 배포판의 (django/contrib/admin/media) 에 있습니다.

여기 두가지 방법이 있습니다

  1. document root 내에 admin media 파일에 대한 심볼릭 링크를 만듭니다. 이 경우, 모든 장고 관련 파일들 — 코드 그리고 템플릿들 — 은 한 장소에 있게되며, 여전히 변경된 최신의 admin 템플릿들을 얻기 위해, svn update를 할 수 있습니다.
  2. 또는, 아파치 document root 안에 admin media 파일들을 복사합니다.

mod_python에서 eggs 사용하기

만약 Python egg에서 장고를 설치했거나 장고 프로젝트에 egg를 사용 중이라면, 추가 설정이 필요합니다. 프로젝트(또는 어딘가에)에 아래와 같은 내용을 포함하는 별도의 파일을 생성하십시오

import os
os.environ['PYTHON_EGG_CACHE'] = '/some/directory'

여기, /some/directory 는 아파치 프로세스가 쓰기 권한을 가진 디렉토리입니다. egg가 사용될 때 egg 코드들이 임시로 압축이 해제되는 곳으로 사용됩니다.

그리고나서 mod_python에게 다른 무엇보다도 먼저 이 파일을 import할 것을 지정해야 합니다. 이는 mod_python에 PythonImport 지시자를 사용하면 됩니다. mod_python에는 위에서 설명한대로 PythonInterpreter 지시자를 명시해둬야 합니다 (이 경우 다중 설치를 사용 하지 않더라도 이것을 해야 합니다). 그리고 나서 PythonImport 줄을 메인 서버 설정에 추가 하십시오(즉, Location 또는 VirtualHost 섹션의 바깥). 예를 들어

PythonInterpreter my_django
PythonImport /path/to/my/project/file.py my_django

mod_python 매뉴얼에서 설명한 대로 절대 경로(또는 일반적인 도트 import 경로)를 사용할 수 있습니다. 우리는 프로젝트에 접근 하기 위해 파이썬 path 수정이 필요할 수도 있는데, PythonImport 라인이 처리되는 시점에서는 이것이 아직 완료가 되지 않았기 때문에 위의 예제에서 우리는 절대 경로를 사용했습니다.

에러 처리

아파치 mod_python을 사용할 때, 에러는 장고에서 잡힙니다 - 즉, 장고에서 발생하는 에러는 아파치로 전달되지 않고, 당연히 아파치 error_log 에도 나타나지 않습니다.

단, 예외가 있다면 장고 애플리케이션에서 무언가 정말 있을 수 없는 일이 발생한 경우입니다. 이 경우, 브라우저에서 "Internal Server Error" 페이지가 나타나면서 파이썬 에러메세지가 아파치 error_log 파일에 남겨집니다. 이 에러메세지는 여러줄에 걸쳐 출력됩니다. (예, 이것은 보기 흉하고 읽기도 어렵습니다만, 이게 mod_python 이 처리하는 방식입니다.)

segment fault 가 났다면

만약 아파치가 segment fault 에러를 낸다면, 예상되는 두가지 원인이 있습니다. 둘다 장고 자체의 문제가 아닙니다.

  1. 파이썬 코드가 아파치에 올려진 버전과 충돌나는 "pyexpat" 모듈을 임포팅 하고 있기

때문일 수 있습니다. 자세한 정보는 Expat Causing Apache Crash 를 보십시오.

  1. 데이터베이스로 MySQL을 사용하여 mod_python과 mod_php를 동일 아파치 인스턴스에서 실행중이기 때문일 수 있습니다. 어떤 경우, 이는 PHP와 Python의 MySQL의 버전 충돌에 의한 것으로 알려진 mod_python 버그를

발생시킵니다. mod_python FAQ entry에 전체 정보가 있습니다.

mod_python에서 문제가 계속된다면, 장고를 제외한 채로, mod_python만 설정해서 기본 사이트가 잘 작동하는지 확인해봅니다. 이렇게 해서 문제를 고립시켜서 원인을 파악할 수 있습니다. Getting mod_python Working에 이 절차가 자세하게 있습니다.

다음 단계는 테스트 코드를 열어서 사용하는 장고 관련 코드 — view, model, URLconf, RSS 설정 따위 등에 대한 모든 import들을 추가 하십시오. 이들 import들을 테스트 핸들러 함수에 넣고 브라우저에서 테스트 URL에 접속하십시오. 만약 이것이 문제를 발생시킨다면, import 한 장고 코드들이 문제를 일으키는 것임이 확인된 것입니다. 문제가 멈출때까지 import 를 점차적으로 줄여나가서, 문제를 발생시키는 특정 모듈을 찾습니다. 필요하다면 해당 모듈 안으로 더 들어가 그 곳의 import 들을 조사합니다.

Last modified 5 years ago Last modified on 03/07/09 03:38:37