플라스크 프레임워크
파이썬으로 작성된 마이크로 웹 프레임워크이다.
이 프레임워크를 통해 웹페이지 제작이 가능하며,
Reddit, Linkedin, Netflix, Uber, Zillow, Airbnb 와 같은 사이트들이 플라스크를 이용해 개발되었다.
마이크로 웹 프레임워크 :
특별한 도구 또는 라이브러리가 필요 없는 프레임워크
다른 프레임워크와 비교
프레임워크 | 언어 | 설명 |
---|---|---|
flask | python | 작성하기 비교적 간단하다. MVC를 명확하게 분리해 사용하지 않아도 되지만, 다른 프레임워크보다 적은 기능들만 구현이 가능하다. 프로그래밍 언어 특성상 많은 접속자를 감당할 수 없다. 또한, 사이트가 복잡해질수록 체계적인 관리가 어렵다는 단점이 있다. |
Django | python | 모델-뷰-컨트롤러가 분리된 MVC 모델을 짜는 데 최적화되어있다. 프로그래밍 언어 특성상 많은 접속자를 감당할 수 없다. |
Java를 이용한 서버 | java | 많은 접속자를 감당할 수 있으며, 현업에 필요한 보안 기능 등을 구현할 수 있다. 또한 위 두 프레임워크보다 많은 기능을 구현할 수 있으며, 현업에서 많이 사용되는 만큼 그 정보 또한 더 쉽게 얻을 수 있다. MVC모델을 명확히 구분해 구축할 수 있다. |
준비
- flask 설치
1
pip install flask
사용법
플라스크는 컨트롤러와 모델이 하나의 코드파일에서 작성이 가능하다.
시작하기
(1) flask를 import 해준다.
(2) 변수에 flask 를 선언해준 뒤, 이 변수에 페이지들을 쌓아준다.
(3) 새로운 페이지는 메서드 정의 형태 (def)로 선언한다.
(4) 데코레이터(@)로 페이지에 접속하는 요청 경로를 선언한다.
(5) 플라스크 서버 실행은 변수명.run
을 통해 해주며, 호스트와 포트넘버 지정이 이 때 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
app = Flask(__name__)
@app.route("/")
def anyname():
return "안녕하세요 아무개입니다."
@app.route('/app1')
def app1():
return 'hello, its app1'
@app.route('/app2')
def app2():
return 'hello, its app2'
# app.run(host = '192.168.10.25', port = 5000)
app.run(host = 'localhost', port = 5002)
HTML 코드 사용
HTML 코드를 string화 하여 return에 넘겨줌으로써 html 코드 사용이 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from flask import Flask
app = Flask(__name__)
@app.route('/')
def anyname():
page = f'''
<html>
<head><title> 아무개입니다. </title></head>
<body>
<p>안녕하세요. 아무개입니다.</p>
</body>
</html>
'''
return page
app.run(host = 'localhost', port = 5002)
동적 변수 사용
동적 변수는 html코드 내 중괄호 {동적변수} 로 선언하여 사용할 수 있다.
아래는, 페이지에 방문할 때마다 방문 횟수가 1씩 증가하는 페이지를 만드는 코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from flask import Flask
app = Flask(__name__)
mycount = 0
@app.route('/')
def anyname():
global mycount
mycount += 1
page = f'''
<html>
<body>
<p>{mycount}회 방문입니다.</p>
</body>
</html>
'''
return page
app.run(host = 'localhost', port = 5002)
여러 페이지 만들고 연결하기
여러 페이지를 만들고, 서로 이동을 하는 구조 또한 만들 수 있다.
아래 예시에서는 아래와 같은 총 3개의 페이지를 가지고 있다.
(1) build_input_page : 방문횟수가 표시되는 페이지
(2) app_input : 방문횟수를 +1 씩 카운트하는 페이지
(3) root : 처음 방문하면 보이는 루트 페이지. app_input으로 연결되는 링크를 가지고 있다.
그리고 이들 페이지는 아래와 같이 연결된다.
No | 페이지 | 작동 내용 | 행위 |
---|---|---|---|
1 | root로 접속 | ||
2 | root | root페이지가 표시됨 | root페이지의 링크 클릭 |
3 | input | count에 +1이 더해짐 | |
4 | build_input_page | build_input페이지가 표시됨 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from flask import Flask
app = Flask(__name__)
mycount = 0
def build_input_page(my_count):
page = f'''
<html>
<body>
<p>안녕하세요. 아무개입니다.</p>
<p>{mycount}회 방문입니다.</p>
</body>
</html>
'''
return page
@app.route('/input')
def app_input():
global mycount
mycount += 1
page = build_input_page(mycount)
return page
@app.route('/')
def root():
return'''
<html>
<body>
<a href='/input'> 이 곳을 누르면 방문 횟수로 count 됩니다. </a>
</body>
</html>
'''
app.run(host = 'localhost', port = 5002)
상호작용 페이지 만들기 = 요청 받기
Flask의 request 모듈을 이용하여, 페이지 접속자의 요청값을 받아올 수 있다.
요청값을 받는 방법은 (1)주소창을 통해 요청값을 받을 수 있고, (2)아래와 같이 입력 form을 이용할 수도 있다.
1
2
3
4
<form action='입력 요청값을 보낼 페이지' method='get'>
입력해주세요 : <input type='text' name='입력값 변수 명'></input>
<input type='submit'></input>
</form>
받은 요청값을 이용하는 페이지의 데코레이터에는 아래와 같이 methods 를 지정해주면 됩니다.
1
@app.route('요청명', methods=['POST', 'GET'])
받은 요청값을 백엔드부에서 이용하기 위해, 아래와 같이 백엔드 변수에 받은 요청값을 넣어줄 수 있다.
1
백엔드 변수명 = request.args.get('입력값 변수명')
예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from flask import Flask
from flask import request
# 수신 결과를 받는 모듈 flask.request
app = Flask(__name__)
def build_input_page():
page = f'''
<html>
<body>
Iris 분류를 위해 꽃의 치수를 cm 단위로 입력해 주세요. <br>
<form action='http://localhost:5002/result' method='get'>
sepal_length : <input type='text' name='sepal_length'></input>cm<br>
sepal_width : <input type='text' name='sepal_width'></input>cm<br>
petal_length : <input type='text' name='petal_length'></input>cm<br>
petal_width : <input type='text' name='petal_width'></input>cm<br>
<input type='submit'></input><br>
</form>
</body>
</html>
'''
return page
def build_result_page():
sepal_length = request.args.get('sepal_length')
sepal_width = request.args.get('sepal_width')
petal_length = request.args.get('petal_length')
petal_width = request.args.get('petal_width')
multiple = (int(sepal_length) * int(sepal_width) * int(petal_length) * int(petal_width))
# multiple = sepal_length * sepal_width * petal_length * petal_width
page = f'''
수신 내용이 맞는지 확인해주세요 <br>
* sepal_length : {sepal_length} <br>
* sepal_width : {sepal_width} <br>
* petal_length : {petal_length} <br>
* petal_width : {petal_width} <br>
모든 값 곱하기 : {multiple}<br>
'''
return page
@app.route('/')
def home_page():
page = build_input_page()
return page
@app.route('/result', methods=['POST','GET'])
def result_page():
page = build_result_page()
return page
app.run(host='localhost', port=5002)
분류 모델을 불러와 이용해보기
미리 학습된 Iris 분류용 DecisionTree 모델 dt_model
을 불러와, 사용자의 요청값에 따라 꽃의 종류를 분류해주는 페이지를 작성해본다.
사용자 요청값을 받아오고 이용하는 방법은 윗 단락 (상호작용 페이지 만들기 = 요청 받기) 을 확인하면 된다.
미리 학습된 모델은 피클로 저장되었으며, 아래와 같은 코드로 불러와 사용한다.
1
2
with open('pickled_model_iris.bin', 'rb') as f:
dt_model_loaded = pickle.load(f)
예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from flask import Flask
from flask import request
import pickle
app = Flask(__name__)
# 모델 불러오기
with open('pickled_model_iris.bin', 'rb') as f:
dt_model_loaded = pickle.load(f)
# 꽃 종류 이름들
label_names = ['setosa', 'versicolor', 'virginica']
def build_input_page():
page = f'''
<html>
<body>
Iris 분류를 위해 꽃의 치수를 cm 단위로 입력해 주세요. <br>
<form action='http://localhost:5002/result' method='get'>
sepal_length : <input type='text' name='sepal_length'></input>cm<br>
sepal_width : <input type='text' name='sepal_width'></input>cm<br>
petal_length : <input type='text' name='petal_length'></input>cm<br>
petal_width : <input type='text' name='petal_width'></input>cm<br>
<input type='submit'></input><br>
</form>
</body>
</html>
'''
return page
def build_result_page():
sl = float(request.args.get('sepal_length'))
sw = float(request.args.get('sepal_width'))
pl = float(request.args.get('petal_length'))
pw = float(request.args.get('petal_width'))
global dt_model_loaded
global label_names
result_idx = dt_model_loaded.predict([[sl, sw, pl, pw]])
result_name = label_names[int(result_idx)]
page = f'''
수신 내용이 맞는지 확인해주세요 <br>
* sepal_length : {sl} <br>
* sepal_width : {sw} <br>
* petal_length : {pl} <br>
* petal_width : {pw} <br>
* 꽃의 종류 : {result_name}<br>
'''
return page
@app.route('/')
def home_page():
page = build_input_page()
return page
@app.route('/result', methods=['POST','GET'])
def result_page():
page = build_result_page()
return page
app.run(host='localhost', port=5002)
백엔드 - 프론트엔드 분리
파이썬 프레임워크에서는 ‘템플릿’이라고 부르는 프론트엔드 코드를 외부에 빼 따로 개발을 진행할 수 있다. (뷰와 컨트롤러의 분리가 목적이다.)
템플릿은 html과 같은 뷰를 만들 수 있는 코드가 해당된다.
더불어 CSS와 같은 외부 스타일시트도 사용이 가능하다.
- 템플릿들은
templates
폴더 안에 위치해야 한다. - CSS 파일은
static
폴더 안에 위채해야 한다. - 이미지, 멀티미디어 소스 등 또한
static
폴더 안에 위치해야 한다.
백엔드(컨트롤러) - 프론트엔드 분리
플라스크에서 템플릿 파일을 이용하기 위해 flask 라이브러리 내의 render_template
모듈을 사용한다.
1
2
3
4
5
6
7
8
9
10
11
# 백엔드 코드
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route('/')
def home_page():
return render_template("flask_index.html")
app.run(host = 'localhost', port = 5002)
1
2
3
4
5
6
7
8
<!-- 뷰(html) 코드 -->
<html>
<head> 템플릿 페이지입니다. </head>
<body>
안녕하세요. 템플릿 바디입니다. <br>
render_template를 이용한 뷰 - 컨트롤 분리입니다. <br>
</body>
</html>
동적 변수 할당
뷰단에서 컨트롤러로부터 받은 변수를 사용할 수도 있다.
이 방식은 Django에서도 동일하다.
먼저, 컨트롤러에서 뷰로 전달할 변수를 render_template
메서드의 파라미터 값으로 선언을 해주고,
1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route('/')
def home_page():
page = render_template("flask_index.html",
var1 = '변수 1입니다.',
var2 = '변수 2입니다.')
return page
app.run(host = 'localhost', port = 5002)
뷰에서는 중괄호 두 개 사이에 컨트롤러로부터 받은 변수명을 적어주는 방식으로 표현하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
<html>
<head> 템플릿 페이지입니다. </head>
<body>
안녕하세요. 템플릿 바디입니다. <br>
render_template를 이용한 뷰 - 컨트롤 분리입니다. <br>
변수 선언은 아래와 같이 가능합니다. <br>
변수1 : <br>
변수2 :
<body>
</html>
CSS 사용하기
뷰단에서는 미리 정의된 스타일 내용을 담고 있는 CSS파일을 불러와 사용이 가능하다.
뷰단에서 link href
태그를 이용해 사용하는 방법을 아래에 설명한다.
CSS 파일을 사용하지 않고 직접 코딩
1
2
3
4
5
6
7
8
9
10
<html>
<head>
<style>
body{background-color: #dddddd;}
</style>
</head>
<body>
밝은 회색 스타일. 뷰에서 직접 스타일을 지정했습니다.
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route('/')
def home_page():
page = render_template('flask_index.html')
return page
app.run(host = 'localhost', port = 5002)
CSS 파일을 사용해 코딩
1
2
3
4
5
6
7
8
9
<html>
<head>
<link rel='stylesheet'
href=''>
</head>
<body>
하늘색 스타일. CSS를 통해 스타일을 지정했습니다.
</body>
</html>
1
body{background-color: #01dddd;}
1
2
3
4
5
6
7
8
9
10
11
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route('/')
def home_page():
page = render_template('flask_index.html')
return page
app.run(host = 'localhost', port = 5002)
마치면서
플라스크는 작성법이 간단하나, 확연한 MVC 분리에는 적합하지 않으며, 이에 따라 페이지가 많아지거나 그 구조가 복잡해질수록 체계적인 관리가 어려워진다.
이에 더불어 커버할 수 있는 동시접속자수가 자바 서버에 비해 턱없이 적은 점과, 보안 기능이 제공되지 않는다는 점에 있어서 불특정 다수
를 대상으로 하는 웹 제작에는 어울리지 않는다.
하지만 반대로, 보안 걱정이 필요 없는 폐쇄망 내에서 관리자 몇 명만을 대상으로 하는 서비스라면 간단하게 플라스크로 제작하는 것도 괜찮을 수 있다. 이 때는 오히려 다양한 기능이 필요 없을 수도 있으므로, 간단히 제작하는 플라스크가 어울릴 수 있다.
즉, 어떤 프레임워크를 이용하는지는 그 상황에 따라 달라질 수 있으며, 어떠한 게 더 낫다고 단정짓기는 힘들다.
하지만 앞서 말한 듯, 대외적인 서비스에서는 자바가 필수적이므로, 자바 공부는 꼭 필요한 것이라는 생각과 함께 이번 글을 마친다.
reference
- 위키피디아:플라스크
- chatgpt : which sites have been built using Flask, a python framework?