ERROR - Updated 2026-05-14

API 응답이 JSON이 아니라 HTML일 때

API 응답이 JSON이 아니라 HTML로 내려와 JSON 파싱이 실패할 때 status code, Content-Type, 인증, 라우팅을 확인하는 순서.

Open JSON Error Doctor

API 응답이 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 HTMLRequest URL 확인
인증 만료로그인 HTML쿠키, 토큰, redirect 확인
서버 내부 오류500 HTML서버 로그 확인
프록시 설정 오류프론트엔드 HTMLproxy/rewrite 설정 확인
Content negotiation 문제HTML 에러 페이지Accept, Content-Type 확인

바로 해결 방법

  1. Network 탭에서 요청을 클릭합니다.
  2. Request URL과 method가 의도한 API와 맞는지 확인합니다.
  3. status code와 Content-Type을 봅니다.
  4. Response 탭에서 본문 첫 200자를 확인합니다.
  5. 인증 헤더, 쿠키, 리다이렉트, 프록시 설정을 확인합니다.
  6. 서버가 오류 응답도 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인지 확인하고 파싱 오류 위치를 볼 수 있습니다.

관련 글

업데이트 날짜

2026-05-14