Flask 시작하기

처음 혼자 웹 개발을 시작하면 어떤 프레임워크를 선택해서 공부해야 할지가 고민이 됩니다.(뭐가 적합한지 알아야지 선택을 하지…) 많은 프레임워크 중 Flask 또한 매력적인 선택지가 될 수 있지 않을까 싶습니다…! 일단 쉬운 언어인 파이썬이 기반이라는 점. 그리고 사용법도 간단하다는 점! 때문입니다.

이번 포스트에서는 Flask는 무엇이고, 어떻게 시작해야 하는지 정리해보았습니다.

선수 지식 : 파이썬 기초 문법, VScode 사용법

Flask 는?

FlaskPython으로 작성된 마이크로 웹 프레임워크로서, 간단하면서도 유연한 웹 애플리케이션을 구축하기 위한 도구입니다.

Flask는 작고 간결한 설계를 통해 개발자에게 큰 유연성을 제공합니다. 필요한 기능만을 포함하고 있어 핵심 기능에 집중할 수 있습니다..

Flask는 작은 규모의 프로젝트부터 중간 규모의 웹 애플리케이션까지 다양한 프로젝트에 유용하게 사용됩니다.

Flask 설치

flask 가상환경을 설정합니다.

가상환경 내에서 pip install flask로 패키지를 설치하면 끝입니다…!

Flask 폴더 구조

Flask는 대부분의 웹 개발 프레임워크와 마찬가지로 프로젝트 폴더 구조가 정해져 있습니다.

폴더 구조는 아래와 같습니다

  • 폴더 안에 app.py 파일을 생성
  • 폴더 안에 templates 폴더를 생성
  • templates 폴더 안에 index.html 파일을 생성
  • templates 폴더는 반드시 고정해야 합니다!
  • app.py는 변경해도 괜찮지만, 라이브러리 이름과 같은 것을 이름으로 사용하면 안 됩니다!

Flask 시작 코드

# app.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return 'This is Home!'

@app.route('/mypage')
def mypage():
    return 'This is mypage!'

if __name__ == '__main__':  
    app.run(debug=True)

코드를 실행 하면 터미널에 아래와 같은 글이 출력이 됩니다.


실행 시 보여주는 주소 http://127.0.0.1:5000 을 브라우저에 입력하면 서버가 만들어져서 ‘This is Home!’ 이 적힌 화면에 출력되는 것을 확인 할 수 있습니다.

http://127.0.0.1:5000/mypage 을 입력하면 mypage로 연결되어 ‘This is mypage!’ 가 적힌 화면이 출력되는 것을 확인 할 수 있습니다.

Flask로 웹페이지 구축이 완료되었습니다!!

HTML 랜더링

이전 예제에서는 화면에 문자열만 뿌려 주었습니다. 이렇게 화면에 요소들을 표시하는 과정을 “랜더링”이라고 합니다.
하지만 위의 예제처럼 문자열만 표시하려고 웹페이지를 만들지는 않겠죠?
HTML 파일을 가져다가 렌더링 할 수 있게 해주는 함수가 render_template 입니다.

render_templateimport하고 아래와 같은 방식으로 return 합니다

# app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

if __name__ == '__main__':  
    app.run(debug=True)

위와 같이 입력하고 실행하면 templates 디렉토리에 있는 index.html 내용을 화면에 표시해 줄 수 있습니다.

파이썬 데이터를 HTML에 넘겨주기

HTML에 데이터 넘기기

app.py에서 나온 데이터를 HTML 파일에 넘겨 줄 수 있습니다.
render_template 함수에서 data 파라미터에 원하는 데이터를 넘기면 됩니다.

# app.py 
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    str_data = '사용할 데이터'
    return render_template('index.html', data=str_data)

if __name__ == '__main__':  
    app.run(debug=True)

HTML에서 데이터 받기

{{ data }} 이중 중괄호에 띄어쓰기를 하고 그 사이에 data를 넣어주면 app.py에서 넘겨준 데이터를 받을 수 있습니다.

<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>app.py에서 입력 받은 데이터 : {{ data }}</h1>
  </body>
</html>

파이썬의 여러 데이터를 HTML에 넘겨주기

하나의 텍스트가 아니라, 배열, 딕셔너리 같은 객체로 데이터들을 HTML로 넘길 수 있습니다.

# app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    data_dic = {'artist': '',
                'title': '기억을 걷는 시간'}
    return render_template('index.html', data=data_dic)

if __name__ == '__main__':  
    app.run(debug=True)

data 파라미터에 data_dic으로 딕셔너리를 넘긴 것을 확인해 주세요

<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>app.py에서 입력 받은 데이터 : {{ data.artist }}, {{ data.title }}</h1>
  </body>
</html>

data.key 형태로 딕셔너리 데이터를 받은 것을 확인해 주세요


브라우저에 성공적으로 내용들이 전달 된 것을 확인 할 수 있습니다.

HTML에서 파이썬으로 데이터를 넘겨주기

form 태그를 통해서 파이썬의 특정 함수에 데이터를 보낼 수 있습니다.

HTML

form 태그 하위에 input 태그와 button 태그를 넣어서 데이터를 보내는 것이 일반적입니다.

<!-- 데이터를 보낼 곳을 action 속성에 입력 -->
<form action="{{ url_for('movie') }}">
	<!-- input name은 데이터 이름 -->
	<input type="text" name="query">
	<button type="submit">검색</button>
</form>

input 태그의 name 속성에 데이터 이름을 적습니다.

name 속성의 값은 파이썬에서 request.args.get('데이터 이름')에 받은 데이터 이름입니다.

button 태그의 type은 ‘submit‘ 입니다.

Python

HTML에서 보낸 데이터를 받기 위해 flask 라이브러리에서 request 함수를 import 합니다.

request.args.get('데이터 이름') 으로 HTML에서 보낸 데이터를 파이썬에서 받습니다.

from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/movie')
def movie():
    print(request.args.get('query'))  # input tag에서 받은 name 속성 값
    return render_template('movie.html')

if __name__ == '__main__':
    app.run(debug=True)

HTML 파일에서 반복문 사용하기

Flask를 사용하면 원래는 화면의 레이아웃만 구성해주는 언어인 HTML에서 반복문을 사용할 수 있게 됩니다.

VScode에서 ffor를 입력하면 반복문을 자동완성 시킬 수 있습니다.

딕셔너리에 리스트를 포함해서 data 파라미터로 넘겨주고 HTML에서 받아서 반복문으로 내용을 표시해보겠습니다.

# app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    data_dic = {'artist': '',
                'title': '기억을 걷는 시간',
                'filmography': ['2006년 동아일보 최고의 앨범 선정',
                                '2008년 4월 27일 SBS 《인기가요》 뮤티즌송',
                                '제5회 한국대중음악상 시상식 모던록 부문 네티즌이 뽑은 올해의 음악인상',
                                '2011년 그랜드 민트 페스티벌 어워즈 최고의 공연 상 수상',
                                '2012년 멜론 뮤직 어워드 뮤직스타일상 락 부문 (그리고, 남겨진 것들)',
                                "2014년 빌보드 선정 올해의 K-Pop 앨범 제2위 (Newton's Apple)",
                                "2015년 제11회 골든티켓어워즈 최고의 라이브밴드상",
                                "Doindie 2016년 최고의 인디앨범"]}
    return render_template('index.html', data=data_dic)

if __name__ == '__main__':  
    app.run(debug=True)

HTML 파일에서 {% for element in data %} {{ element|e }} {% endfor %} 을 사용해서 반복문을 시행할 수 있습니다.

<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>app.py에서 입력 받은 데이터 : {{ data.artist }}, {{ data.title }}</h1>
    {% for element in data.filmography %} {{ element|e }} {% endfor %}
  </body>
</html>

실행 결과

HTML 조작하기

위에서 반복문을 이용해서 HTML을 조작하는 예제를 보여드렸습니다. 이와 같이 Flask에서 HTML를 조작하기 위한 기본 문법을 정리해보았습니다.

조건문

<!-- if 문 -->
{% if expression %}
    blockofcode
{% endif %}

<!-- elif 문 -->
{% if expression %}
    blockofcode
{% elif expression2 %}
    blockofcode
{% else %}
    blockofcode
{% endif %}

괄호와 % 기호를 감싸주는 것 때문에 타이핑이 힘듭니다…
VScode에서 간단하게 fif, felif 를 입력하면 자동완성이 됩니다.

예제 코드

# app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    is_authenticated = True
    return render_template('index.html', is_authenticated=is_authenticated)

if __name__ == '__main__':  
    app.run(debug=True)
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Flask Template Example</title>
  </head>
  <body>
    {% if is_authenticated %}
    <p>Welcome, authenticated user!</p>
    {% else %}
    <p>Please log in.</p>
    {% endif %}
  </body>
</html>

is_authenticated 변수에 True값을 할당해서 전달했습니다.
HTML에서 조건문으로 is_authenticated 변수가 True인 것을 확인하고 “Welcome, authenticated user!” 텍스트를 화면에 표시하였습니다.


실행 화면

반복문

이미 위에서 확인한 방법입니다…!ㅎㅎ ffor 를 입력하면 자동완성이 가능합니다.

{% for element in collection %}
    {{ element|e }}
{% endfor %}

{{ element|e }}에서 element|e는 Jinja2의 필터(Filter)를 사용한 부분입니다. 여기서 e는 “escape”의 약어로, 특수 문자를 이스케이프하여 안전하게 출력하도록 도와주는 필터입니다.

일반적으로 이스케이프는 사용자로부터의 입력을 안전하게 처리하기 위해 필요합니다. 사용자의 입력을 그대로 출력하는 경우, 예를 들어 <script>와 같은 HTML 태그가 포함된 입력이 있다면 이는 웹 애플리케이션에 보안 문제를 일으킬 수 있습니다. 따라서 이스케이프 필터를 사용하여 사용자 입력을 안전하게 출력할 수 있습니다.

필터

변수에 필터를 적용하여 출력을 수정할 수 있습니다. 예를 들어, 변수를 대문자로 바꾸거나 날짜 형식을 변경하는 등의 작업이 가능합니다.

<!-- 예: 대문자로 변경 -->
<p>{{ name|upper }}</p>

매크로

매크로는 재사용 가능한 코드 블록을 정의할 수 있는데, 함수처럼 호출하여 코드를 삽입할 수 있습니다.

<!-- 매크로 정의 -->
{% macro render_card(title, content) %}
    <div class="card">
        <div class="card-header">{{ title }}</div>
        <div class="card-body">{{ content }}</div>
    </div>
{% endmacro %}

<!-- 매크로 호출 -->
{{ render_card("Card Title", "Card Content") }}

템플릿 상속

템플릿 상속을 사용하면 공통된 레이아웃을 정의하고, 각 페이지에서 이 레이아웃을 확장하여 사용할 수 있습니다.

<!-- 기본 레이아웃 템플릿 -->
<!-- templates/layout.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>
<!-- 특정 페이지에서 레이아웃 확장 -->
<!-- templates/index.html -->
{% extends 'layout.html' %}
{% block title %}Home{% endblock %}
{% block content %}
    <h1>Welcome to the home page!</h1>
{% endblock %}

{% block title %}: 이 부분은 layout.html 템플릿에서 title 블록에 해당하는 부분을 의미합니다. 이 블록은 다른 템플릿에서 확장될 때 해당 템플릿에서 제공되는 내용으로 대체됩니다.

{% block content %}: 이 부분은 layout.html 템플릿에서 content 블록에 해당하는 부분을 의미합니다. 마찬가지로 다른 템플릿에서 이 부분을 확장할 때 해당 템플릿에서 제공되는 내용으로 대체됩니다

조건부 상속 (Conditional Inheritance)

특정 조건에 따라 다른 레이아웃을 상속하는 것이 가능합니다.

{% extends 'layout_home.html' if is_home_page else 'layout_other.html' %}

템플릿 포함 (Template include)

템플릿 인클루드를 사용하면 다른 템플릿 파일을 현재 템플릿에 삽입할 수 있습니다.

<!-- templates/footer.html -->
<footer>
    <p>Copyright © 2022 My Website</p>
</footer>
<!-- templates/index.html -->
{% include 'footer.html' %}

템플릿 상속과 include 차이

include는 단순히 다른 템플릿의 내용을 현재 템플릿에 삽입하는 역할을 합니다.
extend{% block %}을 통해 정의된 블록들을 하위 템플릿에서 오버라이드할 수 있어서, 레이아웃을 기반으로 한 일관된 디자인을 유지하면서도 각 페이지의 내용을 다르게 표현할 수 있습니다.

이미지 삽입하기

이미지를 삽입하기 위해서는 Flask 프로젝트 하위에 “static” 디렉토리 내에 이미지를 위치 시켜야 합니다.

“static” 디렉토리 내에 위치시키는 것만 필수이기 때문에 “static” 디렉토리 하위의 디렉토리에 넣어줘도 상관 없습니다.

디렉토리 구조는 아래와 같습니다. 저는 static/image 디렉토리 안에 HA5.jpg 파일을 넣었습니다.

static 디렉토리 내부 디렉토리에 그림 파일이 위치한 것에 유의합니다.

아래와 코드 형식으로 이미지를 넣습니다.

<img src="{{ url_for('static', filename='[file path]') }}" alt="Image" />

실제 아래처럼 코드를 작성하고 실행하면 그림이 뜨는 것을 확인 할 수 있습니다.

<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Flask Template Example</title>
  </head>
  <body>
    <img src="{{ url_for('static', filename='image/HA5.jpg') }}" alt="Image" />
  </body>
</html>

실행 결과

참고할 만한 글

Leave a Comment

목차