네이버 블로그 API가 내려주는 JSON, 표준 파서가 실패하는 이유
네이버 블로그에 자동 발행한 글의 URL을 사람이 알려주지 않아도 찾아내려고, 로그인 없이 열리는 공개 API를 curl로 두드렸다. JSON이 온다고 되어 있길래 그대로 JSON.parse()에 넣었는데 바로 에러가 났다.
에러 재현
curl -s "https://blog.naver.com/PostTitleListAsync.naver?blogId=ms_sh0728¤tPage=1&countPerPage=5"
이 응답을 그대로 파싱해봤다.
JSON.parse(rawText);
// Uncaught SyntaxError: Bad escaped character in JSON at position 2937 (line 1 column 2938)
position 2937 근처를 직접 열어봤다.
...\'blog2_paginate\'> <strong c...
...\'blind\'>페이지 이동하기</strong>...
...\'page pcol3 _goPageTop _param(1...
응답 문자열 안에 페이지네이션 HTML 조각(pagingHtml 같은 필드)이 그대로 들어 있고, 그 HTML 안의 홑따옴표(')마다 백슬래시가 붙어 \'로 이스케이프돼 있었다.
왜 표준 파서가 이걸 거부하나
JSON 표준(RFC 8259)이 문자열 안에서 허용하는 이스케이프 시퀀스는 정해져 있다.
\" \\ \/ \b \f \n \r \t \uXXXX
\'(백슬래시+홑따옴표)는 이 목록에 없다. 자바스크립트 문자열 리터럴에서는 \'가 그냥 홑따옴표를 의미하는 흔한 표기지만, JSON 문자열에서는 정의되지 않은 이스케이프라 표준을 따르는 파서는 이 지점에서 그대로 문법 오류를 낸다. 네이버 쪽 서버 템플릿이 HTML 조각을 만들 때 JSON 이스케이프 규칙이 아니라 자바스크립트 문자열 관습을 따른 것으로 보인다 — HTML 자체는 브라우저에서 eval 되듯 쓰이는 게 아니라 JSON 필드 값으로 통째로 내려오니, 이 지점에서 두 표준이 부딫힌다.
고친 방법 — 파싱 전에 걷어낸다
\'를 표준 이스케이프인 홑따옴표 그 자체로 되돌리면 된다.
const text = (await res.text()).replace(/\\'/g, "'");
const json = JSON.parse(text);
실제로 이렇게 고친 뒤 같은 응답을 다시 넣어봤다.
표준 JSON.parse 실패: Bad escaped character in JSON at position 2937
치환 후 JSON.parse 성공
치환 후에는 postList, logNo, title, addDate 같은 실제 데이터 필드가 정상적으로 파싱됐다. 이 응답에서는 HTML 조각 밖의 실제 데이터 값에 홑따옴표가 등장하지 않아서, 전체 문자열에 대해 \' → ' 치환을 걸어도 다른 필드가 깨지지 않았다.
왜 이런 문제를 사람이 먼저 발견하기 어려운가
이 API를 브라우저에서 쓰는 페이지는 응답을 JSON.parse가 아니라 eval이나 jQuery.parseJSON처럼 좀 더 관대한 방식으로 처리했을 가능성이 있다. 그런 환경에서는 \'가 조용히 통과되니 네이버 쪽에서도 이 문제가 드러나지 않았을 것이다. 표준을 엄격히 지키는 JSON.parse()를 그대로 붙였을 때만 이 균열이 드러난다 — 서버가 “JSON을 준다”고 문서화했어도, 실제로 표준 JSON인지는 파서에 직접 넣어봐야 확인된다.
정리
| 결과 | |
|---|---|
원본 응답을 JSON.parse() | ❌ Bad escaped character in JSON |
| 원인 | 응답 안 HTML 조각의 \' 이스케이프(JSON 표준에 없는 시퀀스) |
| 해결 | .replace(/\\'/g, "'")로 파싱 전에 치환 |
| 치환 후 파싱 | ✅ 성공 |
“JSON을 준다”는 API 문서나 필드명(pagingHtml)만 보고 표준 JSON.parse()가 항상 통할 거라고 가정하면 안 된다. 에러 메시지가 알려주는 위치를 직접 열어보는 게 가장 빠른 진단이었다.
자주 묻는 질문
왜 네이버 API 응답에 HTML이 JSON 문자열 값 안에 들어있나요?
PostTitleListAsync.naver는 블로그 페이지에서 쓰는 페이지네이션 UI(pagingHtml) 조각을 JSON 필드 값으로 그대로 내려줍니다. 그 HTML을 만드는 쪽(서버 템플릿)이 문자열 안의 홑따옴표를 이스케이프할 때 JSON 표준이 아니라 자바스크립트 문자열 리터럴 관습(\')을 따른 것으로 보입니다.
이 문제는 이 API에만 있나요?
직접 확인한 건 이 API 하나입니다. 다만 서버 템플릿에서 HTML 조각을 JSON 필드에 그대로 끼워 넣는 구조라면 같은 문제가 생길 여지가 있습니다. JSON.parse가 'Bad escaped character'로 실패하면, 응답 원문에서 그 에러 위치 근처를 직접 눈으로 봐야 원인이 잡힙니다.
정규식으로 치환하는 게 안전한가요?
이 응답에서는 안전했습니다 — HTML 조각 밖의 실제 데이터(제목, 날짜 등)에는 원래 홑따옴표에 이스케이프가 붙을 일이 없어서, `\'`를 전부 `'`로 바꿔도 다른 값이 깨지지 않았습니다. 다만 이건 이 API 응답의 구조를 직접 확인하고 내린 판단이라, 다른 API에 그대로 적용하기 전에는 응답 구조를 먼저 봐야 합니다.