마사키군의 다락방

끄적끄적할게 있을때 끄적거려 보관해두는 다락방

Apache와 Python 연동하기

사실 원래는 딴 공부 하고 있었는데(…) 갑자기 하라는 공부는 안하고 급 떠오른 의문을 해소하기 위해(?) 조사를 해 보았다.

인터넷을 찾아보니 파이썬을 CGI 형태로 사용하는 방법은 많이 있었지만, mod_python을 이용하는 방법은 그렇게 문서가 많지 않아서 둘 다 조사하고 정리해보았다. 조사하다 보니, WSGI도 욕심이 생겼지만, 일단 하나라도 좀 끝내놓고 다른걸 시작하자 (…)


Apache와 Python 연동하기

딱히 요즘 공부하고 있는게 파이썬인건 아니긴 한데, 난 왜 이렇게 자꾸 파이썬이 눈에 밟히는지 모르겠다. 딴 공부를 하던 중에 갑자기 웹페이지의 요청을 파이썬으로 처리하는 방법에 대해 관심이 생겼고, 조사하면서 알게 된 내용을 정리해 보았다.

아파치가 전달받은 웹페이지의 요청을 파이썬으로 처리하는 방법은 두가지가 있는데, CGI를 이용하는 방법과 아파치의 mod_python 모듈을 이용하는 방법이 있다. 이외에도 WSGI(Web Server Gateway Interface)를 이용하는 방법이 있는 것 같은데, 이쪽은 조사해보지 않았다.

CGI를 이용해서 Python 이용하기

CGI를 이용해서 요청을 처리하는 방법은 비교적 간단하다. 아파치의 환경설정을 손봐서, 파이썬 확장자로 요청이 전달된 경우에는 파이썬에서 처리하도록 하면 된다.

아파치 환경설정 파일은 아파치 버전에 따라서 차이가 있을 수 있는데, 나는 윈도우용 APM 패키지인 XAMPP를 사용하고 있으니 XAMPP에 맞춰서 기술하려고 한다. 여담으로, 최근에는 XAMPP의 리눅스용 및 맥OS용 패키지도 나온것 같은데, 그쪽은 써보지 않아서 잘 모르겠다.

또한 이 항목은 파이썬 3.4.3을 기준으로 테스트하고 작성되었다. 다들 알다시피 파이썬 2와 파이썬 3은 제법 큰 차이가 있기 때문에, 파이썬 2 기준으로 실험하면 아래 내용들이 동작하지 않을수도 있다.

윈도우용 XAMPP 기준으로, 아파치의 환경설정 파일의 경로는 아래와 같다.

  • {XAMPP Path}\apache\conf\httpd.conf

위 파일을 텍스트 에디터로 열어서, <Directory> 태그를 찾아서 Options +ExecCGIAddHandler cgi-script .py문을 추가한다. 아래와 비슷한 형태가 될 것이다.

아래에서 두개의 라인이 추가된 라인이며, 다음의 의미를 갖는다.

  • Options +ExecCGI
    • 아파치가 요청을 CGI를 이용해 처리할 수 있도록 설정한다
  • AddHandler cgi-script .py
    • 웹페이지 요청 중 .py 확장자를 가지는 요청은 CGI를 이용해 처리한다

위와 같이 설정하고 나면, 설정된 디렉토리에 .py 파일을 작성하여 웹페이지의 요청을 처리할 수 있게 된다. 다만, 파이썬은 웹페이지의 요청을 처리하기 위한 전용 언어가 아니기 때문에, CGI 처리를 위해서는 정해진 규격을 따를 필요가 있다(정확히는 파이썬에서 CGI를 처리하기 위한 규격이라고 보는 편이 옳겠다). 파이썬의 CGI 프로그램은 아래 규격을 따른다.

  • 소스코드 첫번째 라인은 #!로 시작해서, 실제 파이썬 인터프리터의 위치를 명시한다
  • 두번째 라인은 소스코드의 인코딩을 명시한다. 이것은 반드시 필요한 것은 아니라고 생각하지만, 명시하지 않으면 유니코드 처리가 제대로 되지 않는 경우가 발생할 수 있다.
  • 반드시 파이썬의 cgi 모듈을 import한다.

위 규격을 따른다면, 아래와 같은 형태의 샘플 코드가 될 것이다.

위 샘플코드를 작성한 뒤 웹브라우저로 접속해보면 화면에 Hello, Python CGI!라고 표시된다.

운영체제에 따라서는 한글 출력시 오류가 발생하거나 아무것도 표시되지 않을 수가 있는데, 이때는 아래 “한글 출력이 되지 않을때” 부분을 참고한다.

mod_python 이용하기

mod_python은 아파치의 모듈 중 하나로써, 아파치에 파이썬 언어를 처리할 수 있는 모듈을 통합한다. 스크립트는 아파치 내부로 통합된 파이썬 모듈에서 처리되기 때문에, 파이썬 인터프리터를 직접 구동시켜 처리하는 CGI 방식보다 퍼포먼스 면에서 더 유리할 것이라고 생각하지만, 딱히 측정해보지는 않았다. 그런 반면에, 파이썬 인터프리터를 직접 구동하는 것이 아니기에, 파이썬의 특정 feature가 mod_python에서 지원되지 않는다면 mod_python의 버전업만을 기다릴 수밖에 없다는 단점도 있다.

(사실 CGI는 어떤 언어를 지칭하는 것이 아니라, 웹서버와 서버 사이드 스크립트간의 통신 규약을 가리키는 것이다. 그러므로 어떤 CGI 프로그램과 동일한 문법을 가지고 있다고 해서 그 언어가 CGI다 라는 식으로 부를 수는 없다. 좀 길지만, KLDP의 PHP도 CGI인가요?라는 토론을 참고하면 어느정도 감을 잡을 수 있다.)

mod_python의 공식 페이지는 http://modpython.org 이다. 그런데 2015년 4월 14일 현재 mod_python은 최신 버전이 3.5.0이지만, 윈도우용은 3.3.1 버전이 최신 버전이다. GitHub 저장소에 올라온 공지사항에 의하면, 개발자가 윈도우 운영체제의 개발환경을 사용하지 못하기 때문에 저장소의 소스 코드를 사용해서 직접 컴파일해본 뒤 구동이 가능한지 확인 여부를 알려달라고 하고 있다.

이 글에서는 mod_python이 윈도우 운영체제로는 최신 버전이 업데이트 되지 않는 것도 있고 해서 리눅스에서 테스트했던 경과를 기록했지만, 만약 꼭 윈도우 운영체제에 설치해서 사용해보겠다는 사람은 Installing Python (mod_python) on XAMPP (on Windows)라는 문서를 참고하면 도움이 될 것 같다. 다만 2008년도에 작성된 문서라 mod_python 웹페이지의 주소가 틀렸다던가 하는 문제가 좀 있다.

여하튼 그런 연유로, mod_python은 VMware에 설치한 리눅스 환경에서 테스트하였다. 리눅스는 2015년 4월 14일 현재 우분투 서버의 가장 최신버전인 우분투 서버 14.04 LTS를 사용했다. 당연한 이야기지만 패키지 관리자는 RHEL의 RPM이 아닌, 데비안의 apt-get이 사용되었다.

여기서는 아파치 설치부터 mod_python 설치까지 진행했던 내용을 순서대로 기술하려고 한다. 화면이 좀 번잡해지겠지만, Ordered List를 이용해서 수행하려는 작업을 표시하고, Unordered List를 이용해서 명령어를 표시하겠다. 각 명령어들은 굳이 sudo를 붙이지 않았다.

다만, 내가 리눅스에서 서버 운영을 해본 적이 거의 없기 때문에 중간중간 불필요한 작업이 있을수도 있다.

  1. 아파치 설치
    • apt-get install apache2
  2. 파이썬 설치 (다만, mod_python의 특성상 꼭 파이썬을 설치할 필요는 없을 것 같다)
    1. 소스 코드를 컴파일할 컴파일러 설치
      • apt-get install build-essential
    2. SQLite 설치. 근데 이게 꼭 필요한지는 모르겠다.
      • apt-get install libsqlite3-dev
      • apt-get install sqlite3
    3. 패키지의 압축을 풀기 위해 bzip 설치
      • sudo apt-get install bzip2 libbz2-dev
    4. 파이썬 다운로드
      • wget https://www.python.org/ftp/python/3.4.3/Python-3.4.3.tar.xz
      • 위 주소는 파이썬 3.4.3의 주소이며, 다른 버전을 설치하고 싶다면 Python Source Releases 페이지에서 원하는 버전의 XZ compressed source tarball의 주소를 이용한다.
    5. 다운로드한 파이썬의 압축을 풀고 컴파일 및 설치
      • tar xJf ./Python-3.4.3.tar.xz
      • cd ./Python-3.4.3
      • ./configure --prefix=/opt/python3.4.3
      • make && sudo make install
  3. mod_python 설치
    • apt-get install libapache2-mod-python
  4. 아파치가 mod_python을 사용하도록 환경설정 수정
    • vi /etc/apache2/apache2.conf

apache2.conf 파일은 CGI 처리하도록 설정할때와 비슷하게 <Directory> 블럭을 아래와 같이 수정한다. 아래의 3개의 라인이 추가된 부분이다.

 

  1. 위와 같이 설정했다면 아파치를 재시작
    • service apache2 restart

위와 같이 설정했다면 .py 파일은 CGI를 사용할 때와 동일한 문법으로 동작하고, .psp 파일은 ASP나 PHP처럼 HTML 중간에 스크립트를 끼워넣는 형식으로 동작한다.

.py 파일은 CGI에서 작성한 샘플 예제를 그대로 이용할 수 있을 것이고, .psp 파일은 아래와 같은 예제로 테스트해볼 수 있다.

위 페이지를 웹브라우저를 통해 접속해보면 화면에 Hello, PSP!가 표시된다.

또한, .py 파일은 mod_python.cgihandler 대신 mod_python.publisher를 이용해서 처리할 수도 있다. 위에서 적어둔 아파치의 설정 파일을 아래와 같이 설정한다. 사실은 .py 파일은 .cgihandler, .psp는 .psp, 그 외 다른 확장자를 하나 더 둬서 .publisher로 처리되도록 하려고 했으나, 이상하게 .publisher는 .py 확장자로 설정하지 않으면 동작하지 않았다.

apache2.conf 파일에서

  • PythonHandler mod_python.cgihandler | .py

위 부분을

  • PythonHandler mod_python.publisher | .py

로 수정한 뒤 아파치를 재시작한다.

그 후 예제 파일은 확장자를 .py로 해서 아래와 같이 만든다.

위와 같이 작성한 후, 파이썬 파일/handler로 접속해본다. 화면에 Hello, mod_python!이라고 출력된다면 올바르게 설정된 것이다.

한글 출력이 되지 않을때

mod_python은 그냥 경함상 해본 것이라서 HTML만 출력하고 만족했으니 그렇다 치더라도, CGI로 파이썬을 사용할때는 한가지 문제가 발생했다. 화면에 한글을 출력하려고 하면 웹브라우저가 회색으로만 표시되고 아무것도 나오지 않았다. 예를 들어서 print("안녕하세요, 파이썬 프로그램입니다!")를 실행하려고 하니 웹페이지가 회색으로만 표시되었다.

이것이 모든 환경에서 동일하게 발생하는 문제인지는 잘 모르겠지만, 일단 내가 사용하는 서버인 영문판 Windows Server 2012에서는 그러한 문제가 발생했다.

이것은 아마도, 파이썬 CGI 프로그램에서도 print() 함수를 실행할때는 stdout으로 출력하게 되는데, 이때 stdout이 사용하고 있는 인코딩이 해당 글자를 지원하지 않는 경우 발생하는 오류라고 생각된다. 영문판 Windows Server 2012의 stdout의 인코딩을 조회해보니 utf-8이나 euc-kr 등이 아니라 cp1252였다.

실제로 간단한 form 페이지를 만들어서 파이썬으로 데이터를 전달 후 파이썬에서 cgi.test()로 디버깅 정보를 출력해보면, 데이터를 영어로 전달했을때는 오류가 발생하지 않는데 한글 데이터를 전달했을 경우에는 전달받은 form 데이터를 출력하려는 시점에서 아래 오류가 발생하는 것을 확인할 수 있다.

  • UnicodeEncodeError: ‘charmap’ codec can’t encode characters in position 45-47: character maps to

이것을 해결하기 위해서는 파이썬 코드를 UTF-8 인코딩으로 작성한 후, stdout의 인코딩을 강제로 UTF-8로 전환해주면 올바르게 출력된다.

예를 들어서 맨 처음에 작성한 코드는 아래와 같이 수정할 수 있다.

위와 같이 작성한 후 웹브라우저로 접속해보면 안녕하세요, 파이썬 프로그램입니다!라고 표시될 것이다.

참고자료

이 글은 아래 문서들을 참고하였다.

, , , , ,

One thought on “Apache와 Python 연동하기

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.