완벽하게 합리적으로 보이는 JSON 을 작성했는데 —— 모든 키에 따옴표가 있고 모든 값이 유효한데 —— JSON.parse() 가 여전히 SyntaxError 를 던집니다. 범인은 거의 항상 후행 쉼표: 객체나 배열의 마지막 항목 뒤에 앉아 있는 그 여분의 ,. 왜 JSON 이 그것을 금지하는지, 어디서 슬며시 들어오는지, 어떻게 없애는지 설명합니다.
후행 쉼표란?
후행 쉼표("매달린 쉼표" 또는 "최종 쉼표" 라고도 함) 는 목록의 마지막 항목 뒤에 나타나는 쉼표로 —— 닫는 괄호 전에 뒤에 아무것도 따라오지 않는 것입니다.
// 객체의 후행 쉼표
{
"name": "Ada",
"score": 98, // ← 이 쉼표는 다음 항목이 없음
}
// 배열의 후행 쉼표
[1, 2, 3,]
// ^ 같은 문제 위 두 예제는 JSON.parse() 에 넘기면 SyntaxError 를 던집니다.
왜 JSON 은 후행 쉼표를 금지하나?
JSON 문법(RFC 8259 에 정의) 은 쉼표를 요소들 사이의 구분자 로 명시 —— 항상 양쪽에 값이 있어야 합니다. JSON 객체의 형식 규칙은 이렇습니다:
object = "{" [ member *( "," member ) ] "}"
member = string ":" value 쉼표 뒤에는 또 다른 member 가 와야 합니다. 쉼표 뒤에 아무것도 없으면 문법 위반. 이는 의도적인 설계 선택: JSON 은 개발자 편의보다 단순함과 모호하지 않은 파싱을 우선시.
JavaScript 는 다른 길을 갔습니다. ES5(2009) 는 배열 리터럴에서 후행 쉼표를 명시적으로 합법화했고, ES2017 은 이를 함수 매개변수로 확장. JS 의 후행 쉼표는 이제 흔한 스타일 —— 목록에 새 항목을 추가할 때 더 깔끔한 git diff 를 만들어서 많은 linter 가 강제하기도 합니다.
JavaScript 가 허용하는 것과 JSON 이 허용하는 것 사이의 간극이 당신이 보게 될 거의 모든 후행 쉼표 오류의 근원입니다.
후행 쉼표가 어디서 오는가
손으로 편집한 설정 파일
tsconfig.json, package.json, 또는 앱 설정 같은 설정 파일은 사람이 편집합니다. 항목을 추가하거나 제거한 뒤 떠도는 쉼표를 남기기 쉽습니다. 많은 에디터(VS Code, WebStorm) 는 후행 쉼표를 허용하는 JSONC(주석 있는 JSON) 를 조용히 받아들이므로, 파일은 에디터에서 괜찮아 보이지만 런타임에 깨집니다.
// "debug": true 를 지웠는데 쉼표를 안 지움
{
"compilerOptions": {
"strict": true,
"target": "ES2020", // ← 이제 후행이 됨
}
}JavaScript → JSON 직렬화
개발자가 가끔 JavaScript 값을 문자열로 보간하거나 Array.join(',') 로 JSON 문자열을 수동으로 만듭니다. 로직이 모든 항목 뒤에 무조건 쉼표를 추가하면 마지막 항목에 후행 쉼표가 생깁니다.
// ❌ 순진한 수동 직렬화
const parts = items.map(item => `"${item.name}": ${item.value}`);
const json = '{' + parts.join(',') + ',}'; // } 앞에 여분 쉼표
// ✅ JSON.stringify 를 쓰세요 —— 항상 유효한 JSON 생성
const json = JSON.stringify(Object.fromEntries(items.map(i => [i.name, i.value])));LLM 과 AI 출력
"JSON 을 출력하라" 는 요청을 받은 언어 모델은 후행 쉼표를 자주 생성합니다. 모델은 훈련 중 후행 쉼표가 합법인 방대한 양의 JavaScript 코드를 봤기 때문에 패턴을 복제합니다. AI 가 생성한 JSON 은 파싱 전에 항상 검증하거나 수리하세요.
JavaScript 소스에서 복사-붙여넣기
.js 나 .ts 파일에서 객체 리터럴을 복사해 JSON 컨텍스트에 붙여 넣는 것은 후행 쉼표가 나타나는 가장 흔한 경로 중 하나입니다. 소스 코드는 유효한 JavaScript 였고; 목적지는 JSON 만 받아들입니다.
후행 쉼표 찾는 법
오류 메시지는 보통 문제에 가까운 곳을 가리키지만 정확히 쉼표 자체를 가리키진 않습니다 —— 파서는 예상치 못한 } 나 ] 에 부딪혀서야 뭔가 잘못됐다는 걸 알아챕니다:
SyntaxError: Expected double-quoted property name in JSON at position 58
// 또는
SyntaxError: Unexpected token '}', ..."score": 98,}" is not valid JSON보고된 위치에서 거꾸로 작업하세요. 후행 쉼표는 오류를 일으킨 닫는 괄호 바로 앞 문자입니다.
큰 JSON 파일에선 정규식 검색이 도움됩니다:
// 객체/배열의 후행 쉼표 찾기
,\s*[}\]]고치는 법
옵션 1 —— 수동으로 삭제
문제의 객체나 배열에서 마지막 항목을 찾아 뒤의 쉼표를 제 거. 작은 파일엔 이게 가장 빠름.
옵션 2 —— 정규식 치환(주의)
const fixed = raw.replace(/,\s*([}\]])/g, '$1');
JSON.parse(fixed); 흔한 경우엔 동작하지만 깨지기 쉬움: 리터럴 문자로 ,} 나 ,] 를 포함하는 문자열을 손상시킬 수 있습니다. 입력에 그런 문자열이 없다는 것을 알 때만 사용하세요.
옵션 3 —— 제대로 된 수리 파서 사용
수리 파서는 전체 JSON 문법을 이해하고 문자열 내용에 손대지 않으면서 구조적으로 무효한 위치의 후행 쉼표만 제거합니다. 프로덕션 코드나 신뢰할 수 없는 입력엔 가장 안전한 접근.
옵션 4 —— 설정 파일은 JSONC 로 전환
후행 쉼표가 당신이 통제하는 설정 파일에 있다면 JSONC(주석 있는 JSON) 를 지원하는 파서로 전환을 고려하세요. TypeScript 의 tsconfig.json 는 이미 JSONC 를 씁니다. Node.js 설정 파일은 @humanwhocodes/momoa 나 json5 같은 라이브러리가 후행 쉼표와 주석을 허용하는 JSON 상위집합을 파싱합니다.
후행 쉼표가 실제로 허용되는 경우: JSONC 와 JSON5
두 JSON 인접 포맷이 의도적으로 후행 쉼표(그리고 다른 완화) 를 허용합니다. 알아 둘 만함:
- JSONC(주석 있는 JSON) ——
tsconfig.json, VS Code 의settings.json, 그리고 많은 다른 개발자 설정에서 사용. JSONC 는////* */주석 그리고 후행 쉼표를 허용. 파일은 여전히.json로 표시되지만 표준JSON.parse()는 거부 —— VS Code 와 툴링은 JSONC 인식 파서를 함께 배포. - JSON5 —— 더 풍부한 상위집합: 주석, 후행 쉼표, 따옴표 없는 키, 작은따옴표, 여러 줄 문자열, 16 진수.
json5npm 패키지나 Python 의pyjson5로 opt-in. 사람이 손으로 편집하고 파서를 통제하는 곳에서 사용; 엄격한 JSON 을 기대하는 클라이언트에 API 로 보내지 마세요.
경험칙: 엄격한 JSON 파서를 통과하는 모든 것(API 응답, 요청 body, 임의의 라이브러리가 소비하는 파일) 에서 후행 쉼표를 배제 하고, 소비자가 인지하고 있는 JSONC/JSON5 내에서만 받아들이세요.
후행 쉼표 예방
- JSON 문자열을 수동으로 만들지 마세요.
JSON.stringify()를 쓰세요 —— 항상 명세 준수 출력을 생성. - linter 규칙 추가. ESLint 의
jsonc/no-trailing-commas규칙은 저장 시.json파일의 후행 쉼표를 잡습니다. - AI 출력 검증. 언어 모델이 생성한 것은 사용 전에 항상
JSON.parse()(또는 수리 파서)에 통과시키세요. - Prettier 사용. Prettier 는 JSON 파일을 재포매팅하고 저장 시 후행 쉼표를 자동 제거합니다.
자주 묻는 질문
JSON 은 후행 쉼표를 허용하나요?
아니요. RFC 8259 의 JSON 문법은 쉼표를 두 값 사이의 구분자로 엄격히 정의하므로 닫는 } 나 ] 앞에 뒤따르는 것이 없는 쉼표는 무효입니다. 모든 표준 파서 —— JSON.parse(), Python 의 json 모듈, Go 의 encoding/json —— 가 거부합니다.
JSON 에서 후행 쉼표를 어떻게 제거하나요?
파일 하나라면 마지막 항목 뒤의 쉼표를 수동으로 삭제. 반복적이거나 프로그램적 수정엔 JSON.stringify() 로 JSON 재생성, 수리 파서, 또는 JSON Fix 같은 도구 —— 문자열 내용에 손대지 않고 구조적 후행 쉼표를 제거합니다.
왜 JavaScript 는 후행 쉼표를 허용하지만 JSON 은 안 되나요?
JavaScript 는 더 깔끔한 git diff 를 만드는 개발자 편의 기능으로 ES5(배열) 와 ES2017(함수 매개변수) 에서 후행 쉼표를 추가. JSON 은 편의보다 모호하지 않은 파싱을 우선시하는 의도적으로 최소한의 교환 형식이라 결코 채택하지 않았습니다. 전체 차이는 JSON vs JavaScript 객체 참고.
후행 쉼표는 어떤 오류를 일으키나요?
보통 SyntaxError: Unexpected token '}' 또는 Expected double-quoted property name in JSON, 파서는 쉼표 뒤에 또 다른 값을 기대하는데 대신 닫는 괄호를 찾기 때문. 이건 더 넓은 JSON.parse "Unexpected token" 오류 의 한 변형.
지금 고치기 —— 설정 불필요
후행 쉼표가 있는 JSON 문자열을 즉시 고쳐야 한다면 JSON Fix 가 다른 흔한 문제들 —— 작은따옴표, 따옴표 없는 키, Python 리터럴, JavaScript 주석 —— 과 함께 자동으로 제거합니다. JSON 을 붙여 넣고 Repair & Format 을 클릭하고 깨끗한 JSON 을 복사해 가세요. 계정 없음, 업로드 없음, 데이터는 브라우저를 떠나지 않음.
- JSON Fix —— 후행 쉼표와 다른 흔한 JSON 오류 수리
- "[object Object] is not valid JSON" 과 다른 구문 오류 고치기 —— JSON 구문 오류의 완전 가이드
- JSON 의 후행 쉼표 고치기 —— 깨진 예제와 고친 예제가 있는 빠른 참조
- JSON Diff —— 수정이 올바른지 확인하기 위해 원본과 수리된 JSON 비교