본문 바로가기
Spec UP - Backend/Django로 배우는 쉽고 빠른 웹개발 파이썬 프로그래밍

chap 02. 웹 서버 라이브러리

by TIS_Ha 2024. 2. 20.
반응형

2.3 웹 서버 라이브러리

2.3.1 간단한 웹 서버

웹 서버의 역할은 http 통신에서 클라이언트의 요청을 받고 이를 처리하여 결과를 되돌려주는 것이다.

 

파이썬에서는 웹서버를 만드는데 필요한 라이브러리를 http.server 모듈에서 정의하고 있으며, 주요 클래스는 아래와 같다.

클래스명 주요 기능
HTTPServer 웹 서버를 만들기 위한 클래스로 서버IP와 PORT를 바인딩한다.
HTTPServer 객체 생성 시 핸들러 클래스가 반드시 필요하다.
BaseHTTPRequestHandler 핸들러를 만들기 위한 기반 클래스로 HTTP 프로토콜 처리 로직이 들어있다.
이 클래스를 상속받아 자신의 로직 처리를 담당하는 핸들러 클래스를 만든다.
SimpleHTTPRequestHandler BaseHTTPRequestHandler 클래스를 상속받아 만드는 클래스
GET과 HEAD 메소드 처리가 가능한 핸들러 클래스
CGIHTTPRequestHandler SimpleHTTPRequestHandler 클래스를 상속받아 만드는 클래스
추가적으로 POST 메소드와 CGI 처리가 가능한 핸들러 클래스

 

HTTPServer 클래스를 활용하여 클라이언트의 요청을 받고 'Hello World'라는 문장을 리턴하는 예제를 살펴보자.

from http.server import HTTPServer, BaseHTTPRequestHandler

class MyHandler(BaseHTTPRequestHandler): #BaseHTTPRequestHandler를 상속받아 핸들러 클래스 정의.
    def do_GET(self):
        self.send_response_only(200,'OK')
        self.send_header('Content-Type', 'text/plain')
        self.end_headers()
        self.wfile.write(b"Hello World")
        
if __name__ == '__main__':
    server = HTTPServer(('',8888),MyHandler) # 서버의 IP, 포트, 핸들러 클래스를 인자로 하여 HTTPServer 객체 생성
    print("Started WebServer on port 8888....")
    print("Press ^C to quit WebServer")
    server.serve_forever() # HTTPServer객체의 serve_forever() 메소드 호출

위 예제를 실행 후 브라우저에서 "127.0.0.1:8888"을 접근하면 아래와 같이 실행결과를 확인할 수 있다.

 

2.3.2 HTTPServer 및 BaseHTTPRequestHandler 클래스

HTTPServer와 BaseHTTPRequestHandler는 웹서버를 만들기 위해 임포트하거나 상속받아야하는 기반 클래스이다.

기반 클래스는 HTTP 프로토콜을 처리하는 기능이 있어서 기반 클래스를 상속받으면 따로 HTTP 프로토콜과 관련된 로직을 코딩하지 않아도 된다.

 

2.3.3 SimpleHTTPRequestHandler 클래스

파이썬은 별도의 코딩 없이도 필요할 때 즉시 웹 서버를 실행할 수 있도록 SimpleHTTPRequestHandler 클래스가 정의되어있다.

별도의 코딩 없이 "python -m http.server 8888" 명령 실행 후 브라우저에서 "127.0.0.1:8888"을 접근하면 아래와 같이 실행결과를 확인할 수 있다.

* 포트 번호를 설정하지 않으면 디폴트 포트는 8000번이다.

브라우저에서 디렉터리 리스트가 나오는 이유는 SimpleHTTPRequestHandler의 do_GET()메소드가 디렉터리 리스트를 반환하도록 구현되어 있기 때문이다.

 

SimpleHTTPRequestHandler 클래스에는 do_GET(), do_HEAD() 메소드가 정의되어있어 GET과 HEAD 방식을 처리할 수 있다.

하지만 POST 등 그 외의 HTTP 메소드는 처리할 수 없다는 점에 유의하자.

 

2.3.4 CGIHTTPRequestHandler 클래스

CGIHTTPRequestHandler 클래스도 SimpleHTTPRequestHandler처럼 미리 구현되어 있어 필요할 때 즉시 웹서버를 실행할 수 있다.

CGIHTTPRequestHandler에는 do_POST() 메소드가 정의되어있어  GET,HEAD 방식 뿐아니라 POST 방식을 처리할 수 있다.

다만 CGIHTTPRequestHandler의 do_POST()메소드는 CGI 처리 기능만 구현되어 있어 그 밖의 기능이 필요하다면 별도로 구현해야한다.

별도의 코딩 없이 CGI 웹서버가 동작하는지 확인하기 위해서는 -cgi 옵션을 설정해야한다.

"python -m http.server 8888 --cgi " 명령 실행하면 CGI 웹서버가 실행되며, cgi 웹서버를 실행하는 위치가 웹 서버의 루트 디렉터리가 된다는 점에 유의하자.

* 포트 번호를 설정하지 않으면 디폴트로 8000번을 사용한다.

 

CGI 웹 서버가 CGI 스크립트를 정상적으로 처리하는지 확인하려면 2가지 준비 작업이 필요하다.

하나는 서버에서 실행될 스크립트 준비이고 하나는 POST 방식으로 요청을 보낼 웹 클라이언트 준비이다.

 

CGI 웹서버가 실행되는 창과 다른 또 하나의 cmd창을 열고 CGI 스크립트를 코딩한다.

이 때 클라이언트 요청에 담긴 질의 문자열에 액세스 하기위해서 FieldStorage() 클래스의 인스턴스를 생성하고 getvalue() 메소드를 호출하는 것이 중요하다.

또 CGI 스크립트 파일은 cgi-bin 디렉터리 하위에 위치해야하는 점에 유의하여 아래와 같이 실행해보자.

import cgi

form = cgi.FieldStorage()
name = form.getvalue('name')
email = form.getvalue('email')
url = form.getvalue('url')

print("Content-Type: text/plain")
print()

print("Welcome... CGI Scripts")
print("name is", name)
print("email is", email)
print("url is", url)

 

이어서 POST 방식으로 요청을 보낼 웹 클라이언트를 작성한다. (해당 파일위치는 원하는 곳에 해도 무방하다.)

from urllib.request import urlopen
from urllib.parse import urlencode

url = "http://127.0.0.1:8888/cgi-bin/script.py"
data = {
    'name': '김석훈',
    'email': 'shkim@naver.com',
    'url': 'http://www.naver.com',
}
encData = urlencode(data)
postData = encData.encode('ascii')

f = urlopen(url, postData)   # POST
print(f.read().decode('cp949'))

해당 코드를 실행하면 아래와 같이 실행결과를 확인할 수 있다.

 

2.3.5 클래스간 상속 구조

HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler, CGIHTTPRequestHandler 클래스들은 상속을 통해 기능을 확장하는 방식으로 작성되었으며, 해당 클래스들은 http.server 모듈에 정의되어 있다.

모든 HTTP 웹서버는 HTTPServer 클래스를 사용하여 작성하고 웹 서버에 사용되는 핸들러는 BaseHTTPRequestHandler를 상속받아 작성하는 것이다.

각 핸들러 클래스는 상위 핸들러 클래스를 상속받아 정의된다.

즉 기반핸들러인 BaseHTTPRequestHandler 클래스의 기능을 확장해서 정의된다는 뜻이다.

반응형

댓글