[Flask] ๊ธฐ์ด ๋ฐ ์น ์๋ฒ ๊ฐ๋ฐ ๊ฐ๋ ์ดํด
๐ ์๋ ํ์ธ์?
์ด๋ฒ ๊ณต๋ถ๋ ํ์ฌ ์ ๋ฌด๋ฅผ ์ํด ๊ณต๋ถ๋ฅผ ํด๋ณด๊ณ ์ ํ๋ ๋ถ๋ถ ์ ๋๋ค.
์ด๋ฒ์ ์ฃผ๋ํ๋์ ํ์ฌ์์ ์ฌ์ฉ์ค์ธ ๊ด๋ฆฌ์ Page๊ฐ ๊ธฐ์กด์๋ Python Flask ๊ธฐ๋ฐ์ Back End ๋ฐ Jinja๋ก ๊ตฌํ๋ Front End๋ฅผ Nuxt.js์ Spring Boot์ผ๋ก Renewal ํ๋ Project๋ฅผ ๋งก๊ฒ ๋์์ด์!
๊ทธ๋์ Python Flask๋ฅผ ์ดํดํ๊ธฐ ์ํด ๊ณต๋ถ๋ฅผ ํ ํ์์ฑ์ ๋๋ผ๊ณ , ๊ณต๋ถ๋ฅผ ํ์์ต๋๋ค.
์ฃผ๋ํ๋์ JAVA Spring Boot๋ก ๊ณต๋ถ๋ฅผ ํด ์๊ธฐ ๋๋ฌธ์ ๊ธ๋ค์ด ๋ชจ๋ Java Spring Boot๋ก ๋น๋์ด ํํํ๋ ๊ณณ์ด ๋ง์ต๋๋ค.
์ด ์ ์ฐธ๊ณ ๋ถํ ๋๋ฆฌ๊ฒ ์ต๋๋ค.
๐ Flask ์์ํ๊ธฐ
๐ก ์ฐธ๊ณ ์ฌํญ
ํจ์ ์์ def๊ฐ ๋ถ์ ๊ฒ์ ํธ์ถ์ ์๋ฏธํ๋ ๊ฒ์ด ์๋๋ผ ์ ์๋ง ํ๋ค๋ ๊ฒ์ ์๋ฏธ.
๐ฝ ๊ฐ์
Flask๋ Python ๊ธฐ๋ฐ Micro Frame๋ฅผ ํ๋ฐฉํ๋ฉด์ ๋ํ๋ฌ๋ค๊ณ ํฉ๋๋ค.
์ฆ, ๋งค์ฐ ๊ฐ๋ณ๊ณ ์ฌํํ Web Framwork์์.
์ด๋ฌํ ์ฒ ํ ๋๋ฌธ์ ์ต์ด ์ค์น ํ์ ๋ค์ด์๋ ๊ฒ์ด ๋ง์ด ์๋ ๊ฒ์ด ํน์ง์ด์์.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํ์ํ ๊ฒ๋ค์ ์ถ๊ฐํด ๋๊ฐ๋ฉด์ ๊ฐ๋ฐ์ ์งํํด์ผ ํฉ๋๋ค.
์ด๋ฌํ ์ด์ ๋ก ์์ ๋๊ฐ ๋๋ค๋ ํน์ง์ ๊ฐ์ง๊ณ ์์ด์.
๊ฐ๋ฐ์๊ฐ ์ํ๋ ๋ถ๋ฌธ์ ๋ํ Library ๋ฑ์ ๋ถ์ฌ์ ์ฌ์ฉํ ์ ์์ง์.
Django ์ญ์ Python ๊ธฐ๋ฐ Web Framwork์ธ๋ฐ, Django๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค์ ๋ณด์ ํ๊ณ ์์ง๋ง, ์์ฒด ์ค๊ณํ ๊ฐ๋ฐ ํจํด์์ ํฌ๊ฒ ๋ฒ์ด๋ ์๊ฐ ์๋ค๋ ํน์ง์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
ํ๋ ์๋ฅผ ๋ค๋ฉด Flask์๋ DB ORM ๊ตฌ์กฐ๊ฐ ๋ฐ๋ก ์๋ค๊ณ ํฉ๋๋ค. Django์ ๋ํ ORM๋ Flask์๋ ์กด์ฌํ์ง ์์์.
ํ์ง๋ง, ๊ฐ๋ฐ์๊ฐ ์ํ๋ค๋ฉด ORM Package๋ฅผ ์ ํํด์ ์ฌ์ฉํ ์ ์๊ณ , ๋ณดํต SQL Alchemy๋ฅผ ์ด์ฉํฉ๋๋ค.
Flask ๋ด๋ถ๋ฅผ ํฌ๊ฒ ๋ณด๊ฒ ๋๋ฉด WSGI์ฉ Library์ธ Werkzeug์ด๋ HTML์ Data Rendering Engieen Jinja2 temlplat์ผ๋ก ๊ตฌ์ฑ์ด ๋์ด ์์ด์.
๐ฆ ์ค์นํ๊ธฐ
์ต์ด Flask ์ค์น๋ฅผ ํด๋ณด๋๋ก ํ ๊ฒ์.
๋ช ๋ น์ด
pip install flask
# ๋๋
pip3 install flask
๋จผ์ ์์ ๋ช
๋ น์ด๋ก flask๋ฅผ ์ค์นํ๋ ค๋ฉด pip๊ฐ ์ค์น๋์ด ์์ด์ผ ํด์. ์ฃผ๋ํ๋์ Pip3๋ก ์งํํ ๊ฒ์ด๊ณ , ์์ ๊ฐ์ด ์ค์น ๋์ด ์๋์ง ํ์ธํ์์ต๋๋ค.
์ด๋ ๊ฒ ์ค์น๋ฅผ ํ๊ฒ ๋๋ฉด path๊ฐ ์๋์ผ๋ก ์กํ๋ค๊ณ ํฉ๋๋ค.
๐ฆ Package Tree ๊ตฌ์ฑ
Flask๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ตฌ์ฑํ๊ณ ์๋ Package ๊ตฌ์ฑ์ด ์๋ค๊ณ ํด์.
์์ flaskapp ์ด๋ผ๋ package๊ฐ Web App์ด ๋๋ ๋ถ๋ถ์ด์์. JAVA Spring์ ์๊ฐํ๋ฉด src Package๊ฐ ๋ ๊ฑฐ ๊ฐ์์!
์ฐธ๊ณ ๋ก Flask๋ ๊ธฐ๋ณธ Port๋ฅผ 5000์ผ๋ก ์ฌ์ฉํ๊ณ ์์ด์!
__init__.py๋ python์ ์์ฑ์๋ฅผ ๋ํ๋ด์.
์ด ์น๊ตฌ๋ Python์ Web Application์ ์์ฑํ๋ ๊ฒ์ ๋ด๋นํ๊ณ ์์ด์.
์ฆ, flask Web Application Module์ ์์ ์ง์ ์ธ ๊ฒ์ด์์.
๋งจ ์๋์ start_helloflask.py๋ __init__.py๋ฅผ ๊ตฌ๋ํ๋ File์ด์์.
์ต์ด ์ฃผ๋ํ๋์ ์์ ๊ฐ์ด Package์ start_helloflask.py๋ฅผ ๋ง๋ค์ด ์ฃผ์์ด์.
๊ทธ๋ฐ ๋ค์ ์์ ๊ฐ์ด static๊ณผ templates Package๋ฅผ ๋ง๋ค์ด ์ฃผ์์ต๋๋ค.
๊ทธ๋ฐ ๋ค Root Package ๋ฐ์ __init__.py๋ฅผ ๋ง๋ค์ด ์ฃผ์์ด์.
๋จผ์ ์ฒซ๋ฒ์งธ ์ค์ flask๋ฅผ Flask๋ผ๋ ๊ฐ์ฒด๋ก ๋ฐ์ ์ค๋๋ค.
๊ทธ๋ฐ ๋ค 5๋ฒ์งธ ์ค์ Flask()๋ฅผ ์์ฑํ๊ณ , ๋งค๊ฐ ๋ณ์๋ก ์ด๋ฆ์ ์ ํด์ฃผ๊ฒ ๋์. ๊ทธ๋ฌ๋ฉด __name__์ด Main์ด ๋๊ฒ ๋๋ต๋๋ค.
7๋ฒ์งธ ์ค์ Java Spring์์๋ ๋ณด์๋ฏ Controller ์ญํ ์ ํ๋ @app.route()์์. flask์์๋ Decoration์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค๊ณ ํฉ๋๋ค.
/ URI์ ์์ฒญ์ด ๋ค์ด์ค๋ฉด helloword()๊ฐ ๋์ํ๊ฒ ๋๊ณ , ๋ฐํ๊ฐ์ผ๋ก 9๋ฒ์งธ ๋ฌธ์์ด์ด ๋ฐํ๋ ๊ฒ์ด์์.
์ฐธ๊ณ ํด์ผ ํ ์ฌํญ์ Controller ๋ฐํ Type์ ๋ฌธ์์ด์ด์ด์ผ ํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ ์์ ๊ฐ์ด ์์ฑ์ ํ๋๋ฐ, ์ฒซ๋ฒ์งธ ์ค์ Module Name ์ฆ, Project Root Package Name์์ __init__.py์์ ์์ฑํ๋ app์ด๋ผ๋ ๋ถ๋ถ์ ๋ฐ์ import ํ๊ฒ ๋ค๊ณ ํ ๊ฒ์ด์์. ์๋๋ helloflask.__init__.py๋ฅผ ๋ค ์จ์ค์ผ ํ์ง๋ง, ์์ฑ์๋ ์๋ต์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ด ์์ฑํ ์ ์์ด์.
์ด๋ฅผ ํตํด ์ธ๋ฒ์งธ ์ค์ ํด๋น Module์ ๋์ ์ํค๋๋ฐ, port ๋ฒํธ๋ฅผ 8080์ผ๋ก ๋ณ๊ฒฝ์ ํด ์ฃผ์๊ณ , debugging Mode๋ก ๋์์ ์์ผ์ฃผ์์ด์. debugging Mode๋ก ๋์์ ์ํค๊ฒ ๋๋ฉด Code์ ์์ ์ด ์ผ์ด๋ฌ์ ๋, Server๋ฅผ ์ฃฝ์๋ค๊ฐ ๋ค์ ์ฌ๋ฆฌ์ง ์์๋ ๋ฐ์์ด ๋๋ต๋๋ค.
์ฐธ๊ณ ๋ก Debugging Mode๋ ๊ฐ๋ฐ ๋น์์๋ง ์ฌ์ฉํด์ผ ํ๊ณ , ์ด์ Server๋ก ์ฌ๋ผ๊ฐ ๋ ์์ ์ค์ผ ํ๋ Option์ด์์!
๊ทธ๋ฆฌ๊ณ , host Option์ 0.0.0.0์ผ๋ก ์ค ๊ฒ์ localhost๋ผ๊ณ ์๊ฐํ๋ฉด ๋์!
์ฐธ๊ณ ๋ก ์์ 8๋ฒ์งธ ์ค์ฒ๋ผ Server Port ๋ฐ Domain ๋ช ์ ๋ฐ๊ฟ์ค์๋ ์์ด์.
์ด์ ์ด๊ธฐ ์ค๋น๋ ๋ชจ๋ ๋๋ฌ์ด์! ํ๋ฒ ๊ตฌ๋ํด ๋ณผ๊ฒ์.
์ฃผ๋ํ๋์ IDE๋ฅผ Pycham์ ์ฌ์ฉํ๊ณ ์๊ณ , ์๋์ ๊ฐ์ด Debug Mode๋ก ๊ตฌ๋์ ์์ผ ์ค ๊ฑฐ์์.
๋ง์ฝ FileNotFoundError๊ฐ ๋๋ค๊ณ ํ๋ฉด ๊ตฌ๋ ์์ผ์ผ ํ๋ File์ ์ฐพ์ง ๋ชปํด์ ๋ฐ์ํ๋ ๋ฌธ์ ์์.
์์ ๊ฐ์ด ๊ตฌ์ฑ ํธ์ง์ ๋ค์ด๊ฐ์ ์๋์ ๊ฐ์ด ์ค์ ์ ํด์ฃผ์ด์ผ ํด์.
์ฐ๋ฆฌ๊ฐ ์ฌ๊ธฐ์ ์ฃผ๋ชฉํด์ผ ํ ๊ณณ์ ์คํฌ๋ฆฝํธ ๊ฒฝ๋ก(Script Path)์์. ์ด ๊ณณ์ Server ๋์์ ์์ผ์ค Python File์ ๋ช
์ํด ์ค์ผํด์.
์์ ๊ฐ์ด ๊ตฌ๋์ด ์๋ฃ ๋์์ด์. ์์ (lazy loading)์ด๋ผ๊ณ ๋์ ์๋๋ฐ, ์ง์ฐ ๋ก๋ฉ ์ฆ, ์ฒ์ ๊ตฌ๋ ํ ๋ ๋ถํฐ ๋ชจ๋ ๊ธฐ๋ฅ์ ๋ค ๊ฐ์ง๊ณ ๊ตฌ๋ ํ์ง ์๊ฒ ๋ค๋ ์๋ฏธ์์. ํ์ํ ๋ ๊ตฌ๋์ ์ํค๊ฒ ๋ค๋ ์๋ฏธ์ด์ฃ .
ํ์ฌ ๊ตฌ๋์ด Envirnment: production ์ฆ, ์ด์ ํ๊ฒฝ์ ๋ง๊ฒ ๊ตฌ๋์ด ๋์์ด์. ๊ทธ ์ด์ ๋ Default Value์ด๊ธฐ ๋๋ฌธ์ด์์.
๊ทธ๋์ ๊ฒฝ๊ณ ๋ฌธ๊ตฌ๋ฅผ ๋ณด๋ฉด ์ด ํ๊ฒฝ์์ ๊ฐ๋ฐํ์ง ๋ง์ธ์! ๋ผ๊ณ ํ๋ ๊ฒ์ ๋ณผ ์ ์์ด์.
๋ธ๋ผ์ฐ์ ๋ก ์ ์์ ํ๊ฒ ๋๋ฉด ์๋์ ๊ฐ์ด ์ ์ ์์ด ๋ฉ๋๋ค.
Java Spring ๋ณด๋ค ๊ตฌ๋ ์๋๊ฐ ๋นจ๋๋๋ฐ, Python์ด Interpreter Language ์ด๊ธฐ ๋๋ฌธ์ด์์.
๐ฝ Response Object
๐ฆ Global Object : g
Flask๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ๋ณธ๊ฒฉ์ ์ผ๋ก ๊ณต๋ถ ํด ๋ณผ๊ฒ์.
Flask์๋ g ๋ผ๋ ๊ฐ์ฒด๊ฐ ์๋ ๊ฒ์ด์์. ์ฐธ ์ธ๊ตญ์ธ๋ค ์ด๋ฆ ์ฝ๊ฒ ์ง๋ ๊ฑฐ ๊ฐ์์.
g(Application Context)๋ผ๋ ๊ฐ์ฒด๋ Global ์ฆ, ์ ์ญ ๋ณ์์์.
๐ก ์ฐธ๊ณ ์ฌํญ
Application Context๋?
Context๋ ์์ญ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋๋ฐ, Application Context๋ Application์ด ์คํ๋๋ ์์ญ์ ๋ปํ๋ค.
์๋ฅผ ๋ค์ด ์ด๋ค Web Application์ด ๊ตฌ๋๋ ๋ค ๋ชจ๋ ์์ฒญ ์ฆ, ๋ถํน์ ๋ค์๊ฐ ๊ณต์ ํ๋ ์์ญ์ Application Context๋ผ๊ณ ํ๋ค.
Session Context๋?
Session์ ํ ์ด์ฉ์๊ฐ ๋ถ๊ฒ ๋๋ฉด Session์ ์ด์ด์ฃผ๋ ๊ฐ๋ ์ธ๋ฐ, Web Application์์ ๋งํ๋ Session์ ํ๋์ User๋ฅผ ๋ปํ๋ค. ํ User๊ฐ ๊ฐ์ ์์ฒญ์ 100๋ฒ ๋ณด๋ด๋ ๊ฐ์ Session์ด๋ค.
๊ทธ๋ฐ๋ฐ, ๋ธ๋ผ์ฐ์ ๋ฅผ ๊ฐ๊ธฐ ๋ค๋ฅธ ์ข ๋ฅ๋ก ์ด๊ณ , ๊ฐ์ ์์ฒญ์ ๋ณด๋ด๊ฒ ๋๋ฉด ๋ค๋ฅธ Session์ด๋ค.
g๋ผ๋ ์น๊ตฌ๋ Application ์์ญ์ธ ์ ์ ์์ผ๋ฉด ์๋์!
์์ ๊ฐ์ด g๋ฅผ import๋ฅผ ํด์ฃผ์๊ณ , 9๋ฒ์งธ ์ค์ @app.before_request Decoration์ ์ผ๋๋ฐ, ์ด๋ ์ด๋ค ์์ฒญ์ด ์ด๋์ง ๋จผ์ ๊ฑฐ์น๋ ๊ณณ์ด์์.
12๋ฒ์งธ ์ค์๋ ํ์ ๊ฐ์
์, ์ด์ฉ์ ์ ๋ฑ์ ๋ํ ๋ด์ฉ์ ๋ฃ์ผ๋ฉด ์ข์ ๊ฑฐ ๊ฐ์์. ์๋ํ๋ฉด ์ ์ญ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ณณ์ด๊ณ , Application Context์ด๊ธฐ ๋๋ฌธ์ด์์.
์๋ฅผ ๋ค์ด ์ ๊ณณ์ ์ด์ฉ์๊ฐ ์ ์ํ ๋ ๋ง๋ค ๋ํ๊ธฐ ์ฐ์ฐ์ ํด์ฃผ๋ฉด ๊ณ์ ์ฆ๊ฐํ๊ฒ ์ง์?
16๋ฒ์งธ ์ค getattr() ๋๋ฒ์งธ ์ธ์์ 12๋ฒ์งธ ์ค g.str ๊ฐ์ด ์ค๊ฒ ๋์. ์ธ๋ฒ์ฌ ์ธ์๋ Default ๊ฐ์ด๋๋๋ค.
g.str์ ๊ฐ์ด ์๋ค๋ฉด 111์ ์ถ๋ ฅํ ๊ฒ์ด์์.
์์ ๊ฐ์ด ์ถ๋ ฅ์ด ๋๋ค์!
์ด๋ฒ์๋ Response์ ๋ํด ๊ณต๋ถ ํด ๋ณผ๊ฒ์.
8 ~ 11๋ฒ์งธ ์ค์ ๋ณด๋ฉด /res๋ผ๋ URI๋ก ์์ฒญ์ด ์์ ๋, Response ๊ฐ์ฒด์ Custom Response๋ผ๋ ๋ฌธ์์ด์ ๋ด๊ณ , HTTP Status Code 200๊ณผ ํจ๊ป JSON ๊ฐ์ฒด๋ฅผ custom_res ๋ณ์์ ๋ฃ์ด์ฃผ๊ณ , make_response()์ ํด๋น ๋ณ์๋ฅผ ๋ฃ์ด ๋ฐํํด ์ฃผ์์ด์.
์์ ๊ฐ์ด ๋ฌธ์์ด์ด ๋ฐํ๋ ๊ฒ์ ํ์ธํ ์ ์์ด์.
๊ฐ๋ฐ์ ๋๊ตฌ์์ Network Tab์ผ๋ก ํ์ธํด ๋ณด๋ HTTP Status Code๊ฐ 200์ผ๋ก ์๋ต๋ ๊ฒ์ ๋ณผ ์ ์์ด์.
๊ทธ๋ฆฌ๊ณ , ์๋ต ํค๋ ๋ถ์ test: ttt๊ฐ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ด์.
HTTP Status Code ๋ถ๋ถ์ 201๋ก ๋ณ๊ฒฝํ๊ณ , ๋ค์ ํ๋ฒ ์ ์ํด ๋ณผ๊ฒ์.
HTTP Status Code๊ฐ 201๋ก ์๋ต๋ ๊ฒ์ ํ์ธํ ์ ์์ด์.
๐ฆ WSGI(Web Server Gateway Interface)
์ด๋ฒ์๋ WSGI์ ๋ํด์ ๊ณต๋ถ ํด ๋ณผ๊ฒ์.
WSGI๋ ์น ์๋ฒ ์ํํธ์จ์ด์ Python์ผ๋ก ์์ฑ๋ Web Application Program ๊ฐ ํ์ค Interface์
๋๋ค.
ํ๋กํ ์ฝ ๊ฐ๋
์ผ๋ก๋ ์ดํดํ ์ ์๊ณ , WSGI๋ Application ์๋จ์ผ๋ก ๋๋์ด์ ธ ์๋๋ฐ, WSGI Request๋ฅผ ์ฒ๋ฆฌํ๋ ค๋ฉด Server์์ ํ๊ฒฝ์ ๋ณด์ Call Back ํจ์๋ฅผ Application์ ์ ๊ณตํด์ผ ํฉ๋๋ค.
Application์ ๊ทธ Reqeust๋ฅผ ์ฒ๋ฆฌํ๊ณ , Call Back ํจ์๋ฅผ ํตํด Server์ Response ํฉ๋๋ค.
๐ก ์ฐธ๊ณ ์ฌํญ
๋ฐฉ์
Request(์์ฒญ) -> Web Server -> WSGI Server(Middleware) -> WSGI ์ง์ Web Application(Django, flask ๋ฑ)
์ด๋ฒ์๋ 8๋ฒ์งธ ์ค ๋ถํฐ 17๋ฒ์งธ ์ค์ ์ฃผ๋ชฉํ ๊ฒ์.
๋จผ์ Request URI๊ฐ /test/wsgi๋ผ๋ฉด wsgi_test()๊ฐ ํธ์ถ๋ ๊ฒ์ด์์. ๊ทธ๋ฆฌ๊ณ , application()์ด ํธ์ถ ๋๋๋ฐ, ๊ทธ ๋, environ์ Environment (ํ๊ฒฝ)์ ์ฝ์์ธ ๊ฒ๊ณผ start_response๋ผ๋ ๋งค๊ฐ ๋ณ์๋ฅผ ๋ฐ์ ํธ์ถ์ ํด์.
Response Body์๋ 11๋ฒ์งธ ์ค์ฒ๋ผ ๋ฌธ์์ด์ด ๋์ค๊ณ %s์์ % ๋ค์ ์๋ environ['REQUEST_MTTHOD']๊ฐ Mapping๋์ ์ถ๋ ฅ๋ ๊ฑฐ์์.
122๋ฒ์งธ ์ค์ Response header์ Type์ Text๋ก ํด์ฃผ๊ณ , ๊ธธ์ด๋ฅผ ๋ฐํํ๋๋ฐ, Header๋ Key : Value ์์ผ๋ก Value๋ ๋ฌธ์์ด์ด์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ด ํด์ค ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค start_response Function์ด ํธ์ถ ๋๋ฉด 200 OK์ ํจ๊ป headers ๋ณ์๊ฐ ๋งค๊ฐ ๋ณ์๋ก ๋ค์ด๊ฐ์ ๋์์ ํ๊ฒ ๋ ๊ฑฐ์์.
15๋ฒ์งธ ์ค์ application()์ body๋ฅผ ๋ฐํํ๊ณ , 17๋ฒ์งธ ์ค์ make_response์ application()์ ํธ์ถํ๊ณ , ํด๋น ๊ฐ์ ๋ฐํํ๋ฉด์ ์ข
๋ฃ ๋์.
์ถ๋ ฅ๋ ๊ฒ์ ๋ณด๋ body ๋ณ์ ๊ฐ์ด ์ถ๋ ฅ์ด ๋๊ณ ์๊ณ , ์๋ต ํค๋ ๋ถ์ ๋ณด๋ฉด Context Type, Context Length๊ฐ ์ ์ฐํ๋ ๊ฒ์ ๋ณผ ์ ์์ด์.
๊ทธ๋ฆฌ๊ณ , HTTP Status Code๋ 200 OK๊ฐ ์ฐํ๋ค์!
๐ฝ Request Event Handler
๐ฆ @app.before
โ before_first_request
- ์ด์ฉ์๊ฐ Request(์์ฒญ)์ ๋ณด๋ด๊ฒ ๋๋ฉด ์ฒซ๋ฒ์งธ ์์ฒญ์ ๋ณด๋์ ๋, ํด๋น Decoration Function์ด ๋์.
โ before_request
- ์ด์ฉ์๊ฐ ์ง์์ ์ผ๋ก ์์ฒญ์ ๋ณด๋ผ ๋๋ง๋ค ๋ฌด์กฐ๊ฑด ํด๋น Decoration Function ๋์. (Web Filter ์ญํ )
โ after_request
- ํน์ ์์ฒญ์ ๋ํ ์๋ต์ด ๋๊ฐ๊ธฐ ์ง์ ํด๋น Decoration Function ๋์.
- DB์ ์ฐ๊ฒฐ์ ์ํํ ๋ค DB ์ฐ๊ฒฐ์ ํด์ค์ผ ํ๋๋ฐ, ์ด๋ด ๋ ๋ง์ด ์ฌ์ฉ.
โ teardown_request
- Destroy ์ฆ, Response(์๋ต)๊น์ง ๋ค ๋ ๋ค ํด๋น Decoration Function ๋์.
- ๋งค๊ฐ ๋ณ์๋ก exception์ ๋ฐ๋๋ค. ๊ธฐ๋ฅ ๋์ ์ด ํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด Log๋ฅผ ๋จ๊ธฐ๋ ๋ฑ์ ์์
์ ์ํด ์ฌ์ฉ.
โ teardown_appcontext
- Application Context๋ฅผ AppContext๋ผ๊ณ ๋ ๋ถ๋ฅด๋๋ฐ, Application Context๊ฐ Destroy(์ข
๋ฃ) ๋์์ ๋, ํด๋น Decoration Function ๋์.
- ๋งค๊ฐ ๋ณ์๋ก exception์ ๋ฐ๋๋ค.
๐ฝ Routing
@app.route('/test', methods=[ 'POST', 'PUT' ])
def ...
์์ฒญ URI๊ฐ /test์ด๋ฉด์ HTTP Request Method๊ฐ POST ํน์ PUT์ด๋ฉด ํด๋น Decoration Function ๋์ ํฉ๋๋ค.
@app.route('/test/<tid>/')
def test3(tid) :
print("tid is", tid)
HTTP Reqeust Method๋ฅผ Get์ผ๋ก ํ๋ฉด์ URI Parameter(/test/์ซ์ ๋ฑ)๋ก ๊ฐ์ ๋ณด๋ด๊ฒ ๋๋ฉด ํด๋น Decoration Function์ด ๋์ํ๋ฉด์ ๋งค๊ฐ ๋ณ์๋ก <> ์์ ๊ฐ์ ์ ๋ฌ ํฉ๋๋ค.
@app.route('/test', defaults= { 'page' : 'index' })
@app.route('/test/<page>')
def function(page) :
์์ ๊ฐ์ด URI Parameter๋ก page๋ผ๋ ๊ฐ์ ๋ฐ์๊ฑด๋ฐ, ๋ง์ฝ page ๊ฐ์ด ๋ค์ด์ค์ง ์์ผ๋ฉด Default ๊ฐ์ธ index๋ฅผ @app.route('/text/<page>')๊ฐ ๋์ํ๋๋ก ํฉ๋๋ค.
@app.route('/test', host='abc.com')
์ด์ฉ์๊ฐ URL์ abc.com์ผ๋ก ์์ฒญ์ ๋ณด๋ด๋ฉด ์์ Decoration์ด ๋์ํ์ฌ ์์ฒญ์ ์ฒ๋ฆฌํ๊ฒ ๋ฉ๋๋ค.
์ฆ, Domain ๋ณ๋ก ์ฒ๋ฆฌ๋ฅผ ๋ถ์ฐํ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค.
@app.route('/test', redirect_to='/new_test')
์ด์ฉ์๊ฐ URI๋ก /test๋ฅผ ์์ฒญํ๊ฒ ๋๋ฉด /new_test๋ก ์์ฒญ์ ์ ๋ฌํฉ๋๋ค.
์ฐธ๊ณ ๋ก Foward๋ ์ฃผ์๋ ๋ฐ๋์ง ์๊ณ , ์์ฒญ์ด ์ด๋ํ๋ ๊ฒ์ด์์.
@app.route("/", subdomain="blog")
def helloword():
return "Hello"
subdomain์ด๋ URL์ Prifix๋ฅผ ๋งํ๋๋ฐ, ์๋ฅผ ๋ค์ด blog.naver.com๊ณผ cafe.naver.com์ด ์์ ๋, subdomain์ blog์ cafe๊ฐ ๋ฉ๋๋ค. ๊ฒฐ๊ตญ subdomain์ด blog๋ก ์์ฒญ์ด ๋ค์ด์ค๋ฉด ํด๋น Decoration Function์ด ๋์ํ๊ฒ ๋ค์.
๐ฝ Request Parameter
# MultiDict Type
...get('<param name>', <default-value>, <type>)
methods: get, getlist, clear, etc
๋จผ์ Request Parameter๋ ๋์
๋๋ฆฌ ํ์
์ด์์.
Multi๊ฐ ๋ถ์ ์ด์ ๋ ๋ค์ํ ์ฉ๋์ ๋์
๋๋ฆฌ๋ฅผ ์ด๋ค๋ ๋ป์ผ๋ก ๋์
๋๋ฆฌ๋ฅผ ์์๋ฐ์ ์น๊ตฌ์์.
์ต์ด ์ฒซ๋ฒ์งธ ์ค์ request๋ฅผ Import ํด ์ค ๋ค ์์ฒญ URI๊ฐ /req์ผ ๋, ๋์ํ๋ Function์ ๊ตฌํํ์์ด์.
์ด๊ฒ์ Query String์ ์ด์ฉํ๋ ๊ฒ์ธ๋ฐ, ํ๋ฒ ๋ธ๋ผ์ฐ์ ๋ก ์คํํด ๋ณผ๊ฒ์.
์๋ฅผ ๋ค์ด ์ด๋ค ์ด์ฉ์๊ฐ xxx.com/req/q=aaa ๋ผ๊ณ URL์ ์
๋ ฅํ์ฌ ์์ฒญ์ด ๋ค์ด์ค๊ฒ ๋๋ฉด request.args.get('q')๋ URI์ q ๊ฐ ์ฆ, aaa๋ฅผ ๋ฐ๋ ๊ธฐ๋ฅ์ ์ํ ํฉ๋๋ค.
์ด๋ฐ์์ผ๋ก get Method๋ฅผ ํ์ฉํ ๋ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด์์.
# POST
request.form.get('p', 123)
post Method๋ฅผ ํตํด ์์ฒญ์ ๋ฐ์ผ๋ ค๊ณ ํ ๋, ์์ฒญ Body๋ก ๋ฐ์ ๊ฒ์ ๋งค๊ฐ ๋ณ์ ์ฒซ๋ฒ์งธ์ ์ง์ ํด ์ค ์ ์์ด์.
๋งค๊ฐ ๋ณ์ ๋๋ฒ์งธ ์๋ฆฌ๋ Default ๊ฐ์ผ๋ก ์ฒซ๋ฒ์งธ ๊ฐ์ด ์์ ๋ ๋์ ํ ๊ฒ์ ์จ์ค ์ ์๋ต๋๋ค.
์ด๋ฒ์๋ getlist()์ ๋ํด ๊ณต๋ถํด ๋ณผ๊ฒ์. ์ด๊ฒ์ ์์ฒญ ๊ฐ์ด ์ฌ๋ฌ๊ฐ ์ผ ๋ ์ฌ์ฉํ๋ฉด ์ข์ ๊ฒ์ด์์.
์ฆ, ์ด์ฉ์ํํ
์ฌ๋ฌ๊ฐ๋ฅผ ์ ํํ ์ ์๊ฒ ํ๊ณ , ์ด์ฉ์๊ฐ ์ฌ๋ฌ๊ฐ๋ฅผ ์ ํํด์ ์์ฒญ์ ๋ณด๋ผ ๋ ์ฐ๋ฉด ์ข์ ๊ฒ์ด์์.
์์ ๊ฐ์ด List ํํ๋ก ๊ฐ์ ์ฒ๋ฆฌํ ์ ์์ด์.
์ฃผ์ํ ์ ์ ์์ ๊ฒ์ ์ฌ์ฉํ๋ ค๋ฉด Client๋ ๋์ผํ๊ฒ ์ฒ๋ฆฌ๋ฅผ ํด์ค์ผ ํฉ๋๋ค.
๐ฝ Request.environ
return ('REQUEST_METHOD: %(REQUEST_METHOD) s <br>'
'SCRIPT_NAME: %(SCRIPT_NAME) s <br>'
'PATH_INFO: %(PATH_INFO) s <br>'
'QUERY_STRING: %(QUERY_STRING) s <br>'
'SERVER_NAME: %(SERVER_NAME) s <br>'
'SERVER_PORT: %(SERVER_PORT) s <br>'
'SERVER_PROTOCOL: %(SERVER_PROTOCOL) s <br>'
'wsgi.version: %(wsgi.version) s <br>'
'wsgi.url_scheme: %(wsgi.url_scheme) s <br>'
'wsgi.input: %(wsgi.input) s <br>'
'wsgi.errors: %(wsgi.errors) s <br>'
'wsgi.multithread: %(wsgi.multithread) s <br>'
'wsgi.multiprocess: %(wsgi.multiprocess) s <br>'
'wsgi.run_once: %(wsgi.run_once) s') % request.environ
Request ๊ฐ์ฒด๋ Flask๊ฐ ๋ง๋ค์ด์.
์ฆ, ์์ฒญ์ด ๋ค์ด์์ ๋, Flask๊ฐ Request ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ต๋๋ค.
Flask๊ฐ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋, ํ๊ฒฝ ๋ณ์ ๊ฐ ์ฆ, ์ Code ๋ด์ฉ์ ํ๊ฒฝ ๋ณ์ ๊ฐ์ ๋ค Setting ํด ์ฃผ๋ ๊ฑฐ์์.
ํ๋ฒ ํ๊ฒฝ ๋ณ์ ๊ฐ์ ์ถ๋ ฅํด ๋ณผ๊ฒ์. ์์ฒญ ํ๊ฒฝ๊ฐ์ด %์ผ๋ก ์ธํด ๊ฐ๊ฐ์ ๊ฐ์ ์ ์น๋ ๊ฒ์ด์์.
๐ฝ Request
request.is_xhr
xhr์ AJAX๋ฅผ ์ฌ์ฉํ์ฌ XML HTTP Request๋ฅผ ๋ง๋ค์ด ๋ณด๋ผ ๋ XML HTTP Request๋ฅผ xhr์ด๋ผ๊ณ ๋ถ๋ฌ์.
์์ ๋ด์ฉ์ ์ด๋ค ๋์์ด xhr ํ์์ธ์ง์ ๋ํด ํ์ธํ๊ณ ๋ฐํ Type์ด Boolean์ธ ๊ธฐ๋ฅ์ด์์.
๊ฒฐ๊ตญ AJAX๋ฅผ ์ด์ฉํด์ ๋ถ๋ ๋ค๋ ๊ฒ์ ์ ์ถํ ์ ์์ด์.
ํด๋น ๊ฐ์ด True๋ผ๋ฉด JSON์ ์๋ตํด์ฃผ๊ณ , False๋ผ๋ฉด HTML์ ์๋ตํด ์ฃผ๋ฉด ๋๋ ๊ฒ์ด์์.
์ฐธ๊ณ ๋ก AJAX์ธ์๋ Request Body์ JSON์ ๋ณด๋ผ์๋ ์์ด์.
request.endpoint
์ฌ๊ธฐ์ endpoint๋ URI๋ฅผ ์๋ฏธํด์.
request.get_json()
Client์์ JSON์ผ๋ก ์์ฒญ์ ๋ณด๋ผ ์๋ ์๋๋ฐ, ์์ฒญ์ผ๋ก ๋ค์ด์ค๋ data ๊ฐ ์ฆ, Payload๋ฅผ ํ์ฑํ๊ธฐ ์ํด ์ด์ฉํ๋ ๊ฒ์ด์์.
app.config.update(MAX_CONTENT_LENGTH=1024*1024)
request.max_content_length
์์ ๋ด์ฉ์ Application Context์ ํ๊ฒฝ๋ณ์(config)๋ฅผ ๋ณ๊ฒฝ(update)ํ ๊ฑด๋ฐ, Request Body ๋ด์ฉ ์ต๋ ๊ธธ์ด๋ฅผ 1024*1024 Byte๋ก ํ๊ฒ ๋ค๋ ์๋ฏธ์ธ ๊ฒ์ด์์.
์ฆ, ์ด์ฉ์๊ฐ File์ Uploadํ ๋, 10MB ์ด์ File์ ์ฌ๋ฆฌ์ง ๋ชปํ๊ฒ ํ ๋ ๋ฐ๋ก ๊ทธ ๋! ์ฌ์ฉํ๋ ๊ฒ์ด์์.
๐ฝ Response
๐ฆ Object
from flask import Response
# Response Attributes
# - headers
# - status
# - status_code
# - data
# - mimetype
# ์์ ์ฝ๋
res = Response("Test")
res.headers.add('Program-Name', 'Test Response')
res.set_data("This is Test Program.")
res.set_cookie("UserToken", "A12Bc9")
๋จผ์ res = Response("Test")๋ Response ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๊ฑฐ์์. ๋ง๋ค๋ฉด์ Data๋ฅผ ์ฃผ๋ ๋ถ๋ถ์ด ๋ฐ๋ก ("Test")์ธ ๊ฒ์ด์์.
๊ทธ ๋ค์ ์ค์ Response Header๋ฅผ ๋ง๋ค์ด ๋งค๊ฐ ๋ณ์ ๊ฐ์ ์ ๋ฌํ๋ ๊ฑฐ์์. ์ฆ, Program-Name : Test Response JSON ํํ๋ก ์ ๋ฌ๋ ๊ฒ์ด์์.
๊ทธ ๋ค์ ์ค์ data๋ฅผ This is Test Program. ์ด๋ผ๊ณ ์ ๋ฌ์ ํ๊ฒ ๋ค๋ ๊ฒ์ด์์.
๋ง์ง๋ง์ผ๋ก cookie! cookie๋ฅผ ์๋ตํด ์ฃผ๋ ๋ถ๋ถ์ด์์. ์ด์ฉ์๊ฐ Login์ ํ์ ๋, Token์ด๋, Session ๋ฑ์ ์ค ์ ์์ ๊ฒ์ด์์.
๐ฆ Cookie
Cookie๋ Response ๊ฐ์ฒด ์์ ์ค๋น๊ฐ ๋์ด ์์ด์.
๋ํ, Cookie๋ Class์ธ๋ฐ, ์์ฑ์ Argument๋ก key, value, max_age, expires, domain, path๊ฐ ์ค๋น ๋์ด ์์ด์. Key์ Value๋ JSON์ด๋, ๊ฐ์ฒด ํน์ Map์ ์๊ฐํ๋ฉด ๋๋๋ฐ, ์ด๋ค ์ด๋ฆ(Key)์ผ๋ก ์ด๋ค ๊ฐ(Value)๋ฅผ ๋ฃ๊ฒ ๋ค์์.
# ์์ ์ฝ๋
res = Response("Test")
res.set_cookie("UserToken", "A12Bc9")
# ๋ค๋ฅธ ์์ฒญ (Other Request)
request.cookies.get('UserToken', 'defalut token')
๐ค ์๊ฐํด๋ณด๊ธฐ
1. ์๋ ํํ๋ก ์์ฒญํ์๋, ํด๋น Key๋ก Cookie๋ฅผ ๊ตฝ๋ Code ์์ฑํ๊ธฐ
- http://localhost:8080/write/cookie?key=token&value=abc
/write/cookie URI ์์ฒญ๊ณผ ํจ๊ป Query Sring์ผ๋ก Cookie์ Key Value๊ฐ์ด ์ ๋ฌ๋๋ค๋ฉด 11๋ฒ์งธ ์ค์์ ์์ฒญ์ get()์ ํตํด 'key'๊ฐ์ ๊ฐ์ ธ์ key ๋ณ์์ ๋ฃ๊ณ , value๋ฅผ ๊ฐ์ ธ์ value ๋ณ์์ ๋ฃ์์ด์.
๊ทธ๋ฐ ๋ค์ Response ๊ฐ์ฒด์ SET COKIE ๋ฌธ์์ด๋ฅผ ์ ๋ฌํ๊ณ , ๊ทธ ๋ฐํ๊ฐ์ response ๊ฐ์ฒด์ ๋ฃ์ ๋ค์ cookie๋ฅผ ๋ง๋๋๋ฐ, key ๋ณ์์ ๋ด๊ธด ๊ฐ๊ณผ value ๋ณ์์ ๋ด์ ๊ฐ์ ํตํด ๋ง๋ค์ด์ค์.
๊ทธ๋ฐ ๋ค์ make_response๋ฅผ ํตํด ๋ง๋ค์ด์ง Cookie๋ฅผ ๋ฐํํด ์ฃผ๋ฉด ๋๋ ๊ฒ์ด์์.
2. ์๋์ ๊ฐ์ด ์์ฒญํ์๋, ํด๋น key์ Cookie Value๋ฅผ ์ถ๋ ฅํ๋ Code ์์ฑ
- http://localhost:8080/read/cookie?key=token
์ด๋ฒ์๋ Cookie์ ๋ด๊ธด ๋ด์ฉ์ ์ฝ์ด์ค๋ ๊ฒ์ ํด ๋ณผ๊ฒ์.
/read/cookie URI๋ก ์์ฒญ์ด ์ค๋ฉด rc()๊ฐ ๋์ํ๊ฒ ๋ ๊ฑฐ์์.
์ต์ด ์์ฒญ๊ฐ ์์ ์๋ 'key'๋ผ๋ ์ด๋ฆ์ ๊ฐ์ key๋ก ๋ด์์ค์. ํด๋น Key ์ด๋ฆ์ Query String์ผ๋ก ์ ๋ฌํด์ค์ผ ํด์.
๊ทธ๋ฆฌ๊ณ ๋์ ์์ฒญ cookie์์ key๋ผ๋ ์ด๋ฆ์ ๊ฐ์ value ๋ณ์์ ๋ด์์ค์.
๊ทธ๋ฆฌ๊ณ ๋์ ํด๋น ๋ด์ฉ์ ์ถ๋ ฅํ๊ฒ ๋๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
์ด๋ ๊ฒ ํด๋น ๋ด์ฉ์ ์ฝ์ด์ฌ ์ ์์ด์.
๐ฆ Session
from flask import session
app.secret_key = 'X1243yRH!mMwf'
# OR
app.config.update(
SECRET_KEY = 'X1243yRH!mMwf',
SESSION_COOKIE_NAME = 'junyharang_flask_session',
PERMANENT_SESSION_LIFETIME=timedelta(31)
)
Cookie๋ Client์๊ฒ ์ ๋ฌํด์ฃผ๊ณ , Client๊ฐ ์ถ๊ฐ ์์ฒญ์ ๋ณด๋ผ ๋ ๋ง๋ค ์์ฒญ๊ฐ์ Cookie๊ฐ์ ๋ฃ์ด์ Server์๊ฒ ์ ๋ฌ์ ํด์ค์ผ๋ก, Authentication(์ธ์ฆ) ๋ฐ Authorizaion(์ธ๊ฐ)์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ด์์.
ํ์ง๋ง, Session์ด๋ผ๋ ์น๊ตฌ๋ Server Memory๊ฐ ๊ฐ์ง๊ณ ์๋ Single Ton Object์์.
์ฆ, Memory ํ ๊ตฐ๋ฐ์ ์์นํด ์๋ ๊ฐ์ด์ง์.
Session์ ์์์ ์ด์ผ๊ธฐ ํ๋ Session Context์์.
๋ํ, Session์ Server Memory ์์ ๋ ์๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ Session์ ๋ฌด์์ ๋ด์๋ ํฌ๊ฒ ์๊ด์ ์๋ค๊ณ ํด์.
์๋ํ๋ฉด Client๊ฐ ๊ฐ๋ ๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ์ด์์.
์ต์ด app.secret_key = ~~~ ๋ถ๋ถ์ ๋ณด๋ฉด Application Context ์ฆ, ๋ชจ๋ ์ด์ฉ์๊ฐ ๊ณตํต์ ์ผ๋ก ๋์ผํ Secret Key๋ฅผ ์ฌ์ฉํ๊ฒ ํ๊ธฐ ์ํด ์ ์ธํ๋ ๋ถ๋ถ์ด์์.
์ด ๋ถ๋ถ์ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก๋ app.config.update(SECRET_KEY = ~~~) ๋ก๋ ์ฒ๋ฆฌํ ์ ์์ด์.
SESSION_COOKIE_NAME์ ํด์ฃผ๋ ์ด์ ๋ Session์ ๊ตฝ๊ฒ ๋๋ฉด Client๋ก ๋์ด๊ฐ๊ธฐ ๋๋ฌธ์ธ๋ฐ, Client์ Login ์ ๋ณด๋ฅผ ๋ด๊ธฐ ์ํ Session์ Client๋ ์์์ผ ํ์ง๋ง, Server๋ ์์์ผ ํ๋ ๊ฒ์ด์์.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ Cookie๋ง ์ฐ์ง ์๊ณ , Session์ ๊ฐ์ด ์ฌ์ฉํ๋ ๊ฒ์ด์์.
์ต์ด 1๋ฒ์งธ ์ค์ ๋ณด๋ฉด session์ import ํด ์ฃผ์์ด์.
10 ~ 14๋ฒ์งธ ์ค๊น์ง๊ฐ ๋ฐ๋ก Session์ ๋ง๋๋ ๊ณณ์ด์์.
/setsess URI๋ก ์์ฒญ์ด ๋ค์ด์ค๋ฉด ๋ฌธ์์ด 123X๋ฅผ session์ด๋ผ๋ List ์์ Token ์์์ ๋ฃ์ด๋์์.
์ฐธ๊ณ ๋ก 12๋ฒ์งธ ์ค์ ๋ณด๋ฉด new ์ฐ์ฐ์๊ฐ ์๋๋ฐ, session์ importํ๊ณ ๊ฐ์ ธ๋ค๊ฐ ์ฐ๋ฉด new๋ฅผ ์๋ตํ ์ ์๋ค๊ณ ์๊ฐํ์๋ฉด ๋์. ์ค์ ๋ก session์ ๊ฐ์ฒด ์ฆ, ์ธ์คํด์ค์ด๊ธฐ ๋๋ฌธ์ new ์ฐ์ฐ์๋ฅผ ์จ์ค์ผ ํ์ง๋ง, ์๋ต ๋ ๊ฒ์
๋๋ค.
๊ทธ๋ฆฌ๊ณ , ๋ฌธ์์ด์ ๋ฐํํ์ฌ ์ฃผ์์ด์.
17 ~ 19๋ฒ์งธ๋ Session์ ๊ฐ์ ธ์ค๋ ๊ณณ์ด์์.
๊ฐ๋จํ๊ฒ session List์ get()์ ํตํ์ฌ ๊ฐ์ ๊ฐ์ ธ์ค๋๋ฐ, Token์ด๋ผ๋ ์์์ ๋ด๊ธด ๊ฐ์ ๊ฐ์ ธ์์ ๋ฐ๋ก ๋ฐํํด์ฃผ๋๋ก ํด ์ฃผ์์ด์.
Cookie๋ฅผ ๋ณด๊ฒ ๋๋ฉด junyharang_flask_session์ด๋ผ๋ Key๋ก Session ๊ฐ์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์์ด์.
21๋ฒ์งธ ์ค์์ 26๋ฒ์งธ ์ค๊น์ง๋ Logout์ ์ํ Session ์ญ์ ์ฒ๋ฆฌ ๋ถ์์.
/delsess๋ก URI ์์ฒญ์ด ์ค๋ฉด if๋ฌธ์ ํตํด Session ๊ฐ์ด ์๋์ง ๊ฒ์ฆ์ ํ๊ธฐ ์ํด session List์ ๊ฐ์ ๊ฐ์ ธ์ค๋๋ฐ, get()์ ํธ์ถํ์ฌ Token์ด๋ผ๋ ์์์ ๊ฐ์ ๊ฐ์ ธ์์ ๊ฐ์ด ์๋ค๋ฉด del์ ํตํ์ฌ session List์ Token ์์๋ฅผ ์์ ์ง์ ๋ฒ๋ฆฌ๋ ๊ฒ์ด์์.
Session ์ญ์ ์ฐ์ฐ์ ์ฒ๋ฆฌํด ๋ฒ๋ฆฌ๋ junyharang_flask_session๊ฐ ์ฌ๋ผ์ ธ ๋ฒ๋ ธ์ด์!