발단:
app.py에서 return jsonify(”쌩 메세지”)로 보내고, 프론트에서 success: function(response) { alert(response) } 해도 alert(response[’msg’]) 때와 똑같은 형식으로 잘 뜨는 것을 발견했다. 이유가 궁금했다.
- response를 jsonify로 안 보내면 어떻게 되지?
⇒ jsonify()로 안 보내도 된다. 이 포스트에 연구해놓았다.
- response를 jsonify로 잘 보내도, ‘키’값이 없는데 어떤식으로 저장돼서 보내지고 출력되는 거지?
⇒ 결론부터 말하면, jsonify()는 위치 인자를 그냥 나열하는 것(
jsonify(”메세지1”, “메세지2”, …)
)과 키워드 인자쌍을 주는 방식(jsonify({”msg”: “메세지1”, “msg2”: “메세지2”})
) 두 가지를 모두 소화한다. 반환하는 객체는flask.wrappers.Response
.
실험:
서버에서 jsonify를 여러 방식으로 주고:
@app.route("/api/comments", methods=["POST"])
def post_comment():
...
resp = jsonify("Comment added successfully!", msg2="Another message~")
# resp = jsonify({'msg': "Comment added successfully!", 'msg2':"Another message~"})
# resp = jsonify(msg="Comment added successfully!", msg2="Another message~")
return resp
프론트에선 콘솔에 한번, alert 창으로 한 번 응답을 찍어 보았다:
function save_comment() {
...
$.ajax({
type: 'POST',
url: '/api/comments',
data: {...},
success: function (response) {
console.log(response, typeof(response))
alert(response)
}
})
}
결과:
서버에서: return jsonify(’메세지’) ⇒ 프론트 콘솔에서: 메세지, 타입은 string ⇒ 프론트 alert에서: 메세지
서버에서: return jsonify(’메세지1’, ‘메세지2’) ⇒ 프론트 콘솔에서: ['Comment added successfully!', 'Another message~'], 타입은 'object’ ⇒ 프론트 alert에서: Comment added successfully!,Another message~
서버에서: return jsonify({’msg’: ‘메세지’}) ⇒ 프론트 콘솔에서: {msg: '메세지'}, 타입은 'object’ ⇒ 프론트 alert에서: [object Object]
서버에서: return jsonify({’msg’: ‘메세지’, ‘msg2’: ‘메세지2’}) ⇒ 프론트 콘솔에서: {msg: 'Comment added successfully!', msg2: 'Another message~'}, 타입은 'object’ ⇒ 프론트 alert에서: [object Object]
jsonify()
flask.json def jsonify(*args: Any, **kwargs: Any) -> Response
positional arguments나 keyword arguments 둘 중 한 쪽만 제공해야 한다.
*args가 여러개 주어지면 list로 취급되고, **kwargs가 주어지면 딕셔너리로 취급된다. (파이썬 *args는 튜플로 취급되는 거 아녔어??) (아마 list로 ‘반환한다’는 얘기 같다. 이걸 자바스크립트쪽에서 받으면 배열이 되겠지)
반환값은 flask.wrappers.Response
객체. HTML mimetype (application/json mimetype.)이 함께 주어진다는 점이 Werkzeug의 response 객체와 다르다는데… mimetype이란?
MIME type
: Multipurpose Internet Mail Extensions.
: Media type.
: 즉 문서나 파일, 바이트모음의 본질과 형식을 일컬어주는 말. IETF's RFC 6838에 정의되어 있다고 한다.
예를 들어 HTML형태의 파일을 위해선 ‘text/html’타입을 지정해주고, jpeg형태의 파일을 위해서는 ‘image/jpeg’타입으로 지정해준다. 그러면 웹 브라우저가 웹 서버 쪽에서 HTTP로 보내온 파일을 어떤 식으로 출력해야할지 알 수 있게 된다.
‘application/json’은 JSON 형식을 특정하는 MIME type이다. 즉 jsonify가 반환하는 값은 flask의 response객체인데, ‘날 해석할 방법은 JSON이다’라는 MIME 타입 정보를 함께 실어 보낸다는 뜻이 되겠다.
결국 프론트에서 받는 response는:
*args에 인수 하나만 넣어 넘겨주면 jsonify된 결과는 순수 string타입이다.
*args에 인수 둘 이상을 넣어주면 jsonify된 결과는 ‘object’, 즉 파이썬 리스트에서 js 배열로 전달되는 듯 하다.
**kwargs에 키=값 형태로 넣어주면 ({’키’: ‘값’}의 형태도 괜찮음) jsonify된 결과는 ‘object’, 즉 파이썬 딕셔너리에서 js 객체 혹은 JSON객체로 전달되는 듯 하다.
결론:
즉 1. *args에 위치 인자들로 데이터를 넣어주는 방식을 쓰든지 :
// app.py
@app.route("/api/comments", methods=["POST"])
def post_comment():
...
return jsonify("Comment added successfully!", "Another message~")
// index.html
$.ajax({
type: 'POST',
url: '/api/comments',
...
success: function (response) {
alert(response[1]) // Another message~
}
})
- **kwargs에 키워드 인자들로 데이터를 넣어주는 방식을 쓰든지 :
// app.py
@app.route("/api/comments", methods=["POST"])
def post_comment():
...
// return jsonify(msg="Comment added successfully!", msg2="Another message~")
return jsonify({'msg': "Comment added successfully!", 'msg2':"Another message~"})
// 위아래 둘 다 가능.
// index.html
$.ajax({
type: 'POST',
url: '/api/comments',
...
success: function (response) {
alert(response['msg2']) // Another message~
}
})
둘 중 한 가지를 사용하면 되겠다.
+
*args 인수와 **kwargs 인수를 모두 줘봤다:
TypeError: app.json.response() takes either args or kwargs, not both 127.0.0.1 - - [28/Nov/2022 13:07:20] "POST /api/comments HTTP/1.1" 500 -
에러남. 예상되는 그대로의 메세지를 던진다.
Uploaded by N2T