개요
Python으로 웹서버를 띄울 때 Flask와 django를 많이 사용한다.
본래 Spring Boot로 REST API를 제작해서 많이 사용해왔으나 이는 안정적인 대신 프로젝트 구조가 복잡하고 배우는데 많은 시간이 걸린다.
Spring Boot로 REST API를 만든다고 하면 보통 다음과 같은 로직으로 구성된다.
Flask는 Controller, Service, DAO를 포괄하여 하나의 함수로 잡는 개념처럼 보인다. 물론 ORM은 별도로 구성해야 한다.
Flask 사용 전 설치할 패키지
Flask를 사용하기 위해 패키지 설치가 필요하다.
$ pip3 install flask
$ pip3 install flask_cors
flask_cors는 브라우저의 CORS 정책을 우회(?)하기 위하여 사용한다. 크롬으로 화면을 띄워 API를 통해 정보를 던져주면 CORS 정책에 의해 에러가 발생한다. 에러가 발생하게 하지 않기 위해 접근 권한을 풀어줄 이유로 사용한다.
Flask를 사용하여 RESTful API 구축하기
화면단에서 두개의 input
을 파라미터로 넘겨 Flask를 통해 넘겨 받은 값의 일치여부를 판단한 뒤 return
한 값을 다시 화면으로 가져오는 과정이다.
우선 API를 구축하기 위해 모듈을 import
해준다.
from flask import Flask, request
from flask_cors import CORS
Flask 사용을 위해 다음을 추가한다.
app = Flask(__name__)
CORS 모듈을 사용하여 접근권한을 설정한다. 모든 url 패턴을 허용한다.
CORS(app, resources={r'*': {'origins': '*'}})
그리고 모든 IP 대역폭을 허용해주어야 한다. 이 코드는 맨 마지막에 들어가야 한다.
if __name__ == "__main__":
app.run(host="0.0.0.0")
첫번째로 "/"
로 접속할 경우(서버 주소만 입력하여 접속하는 경우)에 해당하는 API이다.
@app.route("/")
def hello_world():
print("hello!")
return "Hello, world!"
"/"로 접속할 때 hello_world
라는 함수가 실행되며 콘솔에 "hello!"
라고 찍힐 것이고, "Hello, world!"
라는 문자열을 return
할 것이다.
실제로 서버주소:포트번호
만 입력하고 들어갔을 때 브라우저에 바로 보인다.
처리되는 메소드를 따로 입력하지 않았을 때 GET
방식으로 받는 듯하다.. 그래서 POST
방식으로 데이터를 주고받는 경우 method
를 선언해주어야 한다.
@app.route("/login", methods=["POST"])
def login():
user_id = request.args.get("userId")
user_pw = request.args.get("userPw")
print(user_id)
print(user_pw)
if user_id == "admin" and user_pw == "1q2w3e4r":
return "success"
else:
return "false"
보통 Spring Boot로 REST API를 만들게 되면 화면단에서 던져주는 값을 함수의 파라미터로 받도록 하지만, Flask에서는 좀 다르다.
"/login"
으로 접속하는 API를 사용하기 위해 다음과 같이 화면을 구성하였다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<title>Document</title>
</head>
<body>
<input type="text" placeholder="아이디" id="userId" />
<input type="password" placeholder="비밀번호" id="userPw" />
<button type="button" id="loginBtn">로그인</button>
<script>
const loginBtn = document.getElementById("loginBtn");
loginBtn.addEventListener("click", () => {
const userIdVal = document.getElementById("userId").value;
const userPwVal = document.getElementById("userPw").value;
axios({
method: "POST",
url: "http://192.168.0.29:5000/login",
params: {
userId: userIdVal,
userPw: userPwVal,
},
header: {
"Content-Type": "application/json",
}
}).then((res) => {
if (res.data === "success") {
alert(`로그인에 성공하였습니다.`)
} else {
alert(`로그인에 실패하였습니다.`)
}
})
.catch((err) => {
console.log(err)
})
})
</script>
</body>
</html>
로그인 버튼을 클릭했을 때 클릭 이벤트 리스너에 등록된 함수가 실행된다.
두개 input
의 값을 params
로 던져주는데 분명 Flask에서는 인자로 받는 값이 없음에도 해당 로직은 작동한다.
"/login"
API를 다시 살펴보면
@app.route("/login", methods=["POST"])
def login():
user_id = request.args.get("userId")
user_pw = request.args.get("userPw")
print(user_id)
print(user_pw)
if user_id == "admin" and user_pw == "1q2w3e4r":
return "success"
else:
return "false"
Flask 모듈로부터 함께 import
했던 request
를 사용하고 있다. request
를 통해 화면단에서 던져준 객체의 key
값으로 데이터에 접근한다.
콘솔에 찍어보면 값이 잘 넘어옴을 알 수 있다.
두개의 넘겨받은 input을 변수에 저장하고 값을 비교했을 때 조건과 일치하면 "success"
를 반환하고, 그렇지 않으면 "false"
를 반환한다.
해당 값은 비동기 처리 후 성공여부(then
메소드)를 통해 넘어온 값에서 data
에 해당하는 값을 조회하여 로그인 성공/실패 여부를 가려주게 된다.