JSON 후행 쉼표 — 결론부터
후행 쉼표(trailing comma)란 객체나 배열의 마지막 요소 뒤, 닫는 괄호 } 나 ] 바로 앞에 남아 있는 쉼표를 말합니다. 표준 JSON(RFC 8259)은 이를 허용하지 않으므로, 엄격한 파서는 Unexpected token }나 Expecting property name enclosed in double quotes 같은 오류로 파일을 거부합니다. 고치는 방법은 그 쉼표 하나를 지우는 것뿐입니다.
이 글은 후행 쉼표(,)만 다룹니다. //나 /* */ 같은 주석 문법은 다른 주제입니다. 여기서는 남는 쉼표에 초점을 맞춰 왜 오류가 나는지, 어떻게 찾는지, 어떻게 지우는지, 그리고 JSON5·JSONC에서는 무엇이 다른지를 설명합니다.
브라우저에서 바로 고치기
오류만 빨리 없애고 싶다면 글자 수를 손으로 세지 않아도 됩니다.
- JSON 포맷터를 엽니다
- 실패하고 있는 JSON을 붙여넣습니다
- 표시된 오류 줄을 읽습니다. 남는 쉼표 바로 뒤에 있는 닫는 괄호를 가리킵니다
- 그
}나]바로 앞의 쉼표를 지우고 다시 실행 버튼을 누릅니다 - 출력에서 정리된 JSON을 복사합니다
포맷터는 전부 브라우저 안에서 동작합니다. 붙여넣은 JSON은 업로드되거나 기록되거나 저장되지 않습니다. API 응답이나 내부 데이터가 담긴 설정 파일을 다룰 때 이 부분이 중요해집니다.


고치기 전과 후
후행 쉼표가 나타나는 위치는 세 가지입니다. 각각 깨진 예제와 수정본을 나란히 놓습니다.
객체의 후행 쉼표:
{
"name": "Aoi",
"role": "Engineer",
}
{
"name": "Aoi",
"role": "Engineer"
}
배열의 후행 쉼표:
[
"red",
"green",
"blue",
]
[
"red",
"green",
"blue"
]
중첩된 경우 — 안쪽 객체나 배열에 후행 쉼표가 숨어 있을 때도 있습니다:
{
"tags": ["a", "b",],
"meta": {
"active": true,
}
}
{
"tags": ["a", "b"],
"meta": {
"active": true
}
}
어느 경우든 고치는 방법은 같습니다. 마지막 값과 닫는 괄호 사이에 있는 쉼표만 지우면 됩니다. 값 자체에는 문제가 없습니다.
나타나는 오류 메시지
같은 후행 쉼표라도 어떤 언어로 읽느냐에 따라 파서가 쓰는 표현이 달라집니다.
브라우저·Node.js(V8)의 JSON.parse:
SyntaxError: Unexpected token } in JSON at position 42
SyntaxError: Expected double-quoted property name in JSON at position 42
Python의 json.loads:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 4 column 1 (char 42)
공통점은 파서가 쉼표까지 진행한 뒤 그다음에 또 다른 값이나 키를 기대했는데, 대신 닫는 괄호가 나왔다는 점입니다. 보고되는 position이나 줄 번호는 닫는 괄호 } / ]의 위치이므로, 지워야 할 쉼표는 그 한 줄 앞에 있습니다. 메시지는 나오는데 쉼표가 안 보인다면 JSON 포맷터에 붙여넣어 보세요. 해당 줄을 표시해 줍니다. 따옴표 오류, 키 따옴표 누락, 쉼표 부족 등 파싱 오류 전반의 원인은 JSON 파싱 오류 해결에 정리되어 있습니다.
JSON이 후행 쉼표를 금지하는 이유
RFC 8259새 탭에서 열립니다에서 쉼표는 값과 값을 구분하는 구분자(separator)이지, 각 값 뒤에 붙이는 종료 기호(terminator)가 아닙니다. Section 2의 문법은 배열을 "쉼표로 구분된 값의 나열"로, 객체를 "쉼표로 구분된 멤버의 나열"로 정의하며, 마지막 값 뒤에 요소를 하나 더 두는 생성 규칙(production rule)이 존재하지 않습니다. 그래서 공백과 닫는 괄호만 뒤따르는 쉼표는 구분할 대상이 없고, 사양을 따르는 파서는 이를 거부해야 합니다.
이 실수가 자주 나오는 이유도 같은 맥락입니다. JavaScript의 객체 리터럴과 배열 리터럴은 후행 쉼표를 허용하고, 많은 에디터가 .js 파일을 그 형태로 정리합니다. 하지만 JSON.parse()가 읽는 것은 JavaScript가 아니라 엄격한 JSON입니다. .js 파일 안에서는 아무 문제 없이 동작하는 텍스트도 JSON으로 파싱하는 순간 실패합니다. 코드에 있던 객체를 .json 파일로 복사하는 것이 후행 쉼표가 섞여 들어가는 전형적인 경로입니다.
후행 쉼표 자동으로 제거하기
쉼표 하나를 손으로 지우는 건 순식간이지만, JSON을 생성하는 코드나 여러 파일을 한꺼번에 고쳐야 하는 상황에서는 자동화해야 합니다.
문자열 이어붙이기가 아니라 직렬화 도구로 생성합니다. JSON.stringify(그리고 각 언어의 동등한 기능)는 후행 쉼표를 출력하지 않으므로 애초에 문제가 생기지 않습니다.
const data = { name: "Aoi", role: "Engineer" };
const json = JSON.stringify(data, null, 2);
// 항상 유효함 — 후행 쉼표는 절대 출력되지 않는다
저장할 때 자동으로 정리합니다. VS Code에서 .json 파일에 Format Document(또는 Prettier의 format-on-save)를 실행하면 재정리 과정에서 후행 쉼표가 제거됩니다. 손으로 편집하는 설정 파일을 깨끗하게 유지하는 가장 손쉬운 방법입니다.
정규식은 마지막 수단으로만 씁니다. ,\s*([}\]])는 "쉼표 + 공백 + 닫는 괄호"에 매칭됩니다.
const cleaned = source.replace(/,(\s*[}\]])/g, "$1");
const data = JSON.parse(cleaned);
이건 어디까지나 대체 수단으로 다뤄야 합니다. 문자열 값 안에 있는 쉼표(예: "a,}")에 잘못 반응할 수 있으므로, 직접 관리하는 파일에만 쓰고 처리 후에는 JSON 포맷터로 결과를 검증하세요.
파서 옵션은 "받아들이는" 것이지 "고쳐 쓰는" 것이 아닙니다. 후행 쉼표를 허용하도록 설정할 수 있는 라이브러리도 있습니다(.NET의 JsonSerializerOptions.AllowTrailingCommas 등). 이런 옵션은 자신의 코드가 파일을 읽을 수 있게 해줄 뿐, 디스크에 있는 파일 자체를 바꾸거나 다른 엄격한 파서에서도 통하게 만들어 주지는 않습니다. JSON을 다른 서비스로 보내야 한다면 결국 쉼표를 지워야 합니다.
Python에서 일괄 제거하기
표준 라이브러리 json은 후행 쉼표를 받아들이지 않지만, json5 패키지는 후행 쉼표를 허용하는 JSON5 사양으로 파싱할 수 있습니다. 실제 파서를 거치므로 정규식과 달리 문자열 값 안의 ,}를 잘못 건드리지 않습니다.
# pip install json5
import json, json5
with open("broken.json") as f:
data = json5.load(f)
with open("fixed.json", "w") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
Node.js에서 일괄 제거하기
npm의 json5 패키지로 읽어 들인 뒤 표준 JSON.stringify로 다시 씁니다.
// npm install json5
import JSON5 from "json5";
import fs from "node:fs";
const data = JSON5.parse(fs.readFileSync("broken.json", "utf8"));
fs.writeFileSync("fixed.json", JSON.stringify(data, null, 2));
sed로 여러 파일 한 번에 처리하기
CI나 셸 스크립트에서 많은 파일을 한꺼번에 고쳐야 한다면 sed가 손쉬운 방법입니다. 다만 앞서 나온 정규식과 같은 오작동 위험이 있으므로, 처리 후에는 반드시 파싱 검증 단계를 넣으세요.
sed -E 's/,[[:space:]]*([}\]])/\1/g' broken.json > fixed.json
python3 -c "import json; json.load(open('fixed.json'))" # 검증
jq로는 고칠 수 없는 이유
jq의 파서는 엄격해서 후행 쉼표가 포함된 입력 자체를 받아들이지 않습니다. jq . broken.json은 파일을 고쳐 주는 대신 오류로 멈춥니다. jq는 "이미 올바른 JSON을 변형하고 추출하는" 도구이므로, 제거는 위에 나온 방법 중 하나로 먼저 처리하고, 고친 뒤의 가공에 jq를 사용하세요.
후행 쉼표가 다시 생기지 않게 하기
한 번 고쳤다고 해서 다음 파일에서 재발하지 않는 것은 아닙니다. 일찍 잡아내기 위한 안전장치 몇 가지가 있습니다.
- 에디터: VS Code는
.json파일의 후행 쉼표에 경고를 표시합니다(.jsonc에서는 표시하지 않습니다). 확장자를.json으로 유지해야 이 경고가 계속 켜져 있습니다 - 자주 생기는 곳을 알아 둡니다: 후행 쉼표는 손으로 편집한 설정 파일,
.js소스에서 복사해 온 JSON, 문자열 이어붙이기로 만든 JSON에서 가장 많이 나타납니다. 실제 직렬화 도구가 생성한 JSON은 안전합니다
trailingComma는 어디서 오는가
저장할 때 자동으로 실행되는 정리 기능이 후행 쉼표가 다시 붙는 원인이 되기도 합니다. Prettier 공식 문서와 이슈 트래커에 나와 있는 내용은 다음과 같습니다.
| 항목 | 내용 | 출처 |
|---|---|---|
| Prettier의 기본값 | trailingComma의 기본값은 v3.0.0부터 "all"이며, 그 이전에는 "es5"였다 | prettier.io/docs/options새 탭에서 열립니다 |
| VS Code 확장 | trailingComma를 강제로 끄는 주체는 Prettier 본체가 아니라 VS Code 확장 자체이며, 파서가 json일 때만 적용된다 — 변경 요청 이슈는 closed이자 locked 상태다 | prettier-vscode#589새 탭에서 열립니다 |
tsconfig.json | 확장자가 .json이어도 Prettier 본체는 이 파일을 JSONC로 추정하기 때문에 저장할 때 후행 쉼표가 붙을 수 있다 — closed as not planned 상태다 | prettier#15942새 탭에서 열립니다 |
.jsonc 전반 | 같은 JSONC 추정이 .jsonc 확장자를 쓰는 파일 전체에도 적용된다 — 이슈는 needs discussion 상태로 open이다 | prettier#15956새 탭에서 열립니다 |
CI에 JSON.parse 게이트 두기
JSON을 이해하는 린터나 빌드 중의 JSON.parse 단계는 후행 쉼표가 다른 서비스에서 문제를 일으키기 전에 미리 막아 줍니다. 의존성 없는 최소 구성은 다음과 같습니다.
node -e "JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8'))" config.json
이를 pre-commit 훅으로 걸거나, CI에서 저장소의 모든 .json 파일을 대상으로 반복 실행하세요. 손으로 편집하는 설정 파일에는 특히 넣을 가치가 있습니다. 후행 쉼표가 재발하기 쉬운 곳이 바로 그런 파일이기 때문입니다.
JSON5 / JSONC는 후행 쉼표를 허용합니다
diff를 깔끔하게 유지하려는 이유 등으로 후행 쉼표를 계속 쓰고 싶다면, 이를 허용하는 포맷도 있습니다.
- JSON5는 정식 사양을 갖춘 JSON의 상위 집합(superset)으로, 후행 쉼표·주석·따옴표 없는 키·작은따옴표를 허용합니다
- JSONC(VS Code가 쓰는 "주석 있는 JSON")는 주석을 추가하며, 파서에 따라 후행 쉼표도 선택적으로 받아들입니다
주의할 점은 통용 범위입니다. 이 확장 문법을 이해하는 도구가 읽는 설정 파일이라면 문제없지만, API 페이로드나 package.json, 엄격한 JSON.parse를 쓰는 서비스에서는 유효하지 않습니다.
목표가 "읽기 좋은 엄격한 JSON"이라면 결과물을 JSON 포맷터에 통과시켜 확인하세요.
자주 묻는 질문
JSON에서 후행 쉼표를 쓸 수 있나요?
쓸 수 없습니다. RFC 8259는 쉼표를 값과 값 사이의 구분자로 정의하며, 마지막 값 뒤에 요소를 두는 것을 허용하지 않습니다. 그래서 닫는 괄호 } / ] 바로 앞의 쉼표는 무효이며, 엄격한 파서는 Unexpected token } 같은 오류로 거부합니다.
후행 쉼표는 어떻게 찾아서 지우나요?
JSON 포맷터에 JSON을 붙여넣으세요. 오류 메시지가 남는 쉼표 바로 뒤에 있는 닫는 괄호를 가리키므로, 그 한 줄 앞에 있는 쉼표를 지우고 다시 실행하면 됩니다. 재발을 막으려면 문자열을 손으로 조립하지 말고 JSON.stringify로 생성하세요.
왜 JavaScript에서는 후행 쉼표가 되고 JSON에서는 안 되나요?
JavaScript의 객체·배열 리터럴은 편의를 위해 후행 쉼표를 허용합니다. JSON은 JSON.parse가 읽는 엄격한 데이터 포맷으로, RFC 8259를 따르며 마지막 값 뒤에 요소를 두는 규칙이 없습니다. 같은 텍스트가 JS 리터럴로는 유효하고 JSON으로는 무효가 되는 이유입니다.
후행 쉼표는 어떤 오류 메시지로 나타나나요?
대부분 V8/Node에서는 Unexpected token }(또는 ]), 최신 V8에서는 Expected double-quoted property name, Python에서는 Expecting property name enclosed in double quotes로 나타납니다. 모두 다른 값이나 키를 기대한 위치에 닫는 괄호가 왔다는 뜻입니다.
지우지 않고 후행 쉼표를 그냥 허용하면 안 되나요?
허용하도록 설정할 수 있는 파서도 있습니다(.NET의 AllowTrailingCommas 등). 다만 그건 파일을 읽는 쪽 코드에만 도움이 될 뿐, 다른 파서나 전송을 위해 파일 자체를 유효하게 만들어 주지는 않습니다. 상호 운용 가능한 JSON으로 만들려면 쉼표를 지워야 합니다.
JSON5에서는 후행 쉼표가 동작하나요?
동작합니다. JSON5는 후행 쉼표를 명시적으로 허용하며, 주석과 따옴표 없는 키도 함께 인정합니다. 로컬 설정 파일에는 적합하지만, 엄격한 RFC 8259 JSON이 필요한 API 데이터에는 쓸 수 없습니다.
정리
- 후행 쉼표는 닫는 괄호
}/]바로 앞의 쉼표이며, 표준 JSON은 이를 금지합니다 - 오류는
Unexpected token }나Expecting property name enclosed in double quotes형태로 나타납니다. 보고되는 위치는 괄호이므로 쉼표는 그 한 줄 앞에 있습니다 - 가장 빠른 해결법은 JSON 포맷터에 파일을 붙여넣고 줄을 읽어 쉼표를 지우는 것입니다
JSON.stringify로 생성하고 저장할 때 자동 정리를 걸어 두면 후행 쉼표가 다시 생기는 것을 막을 수 있습니다- JSON5 / JSONC는 후행 쉼표를 허용하지만, 이를 이해하는 도구에서만 통하며 API 페이로드에는 쓸 수 없습니다