Flask API 서버에서 브라우저로 반환되는 응답이 깨져서 하루 종일 원인을 찾아 헤맸습니다. 흥미롭게도 다른 엔드포인트들은 잘 작동하는데, 새로 추가한 이 라우트만 문제가 있었습니다. 이 문제를 해결하면서 알게 된 내용을 정리해 봅니다.
원인 파악하기
이 문제를 일으키는 주요 원인이 세 가지 있다는 것을 알게 되었습니다.
- Content-Type - charset이 UTF-8로 설정되지 않았거나, JSON으로 인식조차 되지 않는 경우
- Content-Encoding - JSON에 대한 브라우저의 기본 자동 압축이 API의 인코딩 방식과 충돌하는 경우
확인하는 두 가지 방법
cURL
터미널을 열고 cURL을 사용하세요
curl -v "https://yourdomain.com/endpoint?"JSON이 올바르게 표시된다면, 문제를 일으키는 것은 대부분 브라우저일 가능성이 높습니다.
깨져서 표시된다면, Flask 앱에서 charset이 UTF-8로 설정되어 있는지 확인하세요. 이는 전송 과정의 문제가 아니라 근본적으로 Flask 내부에서 제대로 처리되지 않았다는 뜻이며, 객체 타입이나 인코딩 문제일 수 있습니다.
브라우저의 개발자 도구
- Network 탭으로 이동해 엔드포인트 페이지를 새로고침하세요
- Content-Type이 ‘application/json; charset=UTF-8’인지 확인하세요
해결 방법
Content-Type
application/json 또는 charset=UTF-8 중 하나라도 빠져 있다면, Flask API 앱의 해당 엔드포인트에 다음 response.header를 추가하세요:
response.headers['Content-Type'] = 'application/json; charset=UTF-8'이제 앱을 재시작하고 다시 시도해서 작동하는지 확인하세요. 그래도 안 된다면 다음 단계로 넘어가세요.
Content-Encoding
이제 Content-Type이 문제가 아니라는 것을 확인했습니다. application/json; charset=UTF-8로 올바르게 표시되니까요. 두 번째 원인인 인코딩 오류로 넘어가 봅시다.
기본적으로 Flask API가 브라우저로 응답을 보낼 때 콘텐츠를 자동으로 압축합니다. 그러면 브라우저가 이를 디코딩하려고 시도합니다. 하지만 어떤 이유에서인지 제대로 디코딩하지 못합니다.
완벽한 예시가 바로 cURL -v에서는 올바른 응답을 받지만 브라우저에서는 깨지는 경우입니다. (제 경우가 바로 이랬습니다.) cURL은 기본적으로 압축되거나 인코딩된 응답을 받지 않기 때문에 cURL에서는 작동하고 브라우저에서는 작동하지 않는 것입니다.
이를 해결하려면 Flask API 앱 응답에 다음을 추가해야 합니다:
response.headers['Content-Encoding'] = 'identity'이렇게 하면 기본적으로 압축이 비활성화되어, 브라우저도 cURL이 받는 것과 동일한 응답을 받을 수 있습니다.
이렇게 하면 해결될 것입니다.
행운을 빕니다.