이전 포스팅들, 「파이썬 웹 프로그래밍 기본」에서 파이썬 플라스크 패키지와 파이썬으로 만드는 웹 프로그래밍의 기본적인 요소들에 대해 살펴보았다. 최대한 쉽게 풀어서 쓰려고 했지만 돌아보면 뭔가 미흡했던 것 같기도 하고, 좀 더 쉽게 풀어쓰지 못한 아쉬움도 남는다.
변명일 수도 있지만 익숙해지기 위해서는 어느 정도의 시간과 인내가 필요한 것이 사실이라고 생각한다. 여담이지만 공자님 말씀 '빨리 가려하지 말고 작은 이익에 마음 흔들리지 마라. 서두르면 어떤 일이건 숙달하기 어렵고, 작은 이익을 자꾸 생각하면 큰 일은 이루기 힘들다(무욕속 무견소리 욕속즉부달 견소리즉대사불성, 無欲速 無見小利 欲速則不達 見小利則大事不成).'이 맞는 말씀이라는 생각이든다.
이어지는 포스팅들에서는 플라스크와 파이썬을 이용해서 블로그 서비스를 만들어보려 한다. 하나씩 익혀나가다 보면 파이썬으로 만드는 웹 서비스가 이런거로구나 감이 오리라 생각한다.
가장 먼저 웹 서비스의 기본 틀(뼈대)을 잡아보자. 이 기본 틀에 기능을 하나씩 붙여나가면서 웹 서비스를 만들어 갈 것이다. 예제를 진행할 파이참(PyCharm) 개발 환경에 프로젝트를 하나 새로 만들고, 아래와 같이 디렉토리를 만들자. 필자는 프로젝트 이름을 PythonFlaskBlog, 예제 디렉토리 이름을 01_flask_blog_template이라고 했지만 다른 이름으로 해도 괜찮다.
디렉토리 구조를 잠깐 살펴보자. 예제는 appmain이라는 이름의 패키지로 구성된다. appmain 패키지는 플라스크 웹 서비스(=app)를 구성하는 주 패키지(=main)가 될 것이다.
패키지는 특정 기능을 수행하는 파이썬 요소(클래스, 함수)들의 집합이다.
① appmain 패키지 아래에 다시 templates, static 디렉토리를 만들고
② static 디렉토리 안에는 css라는 이름으로 디렉토리를 만들자.
css 디렉토리 안에는 CSS 파일을 넣을 것이고, templates 디렉토리 안에는 웹 페이지(정확히는 보여지는 화면인 뷰(view))를 구현하는 HTML 파일들을 넣을 것이다.
CSS(Cascading Style Sheet)는 웹 페이지를 구성하는 요소들(HTML 엘리먼트)의 속성(색상, 테두리, 여백 등)과 위치 등을 지정하는 파일이다. 예제에서는 CSS와 같은 디자인 요소들은 사용하지 않을 것이다.
아래와 같이 CSS 파일과 HTML 파일들을 해당하는 디렉토리에 코딩하자.
CSS 파일은 내용을 비워놓자.
▶ appmain/static/css/main.css
HTML 템플릿 중 layout.html은 웹 페이지들의 바탕(layout)이 되는 틀을 제공한다. 예를 들면 '홈 페이지로 돌아가기', '사이트 소개' 등 모든 웹 페이지에서 필요한 공통 요소들을 제공한다.
▶ appmain/templates/layout.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='css/main.css')}}">
{%if title%}
<title>{{title}}</title>
{%else%}
<title>Flask Exercise</title>
{%endif%}
</head>
<body>
<a href="{{url_for('main.home')}}">Home</a>
<a href="{{url_for('main.about')}}">About</a>
<div>
{%block content%}{%endblock content%}
</div>
</body>
</html>
layout.html HTML 스크립트에서 사용된 url_for() 함수는 인자로 전달된 함수의 위치를 URL로 변환해서 반환한다. 플라스크 웹 프레임워크를 사용하면서 편리한 기능 중 하나라고 생각한다.
{% %} 구문은 플라스크의 jinja2 템플릿 엔진에 의해 실행되는 부분이다. 조건문(if), 반복문(for) 등의 제어구문은 {% %}로 감싸고, 파이썬 웹 스크립트로부터 전달받는 변수는 {{ }}로 표시한다.
{%block content%} ~ {%endblock content%}는 다른 HTML 파일로 부터 내용을 받을 수 있는 부분이다. 이어서 살펴볼 about.html, home.html 파일에서 그 예를 곧 살펴보겠다.
다음으로 홈 페이지(home.html)와 사이트 소개 페이지(about.html)를 작성해서 넣자.
▶ appmain/templates/home.html
{%extends "layout.html"%}
{%block content%}
{%for post in posts%}
<h1>{{post.title}}</h1>
<p>{{post.content}}</p>
<p>By {{post.author}} on {{post.datePosted}}</p>
{%endfor%}
{%endblock content%}
▶ appmain/templates/about.html
{%extends "layout.html"%}
{%block content%}
<h1>About Page</h1>
{%endblock content%}
home.html 뷰(view) 파일은 플라스크 jinja2 템플릿 엔진으로부터 post라는 딕셔너리를 받아와서 그 내용(title, content, author, datePosted)을 웹 브라우저 창에 보여준다. 파일의 첫 행의 {% extends %} 구문은 지정한 파일(layout.html)을 확장하겠다는 의미이고, 확장되는 내용이 {% block %} ~ {% endblock %}에 기술된다.
이제 웹 페이지 요청을 받고 전달하는 웹 서버 로직을 플라스크 프레임워크를 이용해서 만들어보자.
프레임워크란 특정한 목적을 달성하기 위해 상호 작용하는 여러 구성 요소들의 집합 그리고 구성 요소들 사이의 상호작용 하는 방법이라고 정의할 수 있다.
아래와 같이 appmain 디렉토리 안에 __init__.py(앞 뒤로 _가 2개 씩)와 routes.py 파일을 작성해서 웹 서비스 기능을 제공하는 appmain 패키지를 만들자.
▶ appmain/routes.py
from flask import Flask, render_template, redirect, url_for, Blueprint
posts = [
{
'author': 'Elsa',
'title': 'Blog posting 1',
'content': 'The first posting',
'datePosted': 'September 6, 2020'
},
{
'author': 'Anna',
'title': 'Blog posting 2',
'content': 'The second posting',
'datePosted': 'September 7, 2020'
}
]
#### Blueprint 객체를 생성한다.
main = Blueprint('main', __name__)
#### Blueprint의 route 데코레이터를 이용해서 URL과 해당 URL에 접속했을 때 실행될 함수를 지정한다.
@main.route("/")
@main.route("/home")
def home():
return render_template("home.html", posts = posts)
@main.route("/about")
def about():
return render_template("about.html", title = 'About')
아직 DB와 같은 데이터 저장소가 없기 때문에 posts라는 이름의 리스트에 간단한 글을 넣어놓았다. 더불어 main이라는 이름으로 Blueprint 객체를 생성하고 이 Blueprint 객체의 route함수를 이용해서 사용자가 URL에 접근했을 때 실행될 함수를 지정해주었다.
▶ appmain/__init__.py
from flask import Flask
#### 플라스크 웹 서버를 생성한다.
app = Flask(__name__)
#### 웹 페이지 사이에 데이터를 주고 받는 경우(예, 사용자 입력 등) 비밀키를 함께 주소 받아서
#### 웹 페이지 위조(CSRF)와 같은 보안 위협에 대비한다.
app.config['SECRET_KEY'] = '97f802e4498c0ce2b8db61eec69268be'
#### routes.py 파일에서 생성한 Blueprint 객체 main을 가져온다.
from appmain.routes import main
#### 플라스크 객체에 웹 서비스를 제공할 수 있도록 가져온 Blueprint 객체를 등록한다.
app.register_blueprint(main)
__init__.py 파일에는 패키지가 만들어질 때 해야할 작업들을 기술한다. appmain 패키지는 웹 서비스를 제공하는 기능을 수행하므로 플라스크 웹 서버를 생성하고, 보안에 필요한 비밀 키 등록, 그리고 웹 서비스 URL을 등록하는 작업을 기술하였다.
__init__.py 파일이 포함된 디렉토리는 파이썬 번역기에 의해 '패키지'로 인식된다. 따라서 특정 디렉토리를 패키지로 작성하였다면 패키지 생성 시에 초기화할 내용이 없더라도 내용이 비어있는 __init__.py 파일을 반드시 만들어주자.
※ 참고로 웹 페이지 위조(CSRF) 보안 위협에 대해서는 '파이썬 웹 프로그래밍 기본' 카테고리의 '5. 입력 처리 - 5.1. 비밀 토큰(secret token)' 포스팅에서 자세히 살펴보았다.
최종적으로 웹 서버 패키지인 appmain 패키지를 동작시키는 파일을 예제 프로젝트 디렉토리에 작성하자.
▶ run.py
from appmain import app
if __name__ == "__main__":
app.run("127.0.0.1", 5000)
만약 run.py 파일이 다른 파일에 포함되어지는 것이 아니라면(이 경우 파이썬 번역기에 의해 '__main__'이라는 이름이 부여된다) 필요한 IP와 포트 번호를 부여하고 플라스크 서버를 실행시킨다.
프로젝트를 실행시키기 전에 Flask 패키지를 설치해야 한다. 아래와 같이 파이참 메뉴의 File → Settings로 들어간다.
왼쪽의 네비게이션 바에서 'Project Interpreter' 항목을 선택하고 오른쪽 메뉴 창의 'pip' 패키지를 더블 클릭한다.
패키지 검색 창이 나타나면 검색 창에 'Flask'를 입력하여 검색하고 Install Package 버튼을 눌러 설치한다.
이제 아래와 같이 run.py 파일 위에 마우스 커서를 위치시키고 Run 기능을 선택해서 예제를 실행시키자.
프로젝트가 정상적으로 실행되면 파이참의 메시지 창에 아래와 같은 메시지들이 나타날것이다.
웹 브라우저를 열고 http://127.0.0.1:5000 주소를 입력해서 서버에 접근해보자. 127.0.0.1은 내 컴퓨터를 지칭하는 주소이므로 결국 웹 서버는 내 컴퓨터에서 실행되는 프로그램이라는 것을 알 수 있다.
아래와 같이 파이참의 Stop 버튼을 이용하여 실행중인 프로젝트를 중지할 수 있다.
플라스크로 웹 서비스를 만들기위한 기초 작업으로 프로젝트의 뼈대를 만들었다. 플라스크 웹 서버 프로그램과 그 동작이 이번 포스팅에서 간단하면서도 명확하게 설명되었기 때문에 직접 코딩하면서 살펴보았으면 좋겠다. 더불어 '파이썬 웹 프로그래밍 기본' 카테고리의 '3. 웹 프로그램 동작 원리 - 3.2. Flask 예제 분석' 포스팅의 내용을 참고하면 이번 포스팅을 이해하는데 도움이 될 것이다.
앞으로 이어지는 포스팅들에서는 로그인, 데이터베이스 사용, 템플릿 엔진 등의 기능을 이 기본 틀에 추가해가면서 웹 서비스를 구성하는 다양한 기능들에 대해 살펴보기로 하겠다.
■
'파이썬 웹 서비스 만들기' 카테고리의 다른 글
4. 계정 인증(로그인) 기능 - 4.1. 쿠키와 세션 (0) | 2020.10.05 |
---|---|
3. 사용자 등록 기능 - 3.3. 계정 생성 (0) | 2020.09.30 |
3. 사용자 등록 기능 - 3.2. 정보입력 페이지 (0) | 2020.09.24 |
3. 사용자 등록 기능 - 3.1. 계정 정보 정의 (0) | 2020.09.21 |
2. MVC: 모델/폼 - 뷰 - 로직(컨트롤) (0) | 2020.09.14 |
댓글