03_Nov_2021 ๐Ÿฐ ์—˜๋ฆฌ์Šค AI ํŠธ๋ž™ TIL: Flask ๊ธฐ์ดˆ

์œ ํ™˜์ตยท2021๋…„ 11์›” 3์ผ
0

Alexander Yoo์˜ Web Programming

๋ชฉ๋ก ๋ณด๊ธฐ
4/4

์›น ์„œ๋ฒ„์˜ ๋™์ž‘ ๊ณผ์ • ์ดํ•ดํ•˜๊ธฐ

์šฐ๋ฆฌ๊ฐ€ ํ”ํžˆ ์ •๋ณด๋“ค์„ ์ ‘ํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๋งŽ์€ ์„œ๋น„์Šค๋Š” '์›น ์„œ๋ฒ„'๋ฅผ ํ†ตํ•ด ์šฐ๋ฆฌ์—๊ฒŒ ์ œ๊ณต๋˜๊ณ  ์žˆ๋‹ค.

์›น ์„œ๋ฒ„์˜ ๋™์ž‘ ๊ณผ์ •

ํด๋ผ์ด์–ธํŠธ๋ž€? ์‚ฌ์šฉ์ž/ ์‚ฌ์šฉ์ž ์ปดํ“จํ„ฐ / ์ธํ„ฐ๋„ท ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์— ์š”์ฒญํ•œ๋‹ค.
์„œ๋ฒ„๋ž€? ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ด์ฃผ๊ณ  ์‘๋‹ต์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋Œ๋ ค์ฃผ๋Š” ๊ณณ์„ ์˜๋ฏธํ•œ๋‹ค.

์›น ์„œ๋ฒ„์˜ ๋™์ž‘: ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ํ•˜๊ณ , ์š”์ฒญ์„ ๋ฐ›์€ ์„œ๋ฒ„๋Š” ์š”์ฒญ์— ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋Œ๋ ค์ค€๋‹ค.

์„œ๋ฒ„์˜ ์‘๋‹ต์œผ๋กœ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ›๋Š” ์‘๋‹ต์ธ ๋ฐ์ดํ„ฐ๋Š” HTML, JSON, XML ๋“ฑ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.

์š”์ฒญ๊ณผ ์‘๋‹ต

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„ ์ •๋ณด ๊ตํ™˜์—์„œ๋Š” ๋ฏธ๋ฆฌ ์•ฝ์†ํ•œ ๊ทœ์น™์„ ํ†ตํ•ด์•ผ ํ•œ๋‹ค.
ํด๋ผ์ด์–ธํŠธ๋Š” ๊ทœ์น™์— ๋”ฐ๋ผ ์š”์ฒญ์„ ํ•˜๊ณ , ์„œ๋ฒ„ ๋˜ํ•œ ์ •ํ•ด์ง„ ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋กœ ์‘๋‹ต์„ ํ•œ๋‹ค.

์ •ํ•ด์ง„ ํ˜•์‹, ๋ฐ์ดํ„ฐ์˜ ํ†ต๋กœ: API

์›น์‚ฌ์ดํŠธ์˜ ์ ‘์† ์ฃผ์†Œ๋Š” ๋ฏธ๋ฆฌ ์•ฝ์†๋œ ์ฃผ์†Œ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ตฌ๊ธ€์˜ url ์ฃผ์†Œ (https:// www.naver.com)๊ฐ€ ์žˆ๋‹ค. ํ•ด๋‹น ํŽ˜์ด์ง€์˜ url ์ฃผ์†Œ๋ฅผ ์ฃผ์†Œ์ฐฝ์— ์ž…๋ ฅํ•˜๋ฉด, ์•ฝ์†๋œ ๋ฐฉ๋ฒ•์œผ๋กœ ์š”์ฒญํ•œ ํ›„ ํ•ด๋‹นํ•˜๋Š” ํŽ˜์ด์ง€๋ฅผ ๋ณด๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋ ‡๊ฒŒ ์ •ํ•ด์ง„ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ์˜ ํ†ต๋กœ ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ API๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

Flask Framework๋ž€?

Framework๋ž€?

ํ•˜๋‚˜์˜ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ ์ œ๊ณตํ•˜๋Š” ์›น ๊ฐœ๋ฐœ 'ํ‹€'์ด๋‹ค.
๋ฏธ๋ฆฌ ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š” ํ•จ์ˆ˜(๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)์™€ ๊ทธ ์ด์ƒ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

Flask

Python์„ ์‚ฌ์šฉํ•ด์„œ ์›น ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์ž‡๊ฒŒ ๋„์™€์ฃผ๋Š” Web Framework์ด๋‹ค

Python ๊ธฐ๋ฐ˜์˜ Framework๋กœ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ

  • ๋‹ค๋Ÿ‰์˜ ๊ธฐ๋Šฅ์„ ๋ฏธ๋ฆฌ ์ œ๊ณตํ•˜๋Š” Django (์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ๋งŽ์Œ)

  • ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ๋งŒ ์ œ๊ณตํ•˜๋Š” MicroFramework: Flask, Pyramid, Bottle (๊ฐœ๋ฐœ์ด ์ž์œ ๋กญ๋‹ค)

๊ฐ€ ์žˆ๋Š”๋ฐ, ๊ฐ๊ฐ์˜ Framework ๋งˆ๋‹ค ์žฅ/๋‹จ์ ์ด ์žˆ๋‹ค.

Flask์˜ ์žฅ์ 

  • ๋‚˜๋งŒ์˜ ์„œ๋ฒ„๋ฅผ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ex) python, html, css, js ํ™œ์šฉ
  • ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ๋น ๋ฅด๊ฒŒ ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๋‹ค. ex) app.run()
  • ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์œ ์—ฐํ•˜๊ฒŒ ํ™•์žฅํ•˜๊ธฐ ํŽธ๋ฆฌํ•˜๋‹ค. e.g.) micro framework

Flask๋กœ ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

์›น ์„œ๋ฒ„๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์€ ๋ณต์žกํ•  ๊ฒƒ ๊ฐ™์ง€๋งŒ Flask Framework๋ฅผ ์‚ฌ์šฉํ•ด์„œ
๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋งŒ์œผ๋กœ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

Flask Simple Web Server ๋งŒ๋“ค๊ธฐ

from flask import Flask
app = Flask(__name__)

@app.route('/')
def alex():
  return 'hello alex'

if __name__ == '__main__":
  app.run() 
  • Flask ํŒจํ‚ค์ง€์—์„œ Flask๋ฅผ importํ•œ๋‹ค.
  • @app.route()๋Š” ์„œ๋ฒ„์— ์ ‘์† ํ•  ์ˆ˜ ์žˆ๋Š” url์„ ๋งŒ๋“ค์–ด ์ค€๋‹ค.
  • @app.route('/') ์•„๋ž˜์˜ def elice()๋ผ๋Š” ํ•จ์ˆ˜๋Š” app.route()์˜ url์—์„œ ์‹คํ–‰ํ•  ํ•จ์ˆ˜์ด๋‹ค.
  • if __name__ == '__main__'์€, ํŒŒ์ผ >์ด๋ฆ„์ด main์ผ ๋•Œ๋งŒ app.run()์ด ์‹คํ–‰๋˜๋„๋ก ํ•œ๋‹ค.

URL์„ ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚ด๊ธฐ

app.route()๋Š” url์„ ๋งŒ๋“ค์–ด์ค€๋‹ค. app.route()์™€ ์ด์–ด์ ธ ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ HTML๊ณผ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด๋ณด์ž.

JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ ๋‚˜ํƒ€๋‚ด๊ธฐ

from flask import Flask, jsonify
app = Flask(__name__)

@app.route('/')
def alex_json():
  my_data = {'name':'elice'}
  return jsonify(my_data)

if __name__ = '__main__':
  app.run()
  • Flask ํŒจํ‚ค์ง€์—์„œ Flask์™€ jsonify๋ฅผ importํ•œ๋‹ค.
  • jsonify๋ผ๋Š” ํ•จ์ˆ˜๋Š” jsonify() ์•ˆ์— ์žˆ๋Š” ๋‚ด์šฉ์„ ํ™”๋ฉด์— ์ „๋‹ฌํ•œ๋‹ค.
  • @app.route('/') ์•„๋ž˜์˜ def elice_json() ํ•จ์ˆ˜๋Š” app.route()์˜ url์—์„œ ์‹คํ–‰ํ•  ํ•จ์ˆ˜์ด๊ณ , {'name':'elice'}๋ผ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ™”๋ฉด์— ์ „๋‹ฌ ํ•ด์ค€๋‹ค.

HTML ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ ๋‚˜ํƒ€๋‚ด๊ธฐ - ํŒŒ์ผ ์ค€๋น„ํ•˜๊ธฐ

  • html์„ ํ™”๋ฉด์— ์ „๋‹ฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” html ํŒŒ์ผ์ด ํ•„์š”ํ•˜๋‹ค.
  • html ํŒŒ์ผ์€ templates๋ผ๋Š” ํด๋” ์•„๋ž˜์— ์œ„์น˜์‹œํ‚จ๋‹ค.
  • templates ํด๋”์— htmlํŒŒ์ผ์„ ๋„ฃ์œผ๋ฉด Flask๊ฐ€ ์ž๋™์œผ๋กœ ์ฐพ์•„์„œ ์—ฐ๊ฒฐํ•œ๋‹ค.
<html>
    <head>
    	<title>๋‚˜์˜ ์ฒซ html</html>
    </head>
    <body>
    	<h4>htmlํŒŒ์ผ ๋„์šฐ๊ธฐ</h4>
    </body>
</html>
from flask import Flask, render_template
app = Flask(__name__)

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

if __name__ == '__main__':
  app.run()
  • Flask ํŒจํ‚ค์ง€์—์„œ Flask์™€ render_template๋ฅผ import ํ•ฉ๋‹ˆ๋‹ค.
  • render_template ๋ผ๋Š” ํ•จ์ˆ˜๋Š” templates๋ผ๋Š” ํด๋” ์•ˆ์˜ htmlํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์™€ ์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
  • templates ํด๋” ๋‚ด์˜ html ํŒŒ์ผ์˜ ์ด๋ฆ„๊ณผ render_template()์•ˆ์˜ ์ด๋ฆ„์ด ๊ฐ™์•„์•ผ ํ™”๋ฉด์— ์ž˜ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ…œํ”Œ๋ฆฟ ํด๋” ๋‚ด์˜ html์„ render_template์— ๋„ฃ์–ด์„œ elice_html ํ•จ์ˆ˜์˜ return์— ๋„ฃ์–ด์ค€๋‹ค.

์—ฌ๋Ÿฌ๊ฐ€์ง€ url ์—ฐ๊ฒฐํ•˜๊ธฐ

@app.route('url')
  • url ์ฃผ์†Œ๋ฅผ route()์˜ ์ธ์ž๋กœ ๋„ฃ์–ด์ค€๋‹ค.
  • 1๊ฐœ์˜ @app.route๋Š” 1๊ฐœ์˜ ํ•จ์ˆ˜์™€ ์—ฐ๊ฒฐ๋  ์ˆ˜ ์žˆ๋‹ค.
  • @app.route๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ์‚ฌ์šฉํ•ด์„œ ๋‹ค์–‘ํ•œ url์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
    ์ฃผ์˜ ํ•œ๋ฒˆ ์„ ์–ธํ•œ ํ•จ์ˆ˜์˜ ์ด๋ฆ„์€ ๋‹ค์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

REST API๋ž€?

HTTP URL์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ์˜ ์ž์›์„ ํ‘œํ˜„ํ•˜๊ณ , HTTP Method๋ฅผ ํ†ตํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์„ ์˜๋ฏธํ•œ๋‹ค.
Database, ์ด๋ฏธ์ง€, ํ…์ŠคํŠธ ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

REST API์˜ ๊ฐœ๋…

  • HTTP URI (Uniform Resource Identifier)๋ฅผ ํ†ตํ•ด ์ž์›์„ ๋ช…์‹œํ•˜๊ณ , HTTP Method(POST, GET, PUT, DELELTE)๋ฅผ ํ†ตํ•ด ํ•ด๋‹จ ์ž์›์— ๋Œ€ํ•œ CRUD๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ
  • ๋‹ค์–‘ํ•œ ํด๋ผ์ž‰์–ธํŠธ๊ฐ€ ์ƒ๊ฒจ๋‚จ์— ๋”ฐ๋ผ์„œ REST API๊ฐ€ ํ•„์š”ํ•˜๋‹ค (๋‹ค์–‘ํ•œ ๊ณณ์—์„œ์˜ ํ†ต์‹  ์œ„ํ•ด)
  • REST API๋Š” ๋ฉ”์‹œ์ง€๊ฐ€ ์˜๋„ํ•˜๋Š” ๋ฐ”๋ฅผ URL์—์„œ ๋‚˜ํƒ€๋‚ด๋ฏ€๋กœ, ์‰ฝ๊ฒŒ ๊ธฐ๋Šฅ์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • HTTP ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ์— ๋”ฐ๋ฅด๋Š” ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ์˜ ๊ตฌ๋ถ„์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • REST API์˜ ํ‘œ์ค€์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

HTTP Method ์‚ฌ์šฉํ•˜๊ธฐ

HTTP Method์˜ ๊ฐœ๋… - GET/POST

GET๊ณผ POST๋Š” HTTP Method ์ค‘ ํ•˜๋‚˜์ด๋‹ค. GET์€ ๋ฐ์ดํ„ฐ๋ฅผ URL ๋’ค์— ?์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  POST๋Š” ํŠน์ • ์–‘์‹์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด ์ „์†กํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

GET ๋ฐฉ์‹์˜ ์˜ˆ์‹œ

http://์‚ฌ์ดํŠธ์˜ ์ฃผ์†Œ?๋ฐ์ดํ„ฐ=123

  • url ๋’ค์— ๋ฌผ์Œํ‘œ๋ฅผ ๋ถ™์—ฌ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์— ์ „์†กํ•œ๋‹ค.

POST ๋ฐฉ์‹์˜ ์˜ˆ์‹œ

http://์‚ฌ์ดํŠธ์˜ ์ฃผ์†Œ
์ผ์ •ํ•œ ์–‘์‹์— ๋‹ด์•„ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆจ๊ฒจ์„œ ์„œ๋ฒ„์— ์ „์†กํ•œ๋‹ค. (url์ด ๊ฐ™์•„๋„ ๋‚ด์šฉ์€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ)

์ฝ”๋“œ ์˜ˆ

@app.route('url1', methods=["GET"]
@app.route('url2', methods=["POST"]
@app.route('url3', methods=["GET", "POST"]
  • app.route()์— methods๋ผ๋ฏ„ ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•ด์„œ ํ•ด๋‹นํ•˜๋Š” HTTP Method๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • url1, url2๋Š” ๊ฐ๊ฐ GET,POST ๋ฉ”์„œ๋“œ๋งŒ ์‚ฌ์šฉ๊ฐ€๋Šฅ
  • url3๋Š” GET,POST ๋ชจ๋‘ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

GET ์š”์ฒญ๋งŒ ์‚ฌ์šฉ

from flask import *
app = Flask(__name__)

@app.route('/', methods=['GET']) # url ๋’ค์— ?name=alex๋ฅผ ๋„ฃ์–ด get ์š”์ฒญ์„ ํ•œ๋‹ค.
def alex():
	name = request.args.get['name']
    result = 'hello. ' + name
    return result
if __name__ == '__main__':
	app.run()

POST ์š”์ฒญ๋งŒ ์‚ฌ์šฉ

index.html

<html>
<body>
    <form action='/login' method='post'>
    	<p>
        ์•„์ด๋””: <input type='text' name='id'>
        </p>
        <p>
        ๋น„๋ฐ€๋ฒˆํ˜ธ: <input type='password' name='pwd'>
        </p>
        <button type='submit'>
    </form>
</body>
</html>

app.py

from flask import *
app = Flask(__name__)

@app.route('/', methods=['GET'])
def alex():
	return render_template('index.html')

@app.route('/login', methods=['POST'])
def alex_post():
	id = request.form['id']
    pwd = request.form['pwd']
    if id == 'alex' and pwd ='1234':
    	return 'Hi! Alex!'
    else:
    	return 'ERROR'

 if __name__ == '__main__':
 	app.run()
profile
์‚ฌ์šฉ์ž์˜ ํŽธ์˜๋ฅผ ๋” ์ƒ๊ฐํ•˜๊ณ  ํŽธ์•ˆํ•œ UI/UX ๊ฐœ๋ฐœ์„ ๊ฟˆ๊พธ๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ง€๋ง์ƒ์ž…๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€