잘못된 JSON 파일을 빠르게 수정하는 방법: 개발자 필드 매뉴얼
API 호출이 JSONDecodeError: Expecting property name enclosed in double quotes로 실패했습니다. 시계가 째깍째깍 돌아갑니다. 데이터는 LLM에서 왔고, 2,000 토큰짜리 응답 어딘가에서 후행 쉼표 하나가 전체 파이프라인을 망가뜨렸습니다.
2026년 5월 현재, 잘못된 JSON 파일을 수정하는 가장 빠른 방법은 json_repair(Python) 또는 jsonrepair(npm) 같은 자동화 라이브러리를 사용하는 것입니다. 이 도구들은 LLM이 생성한 구문 오류를 즉시 수정하도록 특별히 설계되었습니다. 수동 수정의 경우, 흔한 범인은 후행 쉼표, 작은따옴표, 인용되지 않은 키입니다. 이는 RFC 8259 표준을 위반하는 가장 흔한 세 가지 사례입니다.
가장 빠른 수정: LLM 출력을 위한 json_repair
Python의 json.loads() 같은 표준 파서는 설계상 엄격합니다. 잘못 배치된 문자 하나가 JSONDecodeError를 발생시키고 모든 것이 멈춥니다. 이는 2026년에 일상적인 문제입니다. LLM이 JSON을 대화형 텍스트로 감싸거나, 응답을 문장 중간에 잘라버리거나, 사양을 깨뜨리는 주석을 뿌려 넣기 때문입니다.
json_repair 라이브러리가 정답입니다. GitHub에 따르면, 2026년 현재 이 프로젝트는 4,700개 이상의 별을 받았습니다. 이 도구는 문자열의 의도를 “추측”하는 방식으로 동작합니다. 누락된 괄호를 닫고, 따옴표를 추가하고, JSON 블록 주변의 불필요한 텍스트를 제거합니다.

Python: 수정 전과 후
설치: pip install json-repair
손상된 입력:
import json_repair
bad_json = '{"user": "Alice", "status": tru'
decoded_object = json_repair.loads(bad_json)
내부적으로 무슨 일이 일어났는지: json_repair는 tru가 아마도 true일 것이라고 판단하고, 누락된 닫는 중괄호를 추가한 다음, 유효한 Python 딕셔너리를 반환했습니다. 수동 개입은 전혀 없었습니다.
Salvage 모드: 데이터가 정말 엉망일 때
더 까다로운 경우를 위해, json_repair(v0.59.5+)에는 Salvage 모드가 있습니다. 프로젝트 문서에 설명된 대로, 이 모드는 잘린 AI 응답이나 손상된 로그를 위해 특별히 만들어졌습니다. 배열을 객체로 강제 변환하거나 너무 손상되어 복구할 수 없는 항목을 삭제하여 출력이 스키마에 맞도록 보장합니다.
import json_repair
# Salvage mode for severely truncated data
result = json_repair.loads(
'{"items": [{"id": 1, "name": "Widget"}, {"id": 2, "na',
salvage_mode=True
)
# Result: {'items': [{'id': 1, 'name': 'Widget'}, {'id': 2}]}
# Dropped the incomplete 'na' but saved everything else
npm 대안
Node.js 프로젝트의 경우, jsonrepair CLI가 같은 작업을 처리합니다:
# Fix a file in place
npx jsonrepair broken.json > fixed.json
# Fix a string in a script
const { jsonrepair } = require('jsonrepair');
const fixed = jsonrepair('{"name": "test",}');
수동 디버깅: 사양을 깨뜨린 것 찾기
자동화로는 부족할 때, 파일이 정확히 어디에서 RFC 8259를 위반했는지 찾아야 합니다. JSON은 YAML이나 JavaScript보다 훨씬 관대하지 않습니다. JSONParser 진단 팀의 설명에 따르면, “파서는 이해할 수 없는 첫 번째 문자에서 실패하는데, 이는 종종 몇 줄 앞선 문제의 하위 증상입니다.”
3대 JSON 킬러
킬러 1: 후행 쉼표
DEV Community에 따르면, 후행 쉼표는 파싱 실패의 1번째 원인입니다. JavaScript에서는 괜찮지만, JSON 배열이나 객체의 마지막 항목 뒤에는 허용되지 않습니다.
// BROKEN - trailing comma after "active"
{
"name": "Alice",
"status": "active",
}
// FIXED - no comma before closing brace
{
"name": "Alice",
"status": "active"
}
킬러 2: 작은따옴표
JSON은 키와 문자열 값 모두에 이중 따옴표(")를 요구합니다. 많은 Python과 JavaScript 개발자가 실수로 작은따옴표(')를 사용합니다. TidyCode가 지적하듯, 이는 반드시 수정해야 합니다.
// BROKEN - single quotes
{'name': 'Alice'}
// FIXED - double quotes
{"name": "Alice"}
킬러 3: 인용되지 않은 키
JavaScript에서는 { name: "Alice" }라고 쓸 수 있습니다. 하지만 JSON에서는 모든 키에 이중 따옴표가 필요합니다.
// BROKEN - unquoted key
{name: "Alice"}
// FIXED - quoted key
{"name": "Alice"}

“Unexpected Token” 오류
검증기가 “Unexpected Token”을 보고하면, 파서가 NaN, Infinity, 또는 undefined를 만났다는 뜻입니다. 이는 JSON이 지원하지 않는 JavaScript 상수입니다. JSON은 null, true, false, 숫자만 허용합니다.
// BROKEN - NaN is not valid JSON
{"score": NaN, "result": Infinity}
// FIXED - replace with null or valid values
{"score": null, "result": null}
엄격한 파싱 vs. 복구 파싱: 언제 무엇을 쓸까
올바른 접근 방식은 데이터가 어디서 오는지에 따라 다릅니다. 사람이 편집한 설정 파일은 작성자가 실수를 고치도록 엄격한 파싱이 필요합니다. LLM이나 API 로그에서 온 기계 생성 데이터는 복구 기반 파싱이 필요합니다.
| 특성 | 엄격(json.loads) |
복구(json_repair) |
|---|---|---|
| 후행 쉼표 | JSONDecodeError 발생 |
자동으로 제거 |
| 작은따옴표 | 실패 | 이중 따옴표로 변환 |
| 잘린 데이터 | 실패 | 열린 괄호/따옴표를 닫음 |
| 주석 | 실패 | 자동으로 제거 |
| 최적 용도 | 사람이 편집한 설정 파일 | LLM 출력, API 로그 |
Pydantic으로 스키마 기반 복구
Pydantic v2 또는 JSON Schema를 사용해 복구 과정을 안내할 수 있습니다. json_repair에 스키마를 제공하면, 도구는 구문을 수정할 뿐만 아니라 타입을 교정하고(문자열 "1"을 숫자 1로 변환) 누락된 필수 필드를 기본값으로 채웁니다.
from pydantic import BaseModel
import json_repair
class User(BaseModel):
id: int
name: str
active: bool = True
# Broken JSON with wrong types
raw = '{"id": "42", "name": "Alice"}'
repaired = json_repair.loads(raw)
# Validate against schema
user = User(**repaired)
# user.id is now int(42), user.active defaults to True
Stefano Baccianella가 2025년 프로젝트 인용에서 언급했듯이, 이 접근법은 언어 모델이 자주 생성하는 “대체로 맞지만 기술적으로 유효하지 않은” JSON에 최적화되어 있습니다.
수 기가바이트 파일을 크래시 없이 처리하기
10KB 스니펫을 수정하는 건 쉽습니다. 2GB 파일을 수정하려면 메모리를 다 잡아먹지 않는 전략이 필요합니다. 전체 파일을 메모리에 로드하면 메모리 부족(OOM) 오류가 발생합니다.
전략 1: ijson으로 스트리밍
대규모 데이터셋의 경우, ijson을 사용해 데이터를 조각 단위로 처리하세요. Scrapfly가 언급한 대로, ijson은 데이터를 점진적으로 처리합니다. 파싱 전에 문제를 줄 단위로 수정하는 정리 스크립트와 함께 사용하세요.
import ijson
# Stream through a large JSON file
with open('huge_broken.json', 'r') as f:
for item in ijson.items(f, 'records.item'):
# Process each item individually
process(item)
전략 2: 최대 효율을 위한 CLI 파이프
대용량 파일에서 가장 메모리 효율적인 방법은 jsonrepair CLI를 사용하고 출력을 새 파일로 직접 파이프하는 것입니다:
# Streams repair, never loads full file into memory
jsonrepair large_broken.json > fixed.json
이 방법은 파일을 Python이나 브라우저에 로드하는 것보다 훨씬 메모리 효율적입니다.
결론
json_repair 같은 AI 인식 라이브러리 덕분에 잘못된 JSON을 수정하는 것은 더 이상 수동 작업이 아닙니다. 여전히 RFC 8259 기본 사항(후행 쉼표 금지, 작은따옴표 금지, 인용되지 않은 키 금지)을 이해해야 하지만, 2026년에 대규모 데이터를 다룰 때는 자동화만이 유일한 실용적인 접근법입니다.
워크플로는 간단합니다. 먼저 복구 라이브러리를 시도하세요. 실패하면 검증기를 사용해 정확한 구문 오류를 찾아냅니다. 이렇게 하면 들어오는 데이터가 완벽하지 않더라도 애플리케이션이 계속 실행됩니다.
자주 묻는 질문
JSON이 공식적으로 주석이나 작은따옴표를 지원하나요?
아니요. RFC 8259 표준은 주석을 엄격히 금지합니다. 작은따옴표도 유효하지 않습니다. 키와 문자열에는 이중 따옴표만 허용됩니다. 하지만 json_repair 같은 도구는 주석을 제거하고 따옴표를 자동으로 변환하여 표준 라이브러리로 파일을 파싱할 수 있게 만듭니다.
매우 크고 잘못된 JSON 파일을 크래시 없이 어떻게 처리하나요?
ijson 같은 스트리밍 파서를 사용해 데이터를 청크 단위로 처리하세요. 전체 잘못된 문자열을 단일 변수에 로드하지 마세요. 가장 빠르려면, 출력을 메모리에 모두 담지 않고 디스크의 새 파일로 직접 파이프하는 CLI 복구 도구를 사용하세요.
잘못된(malformed) JSON과 유효하지 않은(invalid) JSON의 차이는 무엇인가요?
잘못된 JSON은 구문 규칙(괄호 누락, 인용되지 않은 키, 후행 쉼표)을 위반하여 파싱할 수 없게 만듭니다. 유효하지 않은 JSON은 모든 구문 규칙을 따르지만 특정 JSON Schema와 일치하지 않습니다(예: 스키마가 정수를 기대하는데 필드가 문자열인 경우). 잘못된 JSON을 수정하는 것은 구조적 복구이고, 유효하지 않은 JSON을 수정하는 것은 데이터 무결성에 관한 것입니다.
json_repair를 Pydantic 검증과 함께 사용할 수 있나요?
네. 먼저 json_repair.loads()로 구문 오류를 수정한 다음, 복구된 딕셔너리를 Pydantic 모델에 전달하여 타입 검증과 스키마 적용을 수행하세요. 이 두 단계 접근법은 구조적 문제와 의미적 문제를 모두 해결합니다.
JavaScript 스타일 주석이 있는 JSON은 어떨까요?
표준 JSON은 주석을 지원하지 않지만, json_repair는 //와 /* */ 주석을 자동으로 제거할 수 있습니다. 설정 파일에 주석이 필요하다면 JSONC(주석이 있는 JSON) 형식과 Python용 json5 같은 호환 파서를 사용하는 것을 고려해 보세요.