[Flask] (7) REST API
π REST API λ ?
REST API : REST κΈ°λ°μΌλ‘ μλΉμ€ API(Application Interface) λ₯Ό ꡬνν κ²μ REST API λΌκ³ νλ€.
μ΅κ·Ό OpenAPI (λꡬλ μ¬μ©ν μ μλλ‘ κ³΅κ°λ API), λ§μ΄ν¬λ‘ μλΉμ€ λ±μ μ 곡νλ κΈ°μ μμλ λλΆλΆ REST APIλ₯Ό μ 곡νλ€.
π‘ REST API νΉμ§
- REST κΈ°λ°μΌλ‘ μμ€ν μ λΆμ°νμ¬ νμ₯μ±κ³Ό μ¬μ¬μ©μ±μ λμ¬ μ μ§λ³΄μλ₯Ό νΈλ¦¬νκ² ν μ μλ€.
- RESTλ HTTP νμ€μ κΈ°λ°μΌλ‘ ꡬννκ³ , HTTPλ₯Ό μ§μνλ νλ‘κ·Έλ¨ μΈμ΄λ‘ ν΄λΌμ΄μΈνΈ,μλ²λ₯Ό ꡬνν μ μλ€.
λ°λΌμ, REST APIλ₯Ό ꡬννλ©΄, ν΄λΌμ΄μΈνΈ λΏλ§ μλλΌ, JAVA, C#, WEB λ±μ μ΄μ©ν΄μ ν΄λΌμ΄μΈνΈλ₯Ό μ μν μ μλ€.
π‘ REST API κ·μΉ
RESTμμ κ°μ₯ μ€μν κΈ°λ³Έμ μΈ κ·μΉμ λ κ°μ§μ΄λ€.
URIλ μμμ νννλ λ° μ§μ€ν, νμμ λν μ μλ HTTP Methodλ₯Ό ν΅ν΄ νλ κ²μ΄ REST APIλ₯Ό μ€κ³νλ ν΅μ¬μ΄λ€.
1. URIλ μ 보μ μμμ ννν΄μΌ νλ€.
- 리μμ€λͺ μ λμ¬λ³΄λ€λ λͺ μ¬λ₯Ό μ¬μ©νλ€.
- URIλ μμμ νννλ λ°μ μ€μ μ λμ΄μΌνλ€.
- GETκ°μ νμμ λν ννμ΄ λ€μ΄κ°μλ μλλ€.
#μ μ’μ μμ
GET /getTodos/3
GET /todos/show/3
#μ’μ μμ
GET /todos/3
2. μμμ λν νμλ HTTP Method(GET, POST, PUT, DELETE λ±)μΌλ‘ νννλ€.
μ£Όλ‘ 5κ°μ§μ Method(GET, POST, PUT, DELETE , PATCH)λ₯Ό μ¬μ©ν΄μ CRUDλ₯Ό ꡬννλ€.
#μ μ’μ μμ
GET /todos/delete/3
#μ’μ μμ
DELETE /todos/3
π RESTful μ΄λ ?
- RESTfulμ μΌλ°μ μΌλ‘ RESTλΌλ μν€ν μ²λ₯Ό ꡬννλ μΉ μλΉμ€λ₯Ό λνλ΄κΈ° μν΄ μ¬μ©λλ μ©μ΄μ΄λ€.
- λ°λΌμ REST APIλ₯Ό μ¬μ©νλ μΉ μλΉμ€λ₯Ό μ°λ¦¬λ "RESTfulνλ€"κ³ ν μ μλ€.
- RESTfulμ RESTλ₯Ό RESTλ΅κ² μ°κΈ° μν λ°©λ²μΌλ‘ λκ΅°κ°κ° 곡μμ μΌλ‘ λ°νν κ²μ΄ μλλ€.
- RESTμ μ리λ₯Ό λ°λ₯΄κ³ μ¬μ©νλ μμ€ν μ RESTfulμ΄λΌλ μ©μ΄λ‘ μΉνκ² λλ€.
π‘ RESTfulμ λͺ©μ μ 무μμΈκ° ?
μ΄ν΄νκΈ° μ½κ³ μ¬μ΄ REST APIλ₯Ό λ§λλ κ²μ΄λ€.
- RESTfulν APIλ₯Ό ꡬννλ κ·Όλ³Έμ μΈ λͺ©μ μ΄ μ±λ₯ ν₯μμ΄ μ€μ μ΄ μλλ€.
- APIμ μ΄ν΄λμ νΈνμ±μ λμ΄λ κ²μ΄ μ£Όλ λͺ©μ μ΄λ€.
- λ°λΌμ, μ±λ₯μ΄ μ€μν μν©μμλ κ΅³μ΄ RESTfulν APIλ₯Ό ꡬνν νμκ° μλ€.
π REST API μ€κ³ κΈ°λ³Έ κ·μΉ
1. URIλ μ 보μ μμμ ννν΄μΌ νλ€.
- μμμ λμ¬λ³΄λ€λ λͺ μ¬λ₯Ό μ¬μ©
- μμμ λλ¬Έμ보λ€λ μλ¬Έμ μ¬μ©
- μμμ λνλ¨ΌνΈ μ΄λ¦μΌλ‘λ λ¨μ λͺ μ¬λ₯Ό μ¬μ©
- μμμ 컬λ μ μ΄λ¦μΌλ‘λ 볡μ λͺ μ¬λ₯Ό μ¬μ©
- μμμ μ€ν μ΄ μ΄λ¦μΌλ‘λ 볡μ λͺ μ¬λ₯Ό μ¬μ©
#μ μ’μ μμ
GET /Student/3
#μ’μ μμ
GET /students/3 # μλ¬Έμ,볡μλͺ
μ¬ μ¬μ©
2. μμμ λν νμλ HTTP Method(GET, POST, PUT, DELETE λ±)λ‘ νννλ€.
- URIμ HTTP Methodκ° λ€μ΄κ°λ©΄ μλλ€.
#μ μ’μ μμ
GET /students/delete/3
#μ’μ μμ
DELETE /students/3
- CRUD κΈ°λ₯μ λνλ΄λ κ²μ URIμ μ¬μ©νμ§ μλλ€.
#μ μ’μ μμ
GET /students/show/3
GET /students/insert/4
#μ’μ μμ
GET /students/3
POST /students/4
- : id λ νλμ νΉμ μμμ λνλ΄λ κ³ μ κ°μ΄λ€.
ex) studentλ₯Ό μμ±νλ route : POST/students
ex) id=12μΈ studentλ₯Ό μμ νλ route: DELETE/students/12
π μ©μ΄
- λκ·λ¨ΌνΈ : κ°μ²΄ μΈμ€ν΄μ€λ λ°μ΄ν°λ² μ΄μ€ λ μ½λμ μ μ¬ν κ°λ
- 컬λ μ : μλ²μμ κ΄λ¦¬νλ λλ ν°λ¦¬λΌλ μμ
- μ€ν μ΄ : ν΄λΌμ΄μΈνΈμμ κ΄λ¦¬νλ μμ μ μ₯μ
π REST API μ€κ³ κ·μΉ
1. μ¬λμ (/) λ κ³μΈ΅ κ΄κ³λ₯Ό λνλ΄λ λ° μ¬μ©νλ€.
ex) https://academy.elice.io/classroom/teach
2. URI λ§μ§λ§ λ¬Έμλ‘ μ¬λμ (/) λ₯Ό ν¬ν¨νμ§ μλλ€.
ex) https://academy.elice.io/classroom/teach/ ← ( X )
- URIμ ν¬ν¨λλ λͺ¨λ κΈμλ μμμ μ μΌν μλ³μλ‘ μ¬μ©λμΌ νλ€.
- URIκ° λ€λ₯΄λ€λ κ²μ λΆλ¬μ€λ μμμ΄ λ€λ₯΄λ€λ λ»μ΄κ³ , λ°λλ‘ μμμ΄ λ€λ₯΄λ©΄ URIλ λ¬λΌμ ΈμΌ νλ€.
- REST APIλ λΆλͺ
ν URIλ₯Ό λ§λ€μ΄ ν΅μ μ ν΄μΌ νκΈ° λλ¬Έμ νΌλμ μ£Όμ§ μλλ‘ URI κ²½λ‘μ λ§μ§λ§μλ
μ¬λμ (/) λ₯Ό μ¬μ©νμ§ μλλ€.
3. νμ΄ν (-) μ URI κ°λ μ±μ λμ΄λλ° μ¬μ©νλ€.
4. λ°μ€ ( _ ) μ URIμ μ¬μ©νμ§ μλλ€.
5. URI κ²½λ‘μλ μλ¬Έμλ₯Ό μ¬μ©νλ€.
6. νμΌνμ₯μλ URIμ ν¬ν¨νμ§ μλλ€.
ex) https://academy.elice.io/classroom/teach/111/python.png ← ( X )
ex) GET / classroom/teach/111/python HTTP/1.1 Host: academy.elice.io Accept: image/png ← ( O )
7. μμ κ°μ μ°κ΄ κ΄κ³κ° μλ κ²½μ° λ€μκ³Ό κ°μ΄ μμ±νλ€.
/μμλͺ
/μμID/κ΄κ³κ° μλ λ€λ₯Έ μμλͺ
ex) GET : /students/{studentid}/classroom
π REST API : CRUD ꡬνν΄λ³΄κΈ°
μμ ν¬μ€ν ( Flask 1~ 6 )μ 보면, render_template( ) λ©μλλ₯Ό μ΄μ©ν΄μ, htmlμ μΆλ ₯ κ²°κ³Όλ₯Ό λμ κ°λ€μ νμΈνμλ€.κ·Έλ¦¬κ³ htmlμμλ jinja2 λ¬Έλ²μΌλ‘ ν΄λΉ λ΄μ©μ λ°μμ htmlμ λμΈ μ μμλ€.
νμ§λ§, μ΄λ "API μλ²"λ₯Ό κ°λ°ν κ²μ΄ μλ, Flaskλ₯Ό νμ©ν΄μ "μΉ μ΄ν리μΌμ΄μ "μ κ°λ°ν κ²μ΄λ€.
REST API μλ²λ₯Ό κ°λ° ν λλ, μλ²λ¨μμ μ§μ λ λλ§(Rendering)ν΄μ νμ΄μ§λ₯Ό 보μ¬μ£Όλ κ²μ΄ μλλΌ
μΉ νμ΄μ§λ₯Ό ꡬμ±νλλ° νμν "μ 보λ₯Ό λ°ν" ν΄μ£Όλλ‘ κ΅¬νν΄μΌ νλ€.
λ°λΌμ, λ°±μλ μλ²λ ν΄λΌμ΄μΈνΈ(νλ‘ νΈ μλ) μ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°μμΌλ‘μ¨ ν΅μ μ νκ² λλ κ²μ΄λ€.
π μΉ μμμ κ°μ₯ λ§μ΄ μ°μ΄λ λ°μ΄ν° νμμ JSON νμμ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°λλ€.
π [Tips] REST APIλ₯Ό μν΄ κ΅¬νλλ CRUDμ λ©μλμ URLμ μ΄λ¦μ CRUDμ λ§μΆλ κ²μ΄ μΌλ°μ μ΄λ€.
from flask import Flask, render_template, request, redirect, url_for
import json
app = Flask(__name__)
board = [] # μ€μ DBκ° μλ, μμ λ₯Ό μν board 리μ€νΈ
# root κ²½λ‘
@app.route('/')
def index():
return render_template("Boards.html", rows = board)
# POST : CREATE (C)
@app.route("/create", methods=["POST"])
def create():
name = request.form["name"]
context = request.form["context"]
board.append([name,context])
return json.dumps( { "status":200, "result" : { "id" : len(board)} } ) # json.dumps({ HTTP μν, λ°νν κ²°κ³Ό }) = λ°μ΄ν°λ₯Ό json ννλ‘ λ³νν΄μ€λ€.
# GET : READ (R)
@app.route("/read", methods=["GET"])
def read():
return json.dumps({"status":200, "result":board})
if __name__ == '__main__':
app.run()
<!-- ./templates/Boards.html -->
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>κ²μν λ±λ‘</title>
<style type="text/css">
body{ text-align: center; }
</style>
</head>
<body>
<h1>κ²μν</h1>
<h4>μΆκ°</h4>
<form action = "/create" method = "POST">
μ΄λ¦<br>
<input type = "text" name = "name" /><br>
λ΄μ©<br>
<textarea name = "context" cols="50" rows="10"></textarea><br><br>
<input type = "submit" value = "κ² μ" /><br>
</form>
<h4>λͺ©λ‘보기</h4>
<table class="table" border="1" width = 600 style = "word-break:break-all" style="table-layout: fixed" align="center">
<thread>
<th width="4%">λͺ©μ°¨</th>
<th width="15%">μ΄λ¦</th>
<th width="25%">λ΄μ©</th>
</thread>
{% for row in rows %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ row[0] }}</td>
<td>{{ row[1] }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
π‘ CREATE : POST
π‘ READ : GET
π UPDATE(PUT)μ DELETE(DLEDTE)λ μμ , CREATE(POST), READ(GET)κ³Ό λ¬λ¦¬, Ajaxλ₯Ό μ΄μ©ν΄μ ꡬνλκΈ°λ νλ€.
π Ajax : λΉλκΈ°μ(Asynchronous) JavaScript + XML μ΄λ€.
Ajax λ REST APIλ₯Ό μμ½κ² ꡬννκΈ° μν΄ μ¬μ©λλ "νλ μμν¬"μ΄λ©°, html νμΌμμ κ°λ¨ν μ¬μ©νλ λ°©λ²μ ν΄λ³΄μ.
( μ΄λ²μλ, html νμΌμ λ, μ£ΌμκΉκ² 보μ. ( Ajax λΆλΆ ) )
# Ajax_Example.py
from flask import Flask, render_template, request, jsonify # Flaskμ λ΄μ₯λ jsonify = json.dump() μ κ°μ κΈ°λ₯μ΄λ€. json ννλ‘ λ°μ΄ν° λ°ν
app = Flask(__name__)
board = [] # μμ DB κ°λ
(μ¬μ€,리μ€νΈ)
# root
@app.route("/")
def index():
return render_template("ajax_index.html", rows=board)
@app.route("/ajax", methods=["POST"])
def ajax():
data = request.get_json() # request.get_json() = POST μμ²μ ν΅ν΄ μ»μ λ°μ΄ν° -> json νμμΌλ‘ μ»κΈ° μν λ©μλ
board.append(data)
return jsonify(result="success", result2=data) # json_dumps({}) μ κΈ°λ₯μ κ°λ€.
if __name__ == '__main__':
app.run()
<!--ajax_index.html-->
<html>
<head>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
<p id="example">AJAX</p>
<input type="text" id="id1" placeholder="id">
<input type="text" id="name1" placeholder="name">
<input type="text" id="context1" placeholder="context">
<input type="button" id="execute" value="execute">
<script>
$('#execute').click(function () {
var id = $('#id1').val();
var name = $('#name1').val();
var context = $('#context1').val();
var postdata = {
'id': id, 'name': name, 'context': context
}
// ajax νμμΌλ‘ -> ajax example.pyλ‘ λ°μ΄ν° μ μ‘
$.ajax({
type: 'POST',
url: '{{url_for("ajax")}}',
data: JSON.stringify(postdata), // μλ²λ‘ λ°μ΄ν°λ₯Ό λκΈΈλλ, JSON.stringify(λ°μ΄ν°)λ‘ StringνμμΌλ‘ λ겨μ€λ€.
dataType: 'JSON',
contentType: "application/json",
success: function (data) {
alert('μ±κ³΅! λ°μ΄ν° κ°:' + data.result2['id'] + " " + data.result2['name'] + " " + data.result2['context'])
},
error: function (request, status, error) {
alert('ajax ν΅μ μ€ν¨')
alert(error);
}
})
})
</script>
<table border=1 width="600">
<thead>
<td>λͺ©μ°¨</td>
<td>μ΄λ¦</td>
<td>λ΄μ©</td>
</thead>
{% for row in rows %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ row['name'] }}</td>
<td>{{ row['context'] }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
π‘ UPDATE & DELETE ( PUT & DELETE )
from flask import Flask, render_template, jsonify, request
app = Flask(__name__)
board = [{"id": 1, "name": "elice", "context": "test"}]
@app.route('/')
def index():
return render_template('index.html', rows = board)
@app.route('/create', methods=['POST'])
def create():
data = request.get_json()
board.append(data)
return jsonify(result = "success", result2= data)
@app.route('/delete', methods=['POST'])
def delete():
del board[-1]
return jsonify(result="success")
@app.route('/put', methods=['POST'])
def put():
data = request.get_json()
board.append(data)
return jsonify(result="success",result2=data)
<!--index.html-->
<html>
<head>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
<p id="example">AJAX</p>
<input type="text" id="id1" placeholder="id">
<input type="text" id="name1" placeholder="name">
<input type="text" id="context1" placeholder="context">
<input type="button" id="create" value="create">
<input type="button" id="update" value="update">
<input type="button" id="delete" value="delete">
<script>
// POST (CREATE)
$('#create').click(function(){
var id = $('#id1').val();
var name = $('#name1').val();
var context = $('#context1').val();
var postdata = {
'id':id, 'name':name, 'context':context
}
$.ajax({
type: 'POST',
url: '{{url_for("create")}}',
data: JSON.stringify(postdata),
dataType : 'JSON',
contentType: "application/json",
success: function(data){
alert('μ±κ³΅! λ°μ΄ν° κ°:' + data.result2['id']+" " + data.result2['name']+ " " + data.result2['context'])
},
error: function(request, status, error){
alert('ajax ν΅μ μ€ν¨')
alert(error);
}
})
})
// PUT (UPDATE)
$('#update').click(function(){
var id = $('#id1').val();
var name = $('#name1').val();
var context = $('#context1').val();
var postdata = {
'id':id, 'name':name, 'context':context
}
$.ajax({
type: 'POST',
url: '{{url_for("put")}}',
data: JSON.stringify(postdata),
dataType : 'JSON',
contentType: "application/json",
success: function(data){
alert('μ±κ³΅! μμ λ λ°μ΄ν° κ°:' + data.result2['id']+" " + data.result2['name']+ " " + data.result2['context'])
},
error: function(request, status, error){
alert('ajax ν΅μ μ€ν¨')
alert(error);
}
})
})
// DELETE (DELETE)
$('#delete').click(function(){
$.ajax({
type: 'POST',
url: '{{url_for("delete")}}',
contentType: "application/json",
success: function(){
alert('μ±κ³΅! λ°μ΄ν° μμ μλ£')
},
error: function(request, status, error){
alert('ajax ν΅μ μ€ν¨')
alert(error);
}
})
})
</script>
<table border=1 width="600">
<thead>
<td>λͺ©μ°¨</td>
<td>μ΄λ¦</td>
<td>λ΄μ©</td>
</thead>
{% for row in rows %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ row['name'] }}</td>
<td>{{ row['context'] }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>