개요
2022.09.16 - [Flask] 웹 애플리케이션 만들기 에서 여러 개의 URL을 가지고, 동적 URL을 지원하는 웹 애플리케이션을 만들어봤다. 이 글에서는 간단한 REST API를 만들어보려고 한다.
먼저 개념적인 내용부터 간단히 정리한다.
REST와 REST API
REST
Representational State Transfer의 약자.
자원의 이름을 기반으로 하여 상태를 주고받는 것을 의미한다. JSON, XML을 통해 데이터를 주고받는다.
REST API
API(Application Programming Interface)란 응용 프로그램에서 사용할 수 있도록, 운영 체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 의미한다.
즉, REST API는 REST 기반으로 구현한 서비스 API로 URI(Uniform Resource Identifier)를 통해 자원을 명시하고 HTTP에서 제공하는 메서드를 활용해 자원에 대한 CRUD를 동작하게 하는 API라고 할 수 있다.
URL / URI
URL; Uniform Resource Locator
해당 경로에 실제로 존재하는 자원의 위치를 가리킨다.
가령 https://example.com/index.html 이라는 주소는 example.com 웹 서버의 root 디렉터리 내에 위치한 index.html이라는 파일을 요청하기 위한 주소이다.
URI; Uniform Resource Identifier
웹 기술에서 사용하는 논리적 또는 물리적 리소스를 식별하는 고유한 문자열 시퀀스
https://example.com/index가 index.html을 가리킨다고 해도, https://example.com/index는 index.html에 대한 위치 정보를 포함하지 않으므로 URL이라고 할 수 없다.
HTTP 메소드
HTTP 메서드는 클라이언트가 서버에게 주어진 리소스에 무엇을 하길 원하는지를 나타낸다. 간단히 개념 정도만 정리한다.
- GET (Read) : 리소스(데이터)를 요청한다. 가장 일반적인 메서드로, URI에 매개변수를 추가하여 요청하는 방식이다.
- HEAD : GET과 비슷하지만 응답 본문을 포함하지 않는 header 정보만을 요청한다.
- POST (Create) : 요청 데이터를 HTTP body에 담아 전송한다.
- PUT (Put) : POST와 비슷하지만 내용 갱신 위주이다.
- DELETE (Delete) : 리소스를 삭제한다.
- OPTIONS : 웹 서버가 어떤 메서드를 지원하는지 알려준다.
HTTP 메서드는 이 외에도 존재하지만, 대부분읜 웹 서버가 보안 상의 이유로 GET, POST 2개의 메소드 또는 OPTIONS 포함 3개의 메서드를 허용하는 경우가 일반적이다.
Flask는 기본적으로 GET 방식을 제공하지만, @app.route에 methods 매개변수를 통해 메서드를 변경할 수 있다.
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
JSON 형식으로 응답
Flask는 jsonify 함수를 이용해 요청에 대해 JSON 형식으로 응답할 수 있다.
jsonify 함수는 JSON 출력을 application/json mimetype을 포함한 Response 객체로 변환한다.
예시 코드
@app.route('/users/<username>')
def get_user_info(username):
return jsonify({"username:": username}), 200
요청
curl -i -X GET \
'http://localhost:5000/users/passwd'
결과
응용
POST 메서드로 로그인을 요청하여 JSON 형식으로 응답하는 API를 만들어본다.
요구사항
- URI : /login
- POST 메소드로 username과 password를 전송한다. 계정 정보는 민감정보이므로 Authorization Header로 전송한다.
- 관리자 계정 로그인이라고 가정하고, 요청받은 username과 password가 기설정된 값과 일치하면, username과 ok 메시지를 JSON 형식으로 응답한다.
{"message":"ok","username":"passwd"}
- 로그인 성공 시 응답 코드는 200으로 한다.
- 로그인 실패 시 응답 코드는 401로 한다.
코드
import base64
from flask import Flask
from flask import request
from flask import Response
from flask import jsonify
# 관리자 계정 정보
ADMIN_USERNAME = 'passwd'
ADMIN_PASSWD = '1111'
app = Flask(__name__)
@app.route('/login', methods=['POST'])
def login():
# request에서 Authorization header 정보 추출
auth = request.headers.get('Authorization')
# request 내 username, passwd 정보 추출
auth = auth.split()[-1]
auth = base64.b64decode(auth).decode('UTF-8')
username, passwd = auth.split(':')
# 계정 정보 비교
if username == ADMIN_USERNAME and passwd == ADMIN_PASSWD:
# 응답
response = {
'username': username,
'message': 'ok'
}
return jsonify(response), 200
return Response('Unauthorized', 401)
테스트
1. 로그인 성공
curl -i -X POST \
-H "Content-Type:application/json" \
-H "Authorization:Basic cGFzc3dkOjExMTE=" \
'http://localhost:5000/login'
2. 로그인 실패
curl -i -X POST \
-H "Content-Type:application/json" \
-H "Authorization:Basic cGFzZDpkc2Rm" \
'http://localhost:5000/login'
참고 문서
https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html
https://rekt77.tistory.com/104?category=825845
https://www.charlezz.com/?p=44767
http://www.ktword.co.kr/test/view/view.php?no=3791