Back-End ์ž‘์—…์‹ค/flask

[Flask] ๊ธฐ์ดˆ ๋ฐ ์›น ์„œ๋ฒ„ ๊ฐœ๋ฐœ ๊ฐœ๋… ์ดํ•ด

์ฃผ๋‹ˆ์“ฐ๐Ÿง‘‍๐Ÿ’ป 2022. 6. 8. 23:09
728x90
๋ฐ˜์‘ํ˜•

 

 

 

๐Ÿ‘‹ ์•ˆ๋…•ํ•˜์„ธ์š”?

์ด๋ฒˆ ๊ณต๋ถ€๋Š” ํšŒ์‚ฌ ์—…๋ฌด๋ฅผ ์œ„ํ•ด ๊ณต๋ถ€๋ฅผ ํ•ด๋ณด๊ณ ์ž ํ•˜๋Š” ๋ถ€๋ถ„ ์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ์— ์ฃผ๋‹ˆํ•˜๋ž‘์€ ํšŒ์‚ฌ์—์„œ ์‚ฌ์šฉ์ค‘์ธ ๊ด€๋ฆฌ์ž 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

 

pip3 ์„ค์น˜ ์—ฌ๋ถ€ ํ™•์ธ

๋จผ์ € ์œ„์˜ ๋ช…๋ น์–ด๋กœ flask๋ฅผ ์„ค์น˜ํ•˜๋ ค๋ฉด pip๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•ด์š”. ์ฃผ๋‹ˆํ•˜๋ž‘์€ Pip3๋กœ ์ง„ํ–‰ํ•  ๊ฒƒ์ด๊ณ , ์œ„์™€ ๊ฐ™์ด ์„ค์น˜ ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์˜€์Šต๋‹ˆ๋‹ค.


$ pip3 install flask

์ด๋ ‡๊ฒŒ ์„ค์น˜๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด path๊ฐ€ ์ž๋™์œผ๋กœ ์žกํžŒ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.


        ๐Ÿ“ฆ Package Tree ๊ตฌ์„ฑ

Flask๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ๋Š” Package ๊ตฌ์„ฑ์ด ์žˆ๋‹ค๊ณ  ํ•ด์š”.

Flask ๊ธฐ๋ณธ ๊ตฌ์„ฑ


์œ„์˜ 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์€ ๋ฌธ์ž์—ด์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

start_helloflask.py


๊ทธ๋Ÿฐ ๋‹ค์Œ ์œ„์™€ ๊ฐ™์ด ์ž‘์„ฑ์„ ํ–ˆ๋Š”๋ฐ, ์ฒซ๋ฒˆ์งธ ์ค„์€ 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๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋˜์š”!

 

/__init__.py

 

์ฐธ๊ณ ๋กœ ์œ„์˜ 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 ์˜์—ญ์ธ ์ ์„ ์žŠ์œผ๋ฉด ์•ˆ๋˜์š”!

/__init__.py

 

์œ„์™€ ๊ฐ™์ด g๋ฅผ import๋ฅผ ํ•ด์ฃผ์—ˆ๊ณ , 9๋ฒˆ์งธ ์ค„์— @app.before_request Decoration์„ ์ผ๋Š”๋ฐ, ์ด๋Š” ์–ด๋–ค ์š”์ฒญ์ด ์–ด๋˜์ง€ ๋จผ์ € ๊ฑฐ์น˜๋Š” ๊ณณ์ด์—์š”.

12๋ฒˆ์งธ ์ค„์—๋Š” ํšŒ์› ๊ฐ€์ž… ์ˆ˜, ์ด์šฉ์ž ์ˆ˜ ๋“ฑ์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ๋„ฃ์œผ๋ฉด ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”. ์™œ๋ƒํ•˜๋ฉด ์ „์—ญ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณณ์ด๊ณ , Application Context์ด๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.

์˜ˆ๋ฅผ ๋“ค์–ด ์ € ๊ณณ์— ์ด์šฉ์ž๊ฐ€ ์ ‘์†ํ•  ๋•Œ ๋งˆ๋‹ค ๋”ํ•˜๊ธฐ ์—ฐ์‚ฐ์„ ํ•ด์ฃผ๋ฉด ๊ณ„์† ์ฆ๊ฐ€ํ•˜๊ฒ ์ง€์š”?

16๋ฒˆ์งธ ์ค„ getattr() ๋‘๋ฒˆ์งธ ์ธ์ž์— 12๋ฒˆ์งธ ์ค„ g.str ๊ฐ’์ด ์˜ค๊ฒŒ ๋˜์š”. ์„ธ๋ฒˆ์žฌ ์ธ์ž๋Š” Default ๊ฐ’์ด๋ž๋‹ˆ๋‹ค.
g.str์— ๊ฐ’์ด ์—†๋‹ค๋ฉด 111์„ ์ถœ๋ ฅํ•  ๊ฒƒ์ด์—์š”.

localhost:8080/junyharang


์œ„์™€ ๊ฐ™์ด ์ถœ๋ ฅ์ด ๋˜๋„ค์š”!

 

 

/__init__.py

 

์ด๋ฒˆ์—๋Š” Response์— ๋Œ€ํ•ด ๊ณต๋ถ€ ํ•ด ๋ณผ๊ฒŒ์š”.
8 ~ 11๋ฒˆ์งธ ์ค„์„ ๋ณด๋ฉด /res๋ผ๋Š” URI๋กœ ์š”์ฒญ์ด ์™”์„ ๋•Œ, Response ๊ฐ์ฒด์— Custom Response๋ผ๋Š” ๋ฌธ์ž์—ด์„ ๋‹ด๊ณ , HTTP Status Code 200๊ณผ ํ•จ๊ป˜ JSON ๊ฐ์ฒด๋ฅผ custom_res ๋ณ€์ˆ˜์— ๋„ฃ์–ด์ฃผ๊ณ , make_response()์— ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ๋„ฃ์–ด ๋ฐ˜ํ™˜ํ•ด ์ฃผ์—ˆ์–ด์š”.

 

localhost:8080/res


์œ„์™€ ๊ฐ™์ด ๋ฌธ์ž์—ด์ด ๋ฐ˜ํ™˜๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

 


๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ Network Tab์œผ๋กœ ํ™•์ธํ•ด ๋ณด๋‹ˆ HTTP Status Code๊ฐ€ 200์œผ๋กœ ์‘๋‹ต๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์–ด์š”.
๊ทธ๋ฆฌ๊ณ , ์‘๋‹ต ํ—ค๋” ๋ถ€์— test: ttt๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

HTTP Status Code ๋ถ€๋ถ„์„ 201๋กœ ๋ณ€๊ฒฝํ•˜๊ณ , ๋‹ค์‹œ ํ•œ๋ฒˆ ์ ‘์†ํ•ด ๋ณผ๊ฒŒ์š”.

localhost:8080/res


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 ๋“ฑ)





/__init__.py


์ด๋ฒˆ์—๋Š” 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()์„ ํ˜ธ์ถœํ•˜๊ณ , ํ•ด๋‹น ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด์„œ ์ข…๋ฃŒ ๋˜์š”.

 

http://localhost:8080/test/wsgi


์ถœ๋ ฅ๋œ ๊ฒƒ์„ ๋ณด๋‹ˆ 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๊ฐ€ ๋ถ™์€ ์ด์œ ๋Š” ๋‹ค์–‘ํ•œ ์šฉ๋„์˜ ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์“ด๋‹ค๋Š” ๋œป์œผ๋กœ ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์ƒ์†๋ฐ›์€ ์นœ๊ตฌ์—์š”.


/__init__.py


์ตœ์ดˆ ์ฒซ๋ฒˆ์งธ ์ค„์— request๋ฅผ Import ํ•ด ์ค€ ๋’ค ์š”์ฒญ URI๊ฐ€ /req์ผ ๋•Œ, ๋™์ž‘ํ•˜๋Š” Function์„ ๊ตฌํ˜„ํ•˜์˜€์–ด์š”.

์ด๊ฒƒ์€ Query String์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ํ•œ๋ฒˆ ๋ธŒ๋ผ์šฐ์ €๋กœ ์‹คํ–‰ํ•ด ๋ณผ๊ฒŒ์š”.

์˜ˆ๋ฅผ ๋“ค์–ด ์–ด๋–ค ์ด์šฉ์ž๊ฐ€ xxx.com/req/q=aaa ๋ผ๊ณ  URL์„ ์ž…๋ ฅํ•˜์—ฌ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ฒŒ ๋˜๋ฉด request.args.get('q')๋Š” URI์˜ q ๊ฐ’ ์ฆ‰, aaa๋ฅผ ๋ฐ›๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ ํ•ฉ๋‹ˆ๋‹ค.

http://localhost:8080/req?q=123

 

http://localhost:8080/req?q=%EC%A3%BC%EB%8B%88%ED%95%98%EB%9E%91


์ด๋Ÿฐ์‹์œผ๋กœ get Method๋ฅผ ํ™œ์šฉํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์—์š”.

 

 

# POST
request.form.get('p', 123)

 

post Method๋ฅผ ํ†ตํ•ด ์š”์ฒญ์„ ๋ฐ›์œผ๋ ค๊ณ  ํ•  ๋•Œ, ์š”์ฒญ Body๋กœ ๋ฐ›์„ ๊ฒƒ์„ ๋งค๊ฐœ ๋ณ€์ˆ˜ ์ฒซ๋ฒˆ์งธ์— ์ง€์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ์–ด์š”.
๋งค๊ฐœ ๋ณ€์ˆ˜ ๋‘๋ฒˆ์งธ ์ž๋ฆฌ๋Š” Default ๊ฐ’์œผ๋กœ ์ฒซ๋ฒˆ์งธ ๊ฐ’์ด ์—†์„ ๋•Œ ๋Œ€์‹ ํ•  ๊ฒƒ์„ ์จ์ค„ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

 

/__init__.py

์ด๋ฒˆ์—๋Š” getlist()์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด ๋ณผ๊ฒŒ์š”. ์ด๊ฒƒ์€ ์š”์ฒญ ๊ฐ’์ด ์—ฌ๋Ÿฌ๊ฐœ ์ผ ๋•Œ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์€ ๊ฒƒ์ด์—์š”.
์ฆ‰, ์ด์šฉ์žํ•œํ…Œ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ณ , ์ด์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์„ ํƒํ•ด์„œ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ์“ฐ๋ฉด ์ข‹์„ ๊ฒƒ์ด์—์š”.



http://localhost:8080/req?q=%EC%A3%BC%EB%8B%88%ED%95%98%EB%9E%91


์œ„์™€ ๊ฐ™์ด List ํ˜•ํƒœ๋กœ ๊ฐ’์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

http://localhost:8080/req?q=%EC%A3%BC%EB%8B%88%ED%95%98%EB%9E%91&q=Hello


์ฃผ์˜ํ•  ์ ์€ ์œ„์— ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด 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 ํ•ด ์ฃผ๋Š” ๊ฑฐ์—์š”.

 

/__init__.py

ํ•œ๋ฒˆ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ฐ’์„ ์ถœ๋ ฅํ•ด ๋ณผ๊ฒŒ์š”. ์š”์ฒญ ํ™˜๊ฒฝ๊ฐ’์ด %์œผ๋กœ ์ธํ•ด ๊ฐ๊ฐ์˜ ๊ฐ’์— ์ „์น˜๋  ๊ฒƒ์ด์—์š”.

 

http://localhost:8080/reqenv

 

 

 

 

    ๐Ÿ”ฝ  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

 

/__init__.py


/write/cookie URI ์š”์ฒญ๊ณผ ํ•จ๊ป˜ Query Sring์œผ๋กœ Cookie์— Key Value๊ฐ’์ด ์ „๋‹ฌ๋œ๋‹ค๋ฉด 11๋ฒˆ์งธ ์ค„์—์„œ ์š”์ฒญ์— get()์„ ํ†ตํ•ด 'key'๊ฐ’์„ ๊ฐ€์ ธ์™€ key ๋ณ€์ˆ˜์— ๋„ฃ๊ณ , value๋ฅผ ๊ฐ€์ ธ์™€ value ๋ณ€์ˆ˜์— ๋„ฃ์—ˆ์–ด์š”.

๊ทธ๋Ÿฐ ๋‹ค์Œ Response ๊ฐ์ฒด์— SET COKIE ๋ฌธ์ž์—ด๋ฅผ ์ „๋‹ฌํ•˜๊ณ , ๊ทธ ๋ฐ˜ํ™˜๊ฐ’์€ response ๊ฐ์ฒด์— ๋„ฃ์€ ๋‹ค์Œ cookie๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ, key ๋ณ€์ˆ˜์— ๋‹ด๊ธด ๊ฐ’๊ณผ value ๋ณ€์ˆ˜์— ๋‹ด์€ ๊ฐ’์„ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ค˜์š”.

๊ทธ๋Ÿฐ ๋‹ค์Œ make_response๋ฅผ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ง„ Cookie๋ฅผ ๋ฐ˜ํ™˜ํ•ด ์ฃผ๋ฉด ๋˜๋Š” ๊ฒƒ์ด์—์š”.

 

http://localhost:8080/write/cookie?key=token&value=abc

 

 

2. ์•„๋ž˜์™€ ๊ฐ™์ด ์š”์ฒญํ–ˆ์„๋•Œ, ํ•ด๋‹น key์˜ Cookie Value๋ฅผ ์ถœ๋ ฅํ•˜๋Š” Code ์ž‘์„ฑ
    - http://localhost:8080/read/cookie?key=token

/__init__.py

 

์ด๋ฒˆ์—๋Š” Cookie์— ๋‹ด๊ธด ๋‚ด์šฉ์„ ์ฝ์–ด์˜ค๋Š” ๊ฒƒ์„ ํ•ด ๋ณผ๊ฒŒ์š”.
/read/cookie URI๋กœ ์š”์ฒญ์ด ์˜ค๋ฉด rc()๊ฐ€ ๋™์ž‘ํ•˜๊ฒŒ ๋ ๊ฑฐ์—์š”.

์ตœ์ดˆ ์š”์ฒญ๊ฐ’ ์•ˆ์— ์žˆ๋Š” 'key'๋ผ๋Š” ์ด๋ฆ„์— ๊ฐ’์„ key๋กœ ๋‹ด์•„์ค˜์š”. ํ•ด๋‹น Key ์ด๋ฆ„์€ Query String์œผ๋กœ ์ „๋‹ฌํ•ด์ค˜์•ผ ํ•ด์š”.

๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ์š”์ฒญ cookie์•ˆ์— key๋ผ๋Š” ์ด๋ฆ„์˜ ๊ฐ’์„ value ๋ณ€์ˆ˜์— ๋‹ด์•„์ค˜์š”.

๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ํ•ด๋‹น ๋‚ด์šฉ์„ ์ถœ๋ ฅํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?


http://localhost:8080/read/cookie?key=token

 

์ด๋ ‡๊ฒŒ ํ•ด๋‹น ๋‚ด์šฉ์„ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ์–ด์š”. 

 

 

 

 

        ๐Ÿ“ฆ 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์„ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด์—์š”.


/__init__.py

 

/__init__.py

์ตœ์ดˆ 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์ด๋ผ๋Š” ์š”์†Œ์— ๋‹ด๊ธด ๊ฐ’์„ ๊ฐ€์ ธ์™€์„œ ๋ฐ”๋กœ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”. 

http://localhost:8080/setsess

 

Cookie๋ฅผ ๋ณด๊ฒŒ ๋˜๋ฉด junyharang_flask_session์ด๋ผ๋Š” Key๋กœ Session ๊ฐ’์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

http://localhost:8080/setsess

 

 

http://localhost:8080/getsess

 

 

http://localhost:8080/getsess

 

 

 

 

 

/__init__.py

21๋ฒˆ์งธ ์ค„์—์„œ 26๋ฒˆ์งธ ์ค„๊นŒ์ง€๋Š” Logout์„ ์œ„ํ•œ Session ์‚ญ์ œ ์ฒ˜๋ฆฌ ๋ถ€์—์š”.

/delsess๋กœ URI ์š”์ฒญ์ด ์˜ค๋ฉด if๋ฌธ์„ ํ†ตํ•ด Session ๊ฐ’์ด ์žˆ๋Š”์ง€ ๊ฒ€์ฆ์„ ํ•˜๊ธฐ ์œ„ํ•ด session List์— ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ, get()์„ ํ˜ธ์ถœํ•˜์—ฌ Token์ด๋ผ๋Š” ์š”์†Œ์— ๊ฐ’์„ ๊ฐ€์ ธ์™€์„œ ๊ฐ’์ด ์žˆ๋‹ค๋ฉด del์„ ํ†ตํ•˜์—ฌ session List์˜ Token ์š”์†Œ๋ฅผ ์•„์˜ˆ ์ง€์›Œ ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด์—์š”.

 

http://localhost:8080/delsess

 

Session ์‚ญ์ œ ์—ฐ์‚ฐ์„ ์ฒ˜๋ฆฌํ•ด ๋ฒ„๋ฆฌ๋‹ˆ junyharang_flask_session๊ฐ€ ์‚ฌ๋ผ์ ธ ๋ฒ„๋ ธ์–ด์š”!

 

 

 

 

 

 

 

 

728x90
๋ฐ˜์‘ํ˜•