네이버 블로그 API가 내려주는 JSON, 표준 파서가 실패하는 이유

·

네이버 블로그에 자동 발행한 글의 URL을 사람이 알려주지 않아도 찾아내려고, 로그인 없이 열리는 공개 API를 curl로 두드렸다. JSON이 온다고 되어 있길래 그대로 JSON.parse()에 넣었는데 바로 에러가 났다.

에러 재현

curl -s "https://blog.naver.com/PostTitleListAsync.naver?blogId=ms_sh0728&currentPage=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에 그대로 적용하기 전에는 응답 구조를 먼저 봐야 합니다.

#JSON#네이버#API#파싱#Node.js