JAY Project
JAY Project

JSON이 깨졌다는데 어디가 문제일까? — 파서가 잡아주는 실수와 조용히 넘어가는 실수

2026-09-01| Jay

설정 파일을 고쳤더니 앱이 뜨지 않습니다. API 응답을 붙여넣었더니 "유효하지 않은 JSON"이라고 합니다. 눈으로는 멀쩡해 보이는데 말이죠.

JSON은 문법이 아주 좁습니다. 자바스크립트에서는 되는 것들이 JSON에서는 대부분 안 됩니다. 이 글은 실제로 12가지 케이스를 파서에 넣어보고, 무엇이 걸리고 무엇이 그냥 통과하는지를 정리한 것입니다.

1. JSON은 자바스크립트가 아니다

가장 많이 겪는 세 가지부터 보겠습니다. 셋 다 자바스크립트에서는 아무 문제가 없습니다.

쓴 것 JS JSON
{"a": 1,} (후행 쉼표)
{'a': 1} (작은따옴표)
{"a": 1} // 메모 (주석)

후행 쉼표가 특히 흔합니다. 목록에서 마지막 항목을 지웠는데 쉼표만 남는 경우죠. 작은따옴표는 코드에서 복사해 올 때 딸려옵니다. 주석은 설정 파일에 설명을 남기려다 넣게 됩니다.

키도 반드시 큰따옴표로 감싸야 합니다. {a: 1}은 JS 객체 리터럴이지 JSON이 아닙니다.

주석을 꼭 쓰고 싶다면 JSON5나 JSONC라는 확장 규격이 있습니다. 다만 tsconfig.json처럼 특정 도구가 지원하는 것이지 표준 JSON은 아닙니다. 표준만 받는 곳에 넣으면 그대로 에러가 납니다.

2. 에러 메시지에 위치가 나오는 경우와 아닌 경우

파서가 내는 메시지는 두 종류로 갈립니다. 실제로 돌려본 결과입니다.

위치를 알려주는 쪽

입력 메시지
{"a":1,} Expected double-quoted property name ... (line 1 column 8)
{'a':1} Expected property name or '}' ... (line 1 column 2)
{"a":01} Unexpected number ... (line 1 column 7)

위치를 알려주지 않는 쪽

입력 메시지
{"a":NaN} Unexpected token 'N' ... is not valid JSON
{"a":.5} Unexpected token '.' ... is not valid JSON

차이는 파서가 어디까지 읽고 포기했는지입니다. 구조를 따라가다 막히면 줄과 칸을 셀 수 있지만, 예상 못 한 토큰을 만나 바로 멈추면 위치 정보 없이 그 글자만 알려줍니다.

그래서 line 1 column 8 같은 표시가 나오면 거의 그 자리입니다. 반대로 위치 없이 Unexpected token 'N'만 나오면 문서 전체에서 N으로 시작하는 값을 찾아야 합니다. 십중팔구 NaN입니다.

3. 🔴 딱 하나, 중복 키만 조용히 통과한다

여기가 이 글에서 가장 중요한 부분입니다. 12가지 케이스 중 11개는 에러로 걸렸는데, 단 하나만 아무 말 없이 통과했습니다.

{"a": 1, "a": 2}   →   {"a": 2}

에러도 경고도 없습니다. 그냥 뒤에 온 값이 이깁니다. 앞의 1은 사라집니다.

JSON 표준은 키 중복을 "권장하지 않는다"고만 하고 금지하지 않습니다. 그래서 대부분의 파서가 마지막 값을 채택하고 넘어갑니다.

이게 왜 위험하냐면, 설정 파일에서 가장 사고가 나기 쉬운 형태이기 때문입니다.

  • 설정을 고치면서 기존 줄을 지우지 않고 아래에 새로 추가했다 → 아래 값이 적용됩니다
  • 반대로 위에 추가했다 → 바꾼 값이 무시되고 옛날 값이 그대로 적용됩니다
  • 두 설정 파일을 합치다가 같은 키가 겹쳤다 → 한쪽이 통째로 묻힙니다

에러가 안 나니까 "문법은 맞는데 왜 반영이 안 되지?"로 한참 헤매게 됩니다. 파일을 고쳤는데 동작이 그대로라면 같은 키가 두 번 있는지 먼저 확인해보세요.

4. 숫자에서 걸리는 것들

숫자는 JS와 JSON의 차이가 특히 큽니다.

입력 결과 이유
NaN JSON에 없는 값
Infinity 마찬가지
01 선행 0 금지
.5 소수점 앞 0 필수 (0.5)

NaNInfinity가 자주 문제가 됩니다. 계산 결과를 그대로 직렬화할 때 나오는데, 표준 JSON에는 이 값을 표현할 방법이 아예 없습니다. 그래서 보통 null로 바꿔서 내보냅니다.

숫자 이야기가 나온 김에 하나 더. 아주 큰 정수는 문법은 통과하지만 값이 바뀔 수 있습니다. 자바스크립트 숫자는 안전하게 다룰 수 있는 정수 범위가 약 9007조까지라, 그보다 큰 ID를 숫자로 받으면 끝자리가 달라집니다. 그래서 긴 ID는 문자열로 주고받는 API가 많습니다.

5. 눈에 보이지 않는 것들

문서를 아무리 들여다봐도 안 보이는 원인도 있습니다.

BOM(Byte Order Mark) — 파일 맨 앞에 붙는 보이지 않는 표식입니다. 윈도우 메모장이나 엑셀 내보내기에서 잘 붙습니다. 화면에는 아무것도 안 보이는데 파서는 Unexpected token을 냅니다. 첫 글자 앞에서 에러가 난다면 이걸 의심해보세요.

백슬래시 — 윈도우 경로를 그대로 넣으면 문제가 됩니다. "C:\Users"\U를 이스케이프로 해석하려다 실패합니다. "C:\\Users"처럼 두 번 써야 합니다. 그리고 JSON이 아는 이스케이프는 \" \\ \/ \b \f \n \r \t \uXXXX 뿐이라, \x41 같은 건 Bad escaped character가 됩니다.

줄바꿈 — 문자열 안에서 엔터를 치면 안 됩니다. \n으로 써야 합니다.

6. 그래서 어떻게 확인하나

  • 에러 메시지의 line·column을 먼저 보세요. 위치가 나오면 대개 그 자리이거나 바로 앞입니다.
  • 위치가 없으면 값 쪽을 의심하세요. NaN, Infinity, 따옴표 없는 값이 후보입니다.
  • 문법이 맞는데 동작이 이상하면 중복 키를 찾으세요. 파서는 이걸 잡아주지 않습니다.
  • 정렬해서 보세요. 한 줄로 압축된 JSON은 사람이 괄호 짝을 셀 수 없습니다. 들여쓰기만 넣어도 빠진 괄호가 눈에 들어옵니다.
  • 배포 전에 설정 파일을 검증하세요. package.json이나 tsconfig.json은 깨진 채로 커밋되면 빌드가 통째로 멈춥니다.

붙여넣고 바로 확인하고 싶다면 JSON 포맷터를 써보세요. 2칸·4칸 들여쓰기와 한 줄 압축을 오갈 수 있고, 문법 오류가 있으면 줄과 칸을 알려줍니다. 접었다 펼 수 있는 트리 뷰도 있어서 깊게 중첩된 구조를 볼 때 편합니다. 브라우저 안에서만 처리하므로 붙여넣은 내용이 서버로 가지 않습니다 — 운영 데이터를 확인할 때 중요한 부분입니다.

인코딩이 섞여 깨진 문자열이라면 인코더·디코더가, 두 응답의 차이를 찾아야 한다면 텍스트 비교가 같은 계열의 도구입니다.

정리

  • JSON은 자바스크립트가 아닙니다 — 후행 쉼표·작은따옴표·주석이 가장 흔한 세 가지 실수입니다
  • 에러 메시지는 위치를 주는 것과 안 주는 것으로 갈립니다. 위치가 없으면 NaN 같은 값을 의심하세요
  • 🔴 중복 키만은 에러가 아닙니다 — 뒤 값이 이기고 앞 값이 조용히 사라집니다. 설정이 반영 안 될 때 가장 먼저 볼 곳입니다
  • NaN·Infinity·01·.5는 전부 문법 위반이고, 아주 큰 정수는 통과하되 값이 바뀔 수 있습니다
  • BOM과 백슬래시는 눈에 안 보이는 원인입니다
🚀 JAY Project · 60+ 무료 웹 도구 모음

취미로 만드는 60+ 무료 웹 도구를 한곳에서. 회원가입 없이 즉시 사용, 입력값은 외부로 전송되지 않습니다.