웹 어플리케이션 & 프레임워크

../_images/34309496175_b82d104282_k_d.jpg

파이썬은 빠른 프로토타이핑과 거대한 프로젝트에 두루 사용되는 강력한 스크립트 언어로서, 웹 어플리케이션 개발에 널리 사용된다.

Context

WSGI

Web Server Gateway Interface(웹 서버 게이트웨이 인터페이스)(줄여서 "WSGI") 는 웹서버와 파이썬 웹 어플리케이션 프레임워크 간의 표준 인터페이스입니다. 웹 서버와 파이썬 웹 프레임워크 간의 동작과 통신을 표준화함으로써 WSGI는 모든 WSGI 호환 웹서버 에 복사해 넣어 배포할 수 있는 파이썬 웹서버 코드를 작성할 수 있도록 합니다.

프레임워크

일반적으로 웹 프레임워크란 웹 어플리케이션(예를 들면 대화형 웹사이트)을 구현하기 위해 사용되는일련의 라이브러리 묶음과 사용자 정의 코드를 빌드할 수 있는 기본 핸들러로 구성됩니다.대부분의 웹 프레임워크는 적어도 다음과 같은 사항들을 달성하기 위한 패턴과 유틸리티를 갖추고 있습니다:

URL 라우팅
들어오는 HTTP 요청을 특정 파이썬 코드 조각에 연결시켜 실행합니다.
요청 & 응답 객체
사용자의 브라우저가 주고 받는 정보를 캡슐화합니다.
템플릿 엔진
어플리케이션의 로직을 구현하는 파이썬 코드를 그 파이썬 코드가 생성하는 HTML(또는 다른 무언가)로부터 분리합니다.
개발 웹서버
신속한 개발이 가능하도록 개발용 머신에 HTTP 서버를 실행합니다. 그리고 파일이 업데이트 될 때 자동으로 서버 측 코드를 다시 불러옵니다.

쟝고

쟝고 는 "batteries included" 웹 어플리케이션 프레임워크입니다. 컨텐츠 중심 웹사이트를 위한 훌륭한 선택입니다. 많은 유틸리티와 패턴을 기본적으로 제공함으로써 쟝고는 복잡한 데이터베이스 기반 웹 어플리케이션을 빠르게 개발할 수 있도록 해줍니다. 또한 쟝고를 사용하면 베스트 프랙티스라 할 코드 작성이 쉽습니다.

쟝고는 크고 활발한 커뮤니티를 가지고 있고, 바로 사용할 수 있는 다양한 재사용 가능 모듈 이 있다. 이 것을 새 프로젝트에 바로 적용할 수도 있고 필요하다면 커스터마이징 해서 사용할 수도 있다.

미국, 유렵, 그리고 오스트레일리아 에서 매년 쟝고 컨퍼런스를 한다.

요즘 새로 개발하는 파이썬 웹 어플리케이션은 대부분 쟝고로 만든다.

플라스크

Flask 는 파이썬의 "마이크로프레임워크" 입니다. 플라스크는 작은 어플리케이션, API, 웹 서비스를 만들기에 좋습니다.

플라스크로 앱을 만드는 일은 라우터가 연결된 함수라는 점을 제외하고는 파이썬 표준 모듈을 작성하는 것과 비슷합니다.정말 아름다워요.

플라스크의 목표는 필요할지 어떨지도 모를 모든 것들을 제공하는 게 아닙니다. 플라스크는 웹 어플리케이션에서 가장 많이 쓰이는 핵심 구성요소들(URL 라우팅, 리퀘스트-리스폰스 오브젝트, 템플릿)을 구현합니다.

플라스크를 사용할 때 어플리케이션을 어떻게 구성할 것인지는 전적으로 당신에게 달려있습니다. 예를 들어 데이터베이스 접근, 폼 생성 및 유효성 체크는 플라스크의 빌트인 함수가 아닙니다.

많은 웹 어플리케이션은 이런 기능을 필요로 하지 않습니다. 그러니 이런 기능이 내장되어 있지 않다는 것은 좋은 일입니다. 이런 기능이 필요하다면 적당한 익스텐션 이 많이 있습니다. 달리 사용하고 싶은 라이브러리를 써도 됩니다!

플라스크는 쟝고에 적당하지 않은 파이썬 웹 어플리케이션을 위한 기본 선택지입니다.

팔콘

Falcon 은 빠르고 확장 가능한 RESTful API 마이크로서비스 개발을 위한 좋은 선택입니다.

팔콘은 대규모 앱 백엔드와 마이크로서비스를 개발하기 위한 신뢰성 있고 성능 좋은 파이썬 웹 프레임워크입니다.Falcon은 URI를 리소스에 매핑하는 REST 아키텍처 스타일을 권장하며, 높은 효율성을 유지하면서 가능한 한 적은 작업을 시도합니다.

Falcon은 주요 4요소에 집중합니다. 속도, 신뢰성, 유연성 및 디버깅.on_get(), on_put() 등과 같은 "응답자"를 통해 HTTP를 구현합니다. 이러한 응답자는 직관적인 request 및 response 오브젝트를 수신 받습니다.

토네이도

Tornado 는 자체 이벤트 루프가 있는 파이썬을 위한 비동기 웹 프레임워크입니다. 이를 통해 웹소켓을 네이티브하게 지원합니다. 잘 작성된 토네이도 어플리케이션은 우서한 성능이 특징인 것으로 잘 알려져 있습니다..

토네이도가 필요하다고 생각하지 않는 한 저는 토네이도 사용을 추천하지 않습니다.

피라미드

Pyramid 는 모듈성에 크게 중점을 둔 유연한 프레임워크다. 빌트인 라이브러리 ("배터리") 가 많이 포함되어 있지 않기 때문에, 피라미드는 사용자가 피라미드의 기본 기능을 확장하도록 지원합니다. 붕어빵 틀처럼 쓸 수 있는 템플릿들을 제공하여 사용자가 새 프로젝트를 어떻게 만들지를 돕습니다. 피라미드는 가장 중요한 파이썬 인프라스트럭쳐 중 하나인 PyPI 를 지원합니다.

비록 피라미드의 사용자 수는 쟝고나 플라스크만큼 많지 않습니다. 피라미드는 써봄직한 프레임워크지만 오늘날 새 파이썬 웹 어플리케이션에는 인기가 없습니다.

매서나이트

Masonite 는 모던하고 개발자 중심적이며 "batteries included" 인 웹 프레임워크입니다.

매서나이트 프레임워크는 MVC(Model-View-Controller) 아키텍쳐 패턴을 따릅니다. 그리고 레일즈와 라바렐 같은 프레임워크로부터 강하게 영감을 받았습니다. 그렇기 때문에 루비나 PHP를 개발하다가 파이썬으로 오셨다면 내 집 같은 편안함을 느끼실겁니다.

매서나이트는 의존성 자둥 주입 기능이 있는 강력한 IOC 컨테이너, 정교한 커맨드라인 툴, Orator active record style ORM를 제공합니다.

매서나이트는 초보자부터 숙련된 개발자에 이르기까지 모두에게 적합합니다. 설치부터 개발에 이르기까지 빠르고 쉽게 작업할 수 있습니다. 한 번만 써보시면 사랑에 빠지게 될겁니다.

FastAPI

FastAPI 는 파이썬 3.6 이상 버전으로 API 개발을 하기 위한 모던 웹 프레임워크입니다.

StarlettePydantic 을 기반으로하여 매우 높은 성능을 가지고 있습니다

FastAPI는 함수 매개 변수의 표준 Python 형식 선언을 활용하여 요청 매개 변수 및 본문을 선언하고, 데이터 변환(시리얼화, 구문 분석), 데이터 유효성 검사 및 OpenAPI 3 (JSON Schema 포함) 를 사용한 API 문서 자동화 기능을 제공합니다.

여기에는 보안 및 인증을 위한 툴과 유틸리티(JWT 토큰이 있는 OAuth2 포함), 종속 주입 시스템, 대화형 API 문서의 자동 생성 및 기타 기능이 포함됩니다.

웹 서버

Nginx

Nginx ("엔진-엑스" 라고 발음함) 는 HTTP, SMTP, 그리고 다른 프로토콜을 위한 웹서버 및 리버스 프록시 입니다. 고성능, 상대적으로 단순함 및 WSGI 서버와 같은 많은 애플리케이션 서버와의 호환성으로 유명합니다. 또한 로드 밸런싱, 기본 인증, 스트리밍 등과 같은 편리한 기능도 포함합니다. Nginx는 부하가 많은 웹 사이트를 제공하도록 설계되었으며, 점점 인기가 많아지고 있습니다.

WSGI 서버

스탠드얼론 WSGI 서버는 일반적으로 전통적인 웹서버보다 리소스를 덜 잡아먹습니다. 그리고 성능이 좋습니다 [1].

지유니콘(Gunicorn)

지유니콘 (그린 유니콘)은 순수 파이썬 WSGI 서버로서 파이썬 어플리케이션을 서비스하는 데 쓰입니다. 다른 파이썬 웹서버와 달리 유저 인터페이스가 좋고 사용하기도 편하고 설정하기도 편합니다.

지유니콘은 건전하고 합리적인 기본 설정을 두고 있습니다. 대조적으로 uWSGI 같은 다른 서버들은 무서울 정도로 커스터마이징이 가능한 대신 효율적으로 사용하기는 어렵습니다.

지유니콘을 현재 새로 만드는 파이썬 웹 어플리케이션을 위한 선택으로 추천드립니다.

웨이트리스(Waitress)

Waitress 는 순수 파이썬으로 만들어진 WSGI 서버로서 "납득하고도 남을 만한 성능" 이 있다고 주장합니다. 문서는 상세하지 않습니다. 하지만 Gunicorn에 없는 멋진 기능(예를 들면 HTTP 리퀘스트 버퍼링)을 제공합니다.

웨이트리스는 파이썬 웹 개발 커뮤니티 사이에서 인기를 얻고 있습니다.

uWSGI

uWSGI 는 호스팅 서비스를 구축하는 용도로 쓰이는 풀스택 서버입니다. 프로세스 관리 뿐 아니라 프로세스 모니터링, 그리고 다른 기능까지 uWSGI는 다양한 프로그래밍 언어와 프로토콜(파이썬과 WSGI 포함)을 위한 어플리케이션 서버로서 동작합니다. uWSGI는 스탠드얼론 웹 라우터로서도 사용할 수 있고, (엔진엑스나 아피치 같은) 완전한 웹서버 뒤에서 동작할 수도 있습니다. 후자의 경우 웹서버는 uwsgi protocol 를 통해 uWSGI와 어플리케이션을 설정할 수 있다. uWSGI의 웹서버 지원 덕분에 파이썬의 설정을 동적으로 변경할 수 있고 환경변수도 넘길 수 있으며 추가 튜닝도 가능합니다. 더이상의 자세한 설명은 생략한다. uWSGI magic variables 을 참고하도록.

왜 uWSGI가 필요한지 이유를 알기 전까지는 이걸 사용하지 않기를 추천합니다.

서버 베스트 프랙티스

요즘은 자체 호스팅할 경우 대부분의 파이썬 어플리케이션을 Gunicorn 같은 WSGI 서버에 바로 호스팅합니다. 그렇지 않으면 nginx 처럼 가벼운 웹서버 뒤에서 호스팅합니다.

WSGI서버는 웹서버가 정적 파일 전송, 리퀘스트 라우팅, 디도스 보호, 기본적인 인증 같이 웹서버가 보다 잘하는 작업들을 수행하는 동안 파이썬 어플리케이션을 서빙합니다.

호스팅

Platform-as-a-Service (PaaS)는 인프라스트럭쳐와 라우팅, 웹 어플리케이션 확장을 추상화하고 관리하는 유형의 클라우드 컴퓨팅 인프라스트럭쳐입니다. PaaS를 사용하면 어플리케이션 개발자가 배포에 관해서 신경 쓸 필요없이 어플리케이션 코드 작성에 집중할 수 있습니다.

헤로쿠

Heroku 는 파이썬 2.7부터 3.5까지의 모든 어플리케이션을 확실하게 지원 보증합니다.

헤로쿠는 모든 종류의 파이썬 웹 어플리케이션과 서버 그리고 프레임워크를 지원합니다. 어플리케이션을 헤로쿠에 공짜로 배포할 수 있습니다. 일단 어플리케이션 배포 준비가 다 끝났다면 취미용 어플리케이션으로든 프로페셔널한 어플리케이션으로든 업그레이드 가능합니다.

헤로쿠는 파이썬을 헤로쿠에서 돌리기 위한 상세한 글 을 제공합니다. 뿐만 아니라 첫 어플리케이션을 셋업하기 위한 step-by-step 안내서 도 제공합니다.

현대 파이썬 웹 어플리케이션 배포를 위한 PaaS로 헤로쿠를 추천합니다.

템플릿

대부분의 WSGI 어플리케이션은 HTTP 요청에 대한 응답으로 HTML이나 다른 마크업 언어 형식의 컨텐츠를 제공합니다. 파이썬에서 직접 텍스트 컨텐츠를 들기보다는 관심사의 분리 개념을 적용하여 템플릿을 사용해봅시다. 템플릿 엔진은 불필요한 반복을 피하기 위해 계층 구조 및 포함 구조로서 여러 템플릿 파일들을 관리합니다. 그리고 템플릿의 정적 컨텐츠를 어플리케이션에서 만들어진 동적 컨텐츠로 채워서 실제 컨텐츠를 렌더링(생성)하는 역할을 합니다.

템플릿 파일은 종종 디자이너나 프론트엔드 개발자가 작성하는데, 이러면 복잡성이 올라가 다루기 힘들어질 수 있습니다.

몇 가지 일반적인 good 프랙티스를 적용하여 템플릿 엔진에 동적 컨텐츠를 전달하거나, 아니면 템플릿 자체를 전달해봅시다.

  • 템플릿에 동적 컨텐츠를 전달할 때는 템플릿 렌더링에 필요한 것들만 넘겨야 합니다. "만약의 경우": 를 대비한 추가적인 컨텐츠를 템플릿에 전달하지 마세요. 사용하지 않는 변수를 제거하는 것보다 빼먹은 변수를 추가하는 게 더 쉽다.
  • 많은 템플릿 엔진이 템플릿 자체 내에서 복잡한 구문과 할당을 합니다. 그리고 템플릿 안에서 파이썬 코드들이 평가되도록 합니다. 이 방법은 편리하지만 감당할 수 없는 복잡성을 증가시킵니다. 가끔은 버그를 찾기 힘들게 합니다.
  • 자바스크립트 템플릿과 HTML 템플릿을 섞어 써야 할 때가 있습니다. 이러한 디자인에 대한 제정신 박힌 접근법은 HTML 템플릿에서 자바스크립트로 값을 전달하는 부분을 분리하는 것입니다.

Jinja2

Jinja2 는 아주 잘 다듬어진 템플릿 엔진입니다.

텍스트 기반 템플릿 언어를 사용하기 때문에 HTML뿐만 아니라 모든 유형의 마크업을 생성하는 데 사용할 수 있으며 필터 태그, 테스트 및 전역 변수의 사용자 지정을 허용합니다. Django의 템플릿 시스템에 비해 많은 개선점을 가지고 있습니다.

Jinja2의 중요한 HTML 태그를 소개합니다:

{# This is a comment #}

{# The next tag is a variable output: #}
{{title}}

{# Tag for a block, can be replaced through inheritance with other html code #}
{% block head %}
<h1>This is the head!</h1>
{% endblock %}

{# Output of an array as an iteration #}
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}

다음은 토네이도 웹서버와 함께 Jinja2를 사용하는 예시입니다. 토네이도는 사용하기에 복잡하지 않습니다.

# import Jinja2
from jinja2 import Environment, FileSystemLoader

# import Tornado
import tornado.ioloop
import tornado.web

# Load template file templates/site.html
TEMPLATE_FILE = "site.html"
templateLoader = FileSystemLoader( searchpath="templates/" )
templateEnv = Environment( loader=templateLoader )
template = templateEnv.get_template(TEMPLATE_FILE)

# List for famous movie rendering
movie_list = [[1,"The Hitchhiker's Guide to the Galaxy"],[2,"Back to future"],[3,"Matrix"]]

# template.render() returns a string which contains the rendered html
html_output = template.render(list=movie_list,
                        title="Here is my favorite movie list")

# Handler for main page
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        # Returns rendered template string to the browser request
        self.write(html_output)

# Assign handler to the server root  (127.0.0.1:PORT/)
application = tornado.web.Application([
    (r"/", MainHandler),
])
PORT=8884
if __name__ == "__main__":
    # Setup the server
    application.listen(PORT)
    tornado.ioloop.IOLoop.instance().start()

예를 들어 base.html base.html 파일은 컨텐츠 블록에 구현된 모든 사이트 페이지의 기준으로 사용할 수 있습니다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{{title}} - My Webpage</title>
</head>
<body>
<div id="content">
    {# In the next line the content from the site.html template will be added #}
    {% block content %}{% endblock %}
</div>
<div id="footer">
    {% block footer %}
    &copy; Copyright 2013 by <a href="http://domain.invalid/">you</a>.
    {% endblock %}
</div>
</body>

다음 예시는 base.html 파일을 확장해서 python 앱에 사이트 페이지 (site.html) 를 로드한 경우입니다. base.html을 확장합니다. 컨텐츠 블록은 base.html 페이지의 해당 블록으로 자동 설정됩니다.

{% extends "base.html" %}
{% block content %}
    <p class="important">
    <div id="content">
        <h2>{{title}}</h2>
        <p>{{ list_title }}</p>
        <ul>
             {% for item in list %}
             <li>{{ item[0]}} :  {{ item[1]}}</li>
             {% endfor %}
        </ul>
    </div>
    </p>
{% endblock %}

새 파이썬 웹 엎ㄹ리케이션을 위한 템플릿 라이브러리로 Jinja2를 추천합니다.

카멜레온(Chameleon)

Chameleon Page Templates 은 HTML/XML template engine 구현체로서, Template Attribute Language (TAL), TAL Expression Syntax (TALES), 그리고 Macro Expansion TAL (Metal) 구문을 사용합니다.

카멜레온은 파이썬 2.5와 그 이상 (3.x와 PyPy 포함)에서 사용 가능하며, Pyramid Framework 에서 일반적으로 사용합니다."

페이지 템플릿은 문서 구조에 특수 엘리먼트 어트리뷰트와 텍스트 마크업을 추가합니다. 간단한 언어 구문으로 문서의 흐름과 엘리먼트의 반복, 텍스트 교체, 다국어 처리가 가능합니다. 어트리뷰트에 기반한 구문 덕분에 렌더링 되지 않은 페이지도 HTML 포맷으로 유효하며 브라우저에서 볼 수 있고 WYSIWYG 에디터로 수정도 가능합니다. 이를 통해 디자이너와 양방향 협업이 가능하고 브라우저에서 정적 파일을 프로토타이핑 하기도 쉽습니다.

기본 TAL 언어는 예제 하나만 봐도 이해할 수 있을 만큼 간단합니다:

<html>
  <body>
  <h1>Hello, <span tal:replace="context.name">World</span>!</h1>
    <table>
      <tr tal:repeat="row 'apple', 'banana', 'pineapple'">
        <td tal:repeat="col 'juice', 'muffin', 'pie'">
           <span tal:replace="row.capitalize()" /> <span tal:replace="col" />
        </td>
      </tr>
    </table>
  </body>
</html>

<span tal:replace="expression" /> 패턴을 텍스트 삽입에 사용하고 렌더링 되기 전의 템플릿이 유효한 HTML 구문일 필요가 없다면 다음과 같이 ${expression} 패턴을 사용해서 보다 간결하고 가독성 높은 구문으로 바꿀 수 있다.

<html>
  <body>
    <h1>Hello, ${world}!</h1>
    <table>
      <tr tal:repeat="row 'apple', 'banana', 'pineapple'">
        <td tal:repeat="col 'juice', 'muffin', 'pie'">
           ${row.capitalize()} ${col}
        </td>
      </tr>
    </table>
  </body>
</html>

하지만 <span tal:replace="expression">Default Text</span> 구문이 렌더링 되지 않았을 때 Default Text가 기본 값으로 찍힌다는 것을 명심하세요.

Pyramid를 사용하는 사람들은 Chameleon은 잘 안 씁니다.

마코(Mako)

Mako 는 파이썬의 최대 성능을 내기 위해 파이썬으로 컴파일 작업을 하는 템플릿 엔진입니다. Django와 Jinja2 같이 다른 템플릿 언어로부터 멋진 부분을 가져와 구문과 API를 만들었습니다. Pylons 과 Pyramid 웹 프레임워크의 기본 템플릿 언어입니다.

마코 템플릿 예제입니다:

<%inherit file="base.html"/>
<%
    rows = [[v for v in range(0,10)] for row in range(0,10)]
%>
<table>
    % for row in rows:
        ${makerow(row)}
    % endfor
</table>

<%def name="makerow(row)">
    <tr>
    % for name in row:
        <td>${name}</td>\
    % endfor
    </tr>
</%def>

다음과 같이 아주 간단한 템플릿을 렌더링 할 수 있습니다:

from mako.template import Template
print(Template("hello ${data}!").render(data="world"))

마코는 파이썬 웹 커뮤니티가 좋아하는 템플릿입니다.

참고

[1]Python WSGI Servers 벤치마크