Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python으로 간단한 프록시 웹 서버 만들기: 핵심 원리와 예제 코드


프록시 웹 서버란?

프록시 서버(Proxy Server)는 클라이언트와 실제 서버 사이에서 중개자 역할을 하는 서버입니다. 클라이언트로부터 받은 요청(Request)을 실제 서버로 전달하고, 실제 서버로부터 응답(Response)을 받으면 그 결과를 다시 클라이언트에게 돌려주는 구조로 동작합니다.

프록시 서버를 사용하는 이유는 다양합니다. 대표적인 예는 다음과 같습니다.

  • IP 주소 보호: 실제 서버의 IP 주소를 외부에 노출하지 않고 숨길 수 있습니다.
  • 성능 향상: 캐싱을 활용해 반복 요청에 대한 응답 속도를 개선할 수 있습니다.
  • 보안 강화: 클라이언트와 서버 사이에서 트래픽을 필터링하거나 접근을 제어할 수 있습니다.

이 글에서는 파이썬(Python)을 이용해 이러한 역할을 수행하는 아주 간단한 프록시 서버를 직접 만들어 보겠습니다.

구현에 사용되는 모듈

간단한 프록시 서버는 다음 세 가지 모듈만으로도 충분히 구현할 수 있습니다.

  • SimpleHTTPServer: HTTP 요청을 처리하는 기본 핸들러를 제공합니다.
  • SocketServer: 네트워크 소켓 기반 서버를 손쉽게 생성할 수 있게 해 줍니다.
  • urllib: 지정한 URL의 리소스를 열어 내용을 가져오는 데 사용됩니다.

구현 방식은 간단합니다. 먼저 요청을 처리할 핸들러 클래스를 정의한 뒤, 해당 클래스를 서버 객체에 전달합니다. 그다음 serve_forever() 메서드를 호출하면 서버가 계속 실행되며 클라이언트의 요청을 수신·처리하게 됩니다.

예제 코드

import SimpleHTTPServer
import SocketServer
import urllib

PORT = 9012

class JustAProxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        url = self.path[1:]
        self.send_response(200)
        self.end_headers()
        self.copyfile(urllib.urlopen(url), self.wfile)

httpd = SocketServer.TCPServer(('localhost', PORT), JustAProxy)
print("Proxy Server at", str(PORT))
httpd.serve_forever()

실행 결과

위 코드를 실행하면 다음과 같은 결과가 출력됩니다.

Proxy Server at 9012

코드 동작 원리

  • do_GET(): 클라이언트의 GET 요청이 들어올 때 자동으로 호출됩니다. 경로(path)에서 첫 번째 문자 '/'를 제거하여 실제로 요청할 대상 URL을 추출합니다.
  • send_response(200): 클라이언트에게 HTTP 200(성공) 상태 코드를 전송해 요청이 정상 처리되었음을 알립니다.
  • end_headers(): 응답 헤더 전송을 마무리하고 본문 작성 단계로 넘어갑니다.
  • copyfile(urllib.urlopen(url), self.wfile): urllib 모듈로 대상 URL의 내용을 가져온 후, 그 결과를 그대로 클라이언트의 출력 스트림(wfile)에 복사합니다.
  • SocketServer.TCPServer(): 지정한 호스트('localhost')와 포트(9012)에서 요청을 수신하는 TCP 서버를 생성합니다.
  • serve_forever(): 서버를 무한 루프로 구동하여 종료 신호가 있기 전까지 계속해서 요청을 처리합니다.

참고 사항

위 예제는 Python 2 환경을 기준으로 작성되었습니다. Python 3에서는 SimpleHTTPServer 대신 http.server, urllib 대신 urllib.request 모듈을 사용해야 하며, 일부 메서드 이름도 변경되었으므로 사용 중인 버전에 맞게 코드를 수정해야 합니다. 또한 실제 운영 환경에서는 HTTPS 지원, 헤더 전달, 예외 및 에러 처리 등 추가적인 기능 구현이 필요하다는 점도 유의하세요.