๐ REST API ๋ ?
REST API : REST ๊ธฐ๋ฐ์ผ๋ก ์๋น์ค API(Application Interface) ๋ฅผ ๊ตฌํํ ๊ฒ์ REST API ๋ผ๊ณ ํ๋ค.
[Flask] (2) REST & HTTP Method & API/End Point
๐ REST๋ ๋ฌด์์ธ๊ฐ ? REST : Representational State Transfer = ์์์ ์ด๋ฆ(์์์ ํํ)์ผ๋ก ๊ตฌ๋ถํ์ฌ ํด๋น ์์์ ์ํ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ฒ์ ์๋ฏธํ๋ค. = ์ฆ, ์์(resourece) ์ ํํ(representation)์ ์ํ "..
youngminieo1005.tistory.com
์ต๊ทผ 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>
'python' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Flask] (6) ORM & SQLAlchemy (0) | 2021.01.28 |
---|---|
[Flask] (5) RDB - Flask Connection & ๊ฒ์ํ ์์ (0) | 2021.01.25 |
[Flask] (4) ์ธ์ฆ & ๋ก๊ทธ์ธ๊ตฌํ & ๋ก๊น (0) | 2021.01.25 |
[Flask] (3) ๋ ๋๋ง ํ ํ๋ฆฟ & Jinja2 & ๊ฐ๋จํ ๊ฒ์ํ (0) | 2021.01.24 |
[Flask] (2) REST & HTTP Method & API/End Point (0) | 2021.01.22 |