기술블로그
✅ Flask에서 JSON 응답 순서 보장하기 (OrderedDict 활용)
Chansman
2025. 4. 18. 13:34
Flask에서 JSON 응답 순서 보장하기 (OrderedDict 활용)
문제 상황
Flask에서 jsonify를 사용하여 JSON 데이터를 반환할 때, 서버 측에서 데이터의 순서를 지정해도 JSON 응답을 받았을 때 순서가 뒤바뀌는 문제가 발생할 수 있습니다. JSON은 객체의 순서를 보장하지 않기 때문에, 브라우저나 서버에서 순서대로 데이터를 반환하지 않는 문제가 생깁니다.
이 문제를 해결하기 위해, **OrderedDict**와 **json.dumps()**를 사용하여 순서 보장을 명시적으로 설정할 수 있습니다.
1. 전체 코드 흐름
목표: Flask에서 JSON 데이터를 반환할 때, result가 먼저 오고 그 뒤에 data가 오도록 순서를 보장합니다.
from flask import Flask, jsonify
from collections import OrderedDict
import json
app = Flask(__name__)
@app.route('/api/v1/feeds', methods=['GET'])
def show_all_feeds():
# 순서대로 데이터 설정
data = OrderedDict([
('result', 'success'),
('data', OrderedDict([
('feed1', 'data1'),
('feed2', 'data2')
]))
])
# JSON으로 변환하여 반환
response = app.response_class(
response=json.dumps(data, ensure_ascii=False, sort_keys=False),
status=200,
mimetype='application/json'
)
return response
if __name__ == '__main__':
app.run(debug=True)
2. 코드 설명 및 수정된 부분
a. OrderedDict 사용
- 목적: Python의 기본 dict는 삽입 순서를 보장하지 않지만, OrderedDict는 데이터를 삽입한 순서대로 반환합니다. 이를 사용하여 서버에서 데이터를 반환할 때 순서를 명확히 설정할 수 있습니다.
- 수정된 코드: 데이터는 **OrderedDict**에 저장되고, **result**가 먼저 나오도록 설정됩니다. OrderedDict는 파이썬 딕셔너리와 동일하게 작동하지만 순서가 보장된다는 특징이 있습니다.
data = OrderedDict([
('result', 'success'),
('data', OrderedDict([
('feed1', 'data1'),
('feed2', 'data2')
]))
])
- 여기서 ('data', OrderedDict([ ... ])) 부분은 Python의 딕셔너리 형식으로 **'data'**라는 키와 그 값을 연결하고 있습니다.
- Python에서 **OrderedDict([('data', {...})])**와 같이 데이터를 정의할 때, 실제로 **콜론(:)**을 사용하여 **'data': {}**와 같이 키와 값을 구분합니다. 하지만, JSON으로 변환할 때 이 데이터가 **data:**와 같은 형태로 나타나는데, 이는 JSON 문법에 맞는 형식이기 때문입니다.
- 왜 두 번 사용하나요?
- 첫 번째 OrderedDict:
- result와 data는 최상위 레벨의 키-값 쌍입니다. result는 단순한 문자열 값을, data는 또 다른 딕셔너리로 묶어주고 있습니다. 여기서 **data**는 **OrderedDict**로 묶어서 중첩된 데이터를 보관합니다.
- 두 번째 OrderedDict:
- data는 또 다른 중첩된 딕셔너리로, **feed1**과 **feed2**라는 항목을 가지고 있으며, 각각의 값은 "data1"과 "data2"입니다.
- 이 내부에서 또 OrderedDict를 사용한 이유는 순서를 보장하면서 두 개의 항목을 저장하기 위함입니다. 순서가 중요하다면 중첩된 항목들도 순서대로 반환되어야 하기 때문에 OrderedDict를 사용합니다.
- 첫 번째 OrderedDict:
b. json.dumps() 사용
- 목적: jsonify()는 기본적으로 키 정렬을 활성화시키기 때문에, 순서가 변경될 수 있습니다. 이 문제를 해결하기 위해, json.dumps()에서 sort_keys=False 옵션을 사용하여 키 정렬을 비활성화합니다.
- 수정된 코드: json.dumps()는 sort_keys=False로 설정되어 JSON 응답의 키 정렬을 방지하고, 입력된 순서대로 반환합니다.
response = app.response_class(
response=json.dumps(data, ensure_ascii=False, sort_keys=False),
status=200,
mimetype='application/json'
)
c. ensure_ascii=False 설정
- 목적: ensure_ascii=False는 JSON 데이터에 한글 등의 비 ASCII 문자가 포함될 때, 그 문자가 유니코드로 출력되는 것을 방지하고 원본 그대로 출력하도록 합니다.
- 수정된 코드: json.dumps()에서 ensure_ascii=False를 설정하여 한글이나 다른 비 ASCII 문자가 제대로 출력되도록 합니다.
response=json.dumps(data, ensure_ascii=False, sort_keys=False)
3. 결과 및 예상되는 응답
JSON 응답 예시
이 코드를 실행한 후 http://127.0.0.1:5000/api/v1/feeds URL에 접근하면, 아래와 같은 JSON 응답을 받을 수 있습니다:
{
"result": "success",
"data": {
"feed1": "data1",
"feed2": "data2"
}
}
설명:
- **result**가 먼저 오고 그 뒤에 **data**가 나오는 순서대로 JSON 응답이 반환됩니다.
- feed1과 feed2는 data 객체 안에 들어가며, 데이터의 순서가 정확히 유지됩니다.
4. 흐름별 설명
- Flask 애플리케이션 설정: Flask 애플리케이션을 설정하고, /api/v1/feeds 경로에 대한 GET 요청을 처리하는 엔드포인트를 만듭니다.
- 데이터 순서 설정: OrderedDict를 사용하여 **result**와 data 순서를 명시적으로 설정합니다. 데이터가 삽입된 순서대로 JSON 객체를 만들 수 있습니다.
- JSON 직렬화: json.dumps()로 데이터를 직렬화하여 JSON 형식으로 반환합니다. sort_keys=False를 사용하여 정렬되지 않은 순서대로 반환되도록 합니다.
- 응답 반환: jsonify() 대신 json.dumps()로 변환된 데이터를 반환합니다. 이를 통해 순서를 보장하면서 JSON 데이터를 클라이언트에 반환합니다.
5. 결론
- OrderedDict를 사용하여 데이터를 순서대로 처리하고, json.dumps(sort_keys=False)를 사용하여 JSON 응답에서 순서가 변경되지 않도록 할 수 있습니다.
- Flask에서 JSON 순서 보장 문제를 해결하기 위해 jsonify() 대신 json.dumps()를 사용한 방법입니다.