파이썬은 스크립트 언어로서 자바와 같은 VM 기반의 언어이기도 합니다. 프론트엔드 사이트 구축이나 일회성 용도로 웹 서버 기능이 종종 필요한 경우가 있습니다. 예를 들어 강의 중에 자료를 배포하려고 할 때, 실행하는 프로그램이나 기능이 반드시 HTTP 서버 위에서만 동작하려고 할 경우 등이 이에 해당할 것입니다.
파이썬은 배터리 전략(Battery Strategy)으로 일반적인 응용 프로그램을 구현할 때 필요한 기능 대부분을 모듈로 제공하고 있습니다. 이 같은 특징은 개발자가 프로그램을 구현하기 위해 새로운 라이브러리를 찾지 않아도 되는 것을 의미하기도 합니다.
파이썬은 HTTP 서버를 구현하기 위한 기본 모듈을 제공하고 있습니다. 여기에서는 파이썬 3 기반에서 HTTP 서버를 구축해보고, 파이썬 기본 모듈로 HTTPS 서버를 구축한 다음, flask 내장 웹 서버로 SSL 서버를 함께 구축해보겠습니다.
파이썬 3으로 HTTP 서버를 구축하는 방법은 크게 2가지 방법이 있습니다.
python 명령어와 실행 옵션 만으로 HTTP 서버 구축
터미널 프로그램(윈도우는 cmd, 리눅스/OSX는 terminal)에서 python 명령어는 다양한 옵션을 제공하는데 그 중 -m 옵션은 명령어 실행과 동시에 실행할 모듈의 위치를 인자로 받습니다. 파이썬 3에서는 내장 웹 서버는 http.server 모듈이 제공합니다.
$ python -m http.server 8080
[명령 1] python 내장 HTTP 서버 구축
python 명령어로 HTTP 서버를 구축하는 일은 현재 폴더에 무엇이 있는지 보는 dir 명령이나 ls 명령을 실행하는 것처럼 쉽습니다. 명령 1의 실행 결과는 웹 브라우저에서 http://localhost:8080에 접속해보는 것으로 쉽게 확인할 수 있습니다.
단순한 목적의 HTTP 서버가 필요하다면 명령 1에서 무리가 없지만, 특별히 MIME types을 지정하거나 브라우저에 보내는 응답 헤더를 다르게 할 경우는 HTTP 스크립트를 사용하는 것이 좋습니다.
python 스크립트로 HTTP 서버 구축
import http.server
httpd = http.server.HTTPServer(('0.0.0.0', 8080), http.server.SimpleHTTPRequestHandler)
httpd.serve_forever()
[스크립트 1] 내장 웹 서버를 실행하는 파이썬 스크립트
스크립트로 내장 웹 서버를 구축할 때는 내장 웹 서버가 웹 서버의 요청을 받았을 때 어떤 파일이 어떻게 응답해야 할지 알려주는 핸들러 클래스를 지정해야 하는데 파이썬은 SimpleHTTPRequestHandler가 기본적으로 제공됩니다.
예를 들어 내장 웹 서버가 HLS 파일을 제공하는 내장 웹 서버라면 파이썬 내장 웹 서버는 SimpleHTTPRequestHandler 클래스 변수인 extension_map 변숫값을 수정해서 특정 확장자인 m3u8, ts 파일이 어떤 MIMEType인지 브라우저에게 알려줘야 합니다.
import http.server
HTTPHandler = http.server.SimpleHTTPRequestHandler
HTTPHandler.extension_map.update({
'.m3u8': 'application/x-xmpegURL',
'.ts': 'video/MP2T'
})
httpd = http.server.HTTPServer(('0.0.0.0', 8080), HTTPHandler)
httpd.serve_forever()
[스크립트 2] m3u8 파일과 ts 파일의 MIME Type을 강제로 지정해서 브라우저에 응답하는 스크립트
단순히 HTTP 서버를 구성하는 일이라면 파이썬 공식 문서에 나와있는 것만으로도 어렵지 않게 구축할 수 있지만 SSL 통신을 전제로 하는 HTTPS 서버 구축은 공식 문서에서도 구축 방법을 찾기가 어렵습니다.
파이썬으로 HTTPS 서버 구축하기
파이썬으로 HTTPS 서버를 구축하려면 ssl 모듈을 임포트해야 합니다. ssl 모듈은 소켓 통신에 대한 암호화 레이어 계층을 제공하는 모듈로서 openssl을 사용합니다. 덕분에 openssl이 설치되어 있으면 대부분의 모던 운영체제(윈도우, 리눅스, 유닉스, OSX)에서도 암호화 레이어 계층을 쉽게 구현할 수 있는 기능을 제공합니다.
import http.server
import ssl
httpd = http.server.HTTPServer(('0.0.0.0', 5443), http.server.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile='newcert.pem', keyfile='newkey.pem')
httpd.serve_forever()
[스크립트 3] ssl 모듈로 httpd.socket 변수를 감싸서 httpd 모듈에 SSL 기능 제공
ssl 모듈은 wrap_socket 함수를 제공합니다. 이 함수는 필수 인자로 SSL 기능을 제공할 소켓 변수를 전달받습니다. 나머지 인자는 선택적 인자인데 인증 서버가 서명한 cert 파일과 서버의 개인 키를 전달함으로서 보안 통신이 제공되는 서버를 만들 수 있습니다.
필자는 사설 루트 인증 기관(CA)과 클라이언트 서버용 인증서를 openssl을 사용하여 생성했습니다. 스크립트 3을 실행하면 keyfile에 인증서 암호가 있으면 내장 웹 서버 실행 과정에서 다음 문자열이 출력되면서 인증서 비밀번호를 물어올 것입니다.
Enter PEM pass phrase:
클라이언트 서버 인증서의 비밀번호를 올바르게 입력하고 나면 SSL 기능이 제공되는 웹서버가 만들어졌을 것입니다. 그런데 이렇게만 만들면, 실행된 웹 서버는 웹 브라우저로 접근 시 반드시 https:// 스킴을 앞에 붙여줘야 합니다.
HTTPS 서버와 HTTP 서버 모두 제공하려면 2개 파일을 각각 실행해야 합니다.
flask 내장 웹 서버에서 SSL 서버 구축
flask는 파이썬 WSGI 규약에 기반한 웹 프레임워크입니다. django와 함께 전세계에서 가장 인기있는 프레임워크이기도 합니다. flask에서 SSL 기능을 제공하려면 다음과 같이 작성합니다.
from flask import Flask
import ssl
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World"
if __name__ == "__main__":
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS)
ssl_context.load_cert_chain(certfile='newcert.pem', keyfile='newkey.pem', password='secret')
app.run(host="0.0.0.0", port=4443, ssl_context=ssl_context)
[스크립트 4] flask 응용 프로그램에 SSL 기능 추가
flask 내장 웹 서버로 ssl 서버 기능을 제공하려면 ssl 모듈의 SSLContext 클래스를 사용해서 클라이언트 서버의 인증서와 비밀키를 제공하면 됩니다. 예제에선 인증서의 비밀번호를 함께 입력했지만 프로그램 코드에 인증서 비밀번호를 제공하는 것은 매우 위험 부담이 큰 일입니다.
SSLContext 클래스의 인스턴스를 생성했으면, 이 인스턴스를 flask 내장 웹 서버를 실행하는 run 메서드의 ssl_context 파라메터에 전달하기만 하면 됩니다.
앞에서 살펴 본것과 같이 파이썬은 ssl 모듈을 사용하여 네트워크 응용 프로그램에 쉽게 SSL 기능을 제공할 수 있습니다. 이 문서에는 설명하지 않았지만 SMTP, FTP 서버에도 이 문서에서 살펴본것과 같이 여러분이 SSL 기능을 제공할 수 있을 것입니다.
파이썬은 아직 많은 곳에서 자유롭게 사용할 수 있는 프로그래밍 언어입니다. 아직 시작하지 않았다면 꼭 한 번, 파이썬을 사용해서 업무 생산성의 향상을 꾀해 보시길 바랍니다. Good Luck~!!
이전 글 : 로서와 로써
다음 글 : 레이저로 자른 170개 조각으로 만든 거인의 손
최신 콘텐츠