[Python] 웹 서버를 구축하는 방법(bottle 모듈)


Development note/Python  2020. 2. 17. 09:00

안녕하세요. 명월입니다.


이 글은 Python에서 웹 서버를 구축하는 방법(bottle 모듈)에 대한 글입니다.


제가 이전에 Python으로 웹 서버를 구축하는 방법에 대해 소개한 적이 있습니다.

링크 - [Python] 웹 서버를 기동하는 방법(http.server)


Python에서는 http.server의 경우는 단순히 socket 서버를 열고 브라우저에서 접속하면 요청 해더 처리(request)와 그것에 대한 응답 코드(response)가 전부입니다.

그러니깐 url의 요청 페이지 별로 처리하거나 html 파일을 읽어서 응답하는 등의 처리가 없기 때문에 전부 구현해야 합니다.


정확히 이야기 하면 http.server의 경우는 단순한 http 서버를 열기 위한 모듈이라면 bottle은 http.server 모듈 위에서 조금 더 웹 사이트를 구성할 수 있는 프레임 워크 모듈이라고 생각하는 것이 정확하겠습니다.

bottle 프레임 워크는 단순히 python에서 기동하는 웹서버가 아닌 apache에서도 CGI로 구현이 가능합니다.


그럼 bottle 모듈을 설치하고 사용해 보겠습니다.

pip install bottle

# ajax의 응답으로 json처리를 하기 위해 json 모듈을 사용
import json;
# bottle 모듈
from bottle import route, run, error, static_file, template, request, response, view;

# favicon.ico가 아래의 index함수로 들어가는 것을 막기 위해.
# re:로 설정하면 정규식으로 검색할 수 있다. 해당 조건이 참이면 send_inmage의 함수를 호출한다.
@route('/<filename:re:.*.ico>')
def send_image(filename):
  # 파일에서 읽어와서 응답한다.
  return static_file(filename, root='d:\\python\\blog', mimetype='image/ico')

# route는 브라우저의 요청에 응답하는 데코레이터
# 「/」에서 「/test」를 사용하면 name은 test로 설정
@route('/', method='GET')
@route('/<name>', method='GET')
# view는 같은 디렉토리 상의 index.tpl 파일을 읽어온다.
@view('index')
# 「/」로 오면 name값을 'Guest'로 설정한다.
def index(name='Guest'):
  # Query string의 값은 request.query로 받을 수 있다. setClear의 값이 1이면 쿠키를 삭제한다.
  if request.query.setClear == '1':
    name = 'Guest';
    # 쿠키 Name값을 삭제한다. expires를 0으로 설정.
    response.set_cookie("Name", '', expires=0);
  else:
    # 값이 Guest가 아니면 쿠키에 Name을 설정한다.
    if name != 'Guest':
      # 쿠키를 set_cookie로도 설정이 가능하지만 header를 설정하는 방법에 대한 예제이다.
      response.set_header('Set-Cookie', f'Name={name}');
      # 기존의 header값에서 추가할 때 사용한다.
      #response.add_header('Set-Cookie', f'next={name}');
    # name값이 Guest일 경우,
    if name == 'Guest':
      # 쿠키로부터 Name을 받아와서 설정한다.
      buf = request.get_cookie("Name");
      # 쿠키값이 설정되어 있으면
      if buf is not None:
        # name을 바꾼다.
        name = buf;
  # 값을 딕셔너리 값으로 넘긴다.
  return dict(name=name);

@route('/ajax', method='POST')
def ajax():
  # request.forms은 폼 데이터 이다. ajax로 넘어온 param의 값을 받아서 json으로 만든다.
  str = json.dumps({'param':request.forms.get('param')});
  # string 타입을 리턴한다.
  return str;
# js폴더안의 자바스크립트 파일을 보낸다.
@route('/js/<filename:path>')
def download(filename):
  # javascript 파일을 보낸다.
  return static_file(filename, root="d:\\python\\blog", download=False);

# 위의 모든 조건에 맞지 않고 404가 에러가 발생하면 호출된다.  
@error(404)
def error404(error):
  # 에러가 발생하면 표시하는 메시지
  return 'Nothing here, sorry';

# 위 route 설정이 완료되면 실제 서버를 기동한다.
run(host='localhost', port=80, debug=True);
<html>
  <head><title>python bottle test</title></head>
  <body>
    <!-- download함수가 호출된다.-->
    <script src="/js/jquery-3.4.1.min.js"></script>
    <!-- python 소스에서 받아온 값이다. -->
    Name : {{name}}
    <br />
    <textarea></textarea>
    <script>
        // ajax 함수가 호출된다.
        $(function(){
            var ajax = $.ajax({
                type: "POST",
                url: "/ajax",
                dataType: 'json',
                data: {'param':'hello world'}
            });
            ajax.done(function(data){
                $("textarea").html(data.param);
            });
        });
    </script>
  </body>
</html>

먼저 localhost/nowonbun로 접속했습니다. name에 nowonbun이 입력되어서 index.tpl 템플릿 파일로 값이 출력되는 것을 확인할 수 있습니다.

그리고 index.tpl 파일의 jquery 라이브러리도 다운을 잘 받았네요.

jquery ajax로 다시 /ajax 함수를 호출해서 param로 hello world의 데이터를 보냅니다.

그럼 python의 ajax함수에서 그걸 다시 param의 json 형태로 만들어서 리턴을 합니다.

그럼 textarea 태그에 param키의 값으로 입력을 하니 hello world가 표시된 것을 확인할 수 있습니다.

다시 제가 localhost/?setClear=1의 식으로 요청하면 python에서 쿠키를 삭제하고 name을 Guest로 설정합니다.

그 결과 name이 Guest로 표시되었습니다.

실행 결과는 처음에 nownobun을 요청하고 jquery를 요청하고 ajax를 요청했네요.

다시 setClear를 요청하고 ajax를 요청했습니다. jqeury는 두번째 요청이라 브라우저에서 캐시로 넘겨서 받았나 보네요.. 요청이 없습니다.

파일 구성은 main.py과 index.tpl 템플릿 파일, jquery 파일을 두었습니다.

favicon.ico파일은 없는데 이건 send_image함수에서 에러가 발생하면 error404로 리디렉션을 합니다.


여기까지 Python에서 웹 서버를 구축하는 방법(bottle 모듈)에 대한 설명였습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.