ERROR - Updated 2026-05-14
API 응답이 JSON이 아니라 HTML일 때
API 응답이 JSON이 아니라 HTML로 내려와 JSON 파싱이 실패할 때 status code, Content-Type, 인증, 라우팅을 확인하는 순서.
Open JSON Error DoctorAPI 응답이 JSON이 아니라 HTML이면 response.json()이나 JSON.parse() 단계에서 실패합니다. 대표적으로 Unexpected token < in JSON at position 0 오류가 나며, 실제 응답은 404 페이지, 로그인 페이지, 서버 오류 페이지, 프론트엔드 HTML일 수 있습니다. 이때는 JSON 문법을 고치기보다 status code, Content-Type, Request URL, 인증 상태를 먼저 확인해야 합니다.
증상
- API 호출 후 JSON 파싱에서 오류가 납니다.
- 응답 본문이
{나[가 아니라<html>또는<!doctype html>로 시작합니다. - 서버는 200을 반환하지만 본문은 로그인 페이지입니다.
- 개발 환경에서는 되지만 배포 환경에서만 HTML이 내려옵니다.
원인
API가 JSON을 내려주지 않는 이유는 여러 가지입니다. 특히 프론트엔드 라우팅과 API 라우팅이 섞인 프로젝트에서는 잘못된 경로가 index.html로 fallback될 수 있습니다.
| 원인 | 흔한 신호 | 대응 |
|---|---|---|
| API 경로 오타 | 404 HTML | Request URL 확인 |
| 인증 만료 | 로그인 HTML | 쿠키, 토큰, redirect 확인 |
| 서버 내부 오류 | 500 HTML | 서버 로그 확인 |
| 프록시 설정 오류 | 프론트엔드 HTML | proxy/rewrite 설정 확인 |
| Content negotiation 문제 | HTML 에러 페이지 | Accept, Content-Type 확인 |
바로 해결 방법
- Network 탭에서 요청을 클릭합니다.
- Request URL과 method가 의도한 API와 맞는지 확인합니다.
- status code와 Content-Type을 봅니다.
- Response 탭에서 본문 첫 200자를 확인합니다.
- 인증 헤더, 쿠키, 리다이렉트, 프록시 설정을 확인합니다.
- 서버가 오류 응답도 JSON으로 내려주도록 일관성을 맞춥니다.
FixData 도구로 확인하기
JSON Error Doctor에 응답 본문을 붙여넣으면 JSON으로 파싱 가능한지 바로 확인할 수 있습니다. HTML 본문을 넣으면 JSON 문법 오류가 아니라 응답 형식 문제라는 점을 빠르게 볼 수 있습니다.
JSON처럼 보여도 실제 Content-Type이 text/html일 수 있으므로, 도구 확인과 함께 Network 탭의 헤더를 같이 확인하는 것이 좋습니다.
수동 해결 방법
JSON 파싱 전에 Content-Type 확인
클라이언트에서 응답 타입을 먼저 확인하면 원인을 더 빨리 로그로 남길 수 있습니다.
const response = await fetch("/api/report");
const contentType = response.headers.get("content-type") ?? "";
if (!contentType.includes("application/json")) {
const text = await response.text();
throw new Error(`Expected JSON, got ${contentType}: ${text.slice(0, 120)}`);
}
const data = await response.json();
서버 오류도 JSON으로 반환하기
API 서버는 성공 응답뿐 아니라 오류 응답도 가능한 한 JSON으로 맞추는 것이 좋습니다.
{
"error": {
"code": "UNAUTHORIZED",
"message": "Login required"
}
}
이렇게 하면 클라이언트가 HTML 파싱 오류 대신 실제 원인을 보여줄 수 있습니다.
배포 환경의 rewrite 확인
로컬에서는 /api/report가 백엔드로 가지만 배포에서는 프론트엔드 앱으로 라우팅될 수 있습니다. Vercel, Nginx, Cloudflare, 개발 서버 proxy 설정을 함께 확인하세요.
예제
실패 응답:
<html>
<body>Please log in</body>
</html>
클라이언트 오류:
Unexpected token < in JSON at position 0
이 경우 해결은 JSON 수정이 아니라 인증 만료 처리, API 오류 응답 형식, 로그인 리다이렉트 정책을 점검하는 것입니다.
자주 하는 실수
- HTTP status가 200이면 반드시 JSON일 것이라고 생각합니다.
- Content-Type을 확인하지 않고 바로
response.json()을 호출합니다. - 로그인 페이지 리다이렉트를 API 성공 응답처럼 처리합니다.
- 개발 서버 proxy와 배포 rewrite가 다르다는 점을 놓칩니다.
관련 도구
- JSON Error Doctor: 실제 응답 본문이 JSON인지 확인하고 파싱 오류 위치를 볼 수 있습니다.
관련 글
- JSON / API Error Center
- Unexpected token < in JSON at position 0
- JSON Unexpected token 오류
- JSON unexpected end of input
- API 디버깅에서 JSON 오류를 확인하는 순서
업데이트 날짜
2026-05-14