← 블로그로 돌아가기

일반적인 JSON 오류와 해결 방법: 완벽 디버깅 가이드

JSON 파싱 오류를 빠르게 찾고 수정하는 방법을 배워보세요. 일반적인 실수, 디버깅 도구, 예방 방법까지 완벽 정리.

Big JSON Team12분 소요beginner
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

12 분 읽기

# 일반적인 JSON 오류와 해결 방법: 완벽 디버깅 가이드

JSON 오류는 개발자라면 누구나 겪는 일입니다. 이 가이드에서 일반적인 JSON 오류를 빠르게 찾고 해결하는 방법을 배워보세요.

JSON 파싱 오류의 이해

JSON 파싱 오류는 JSON 문법이 올바르지 않을 때 발생합니다. 브라우저나 서버가 JSON을 파싱할 수 없으면 에러를 발생시킵니다.

일반적인 오류 메시지

  • Unexpected token
  • Unexpected end of JSON input
  • Expected property name or '}'
  • Invalid or unexpected token

1. 후행 쉼표 (Trailing Comma)

문제

{

"name": "홍길동",

"age": 30,

"email": "hong@example.com", // ❌ 마지막 쉼표

}

오류 메시지:
Unexpected token } in JSON at position 65

해결

{

"name": "홍길동",

"age": 30,

"email": "hong@example.com" // ✅ 쉼표 제거

}

배열에서도 동일

{

"items": [

"item1",

"item2", // ❌ 마지막 쉼표

]

}

예방법

  • JSON 포맷터 사용
  • Linter 설정
  • 자동 검증 도구

2. 따옴표 문제

작은따옴표 사용

{

'name': '홍길동' // ❌ 작은따옴표

}

해결:
{

"name": "홍길동" // ✅ 쌍따옴표

}

따옴표 없는 키

{

name: "홍길동" // ❌ 키에 따옴표 없음

}

해결:
{

"name": "홍길동" // ✅ 키에 쌍따옴표

}

이스케이프되지 않은 따옴표

{

"message": "He said "Hello"" // ❌ 이스케이프 안됨

}

해결:
{

"message": "He said \"Hello\"" // ✅ 백슬래시로 이스케이프

}

한국어와 따옴표

{

"message": "그는 "안녕"이라고 말했다" // ❌

}

해결:
{

"message": "그는 \"안녕\"이라고 말했다" // ✅

}

3. 주석

문제

JSON은 주석을 지원하지 않습니다:

{

// 사용자 정보 // ❌ 주석 불가

"name": "홍길동",

/ 나이 / // ❌ 블록 주석도 불가

"age": 30

}

해결책

방법 1: 주석 제거
{

"name": "홍길동",

"age": 30

}

방법 2: 특수 필드 사용
{

"_comment": "사용자 정보",

"name": "홍길동",

"age": 30

}

방법 3: JSONC 사용 (일부 도구에서 지원)
{

// VS Code 설정 파일 등에서 지원

"name": "홍길동"

}

4. 잘못된 값 타입

undefined

{

"name": "홍길동",

"age": undefined // ❌ JSON에서 undefined 불가

}

해결:
{

"name": "홍길동",

"age": null // ✅ null 사용

}

NaN과 Infinity

const data = {

value: NaN,

infinity: Infinity

};

JSON.stringify(data);

// {"value":null,"infinity":null} // null로 변환됨

해결:
const data = {

value: "NaN", // 문자열로

infinity: "Infinity"

};

함수

const data = {

name: "홍길동",

greet: function() { } // ❌ 함수는 제외됨

};

JSON.stringify(data);

// {"name":"홍길동"} // 함수는 사라짐

5. 특수 문자 이스케이프

줄바꿈

{

"message": "첫 줄

두번째 줄" // ❌ 실제 줄바꿈

}

해결:
{

"message": "첫 줄\n두번째 줄" // ✅ \n 사용

}

{

"text": "이름: 홍길동" // ❌ 실제 탭

}

해결:
{

"text": "이름:\t홍길동" // ✅ \t 사용

}

백슬래시

{

"path": "C:\Users\Hong" // ❌ 단일 백슬래시

}

해결:
{

"path": "C:\\Users\\Hong" // ✅ 이중 백슬래시

}

이스케이프 시퀀스

| 문자 | 이스케이프 |

|------|----------|

| 쌍따옴표 | \" |

| 백슬래시 | \\ |

| 슬래시 | \/ |

| 백스페이스 | \b |

| 폼피드 | \f |

| 줄바꿈 | \n |

| 캐리지 리턴 | \r |

| 탭 | \t |

| 유니코드 | \uXXXX |

6. 숫자 형식

선행 0

{

"code": 0123 // ❌ 8진수 표기

}

해결:
{

"code": 123 // ✅ 또는

"code": "0123" // ✅ 문자열로

}

16진수

{

"color": 0xFF0000 // ❌ 16진수 불가

}

해결:
{

"color": 16711680, // ✅ 10진수로

"colorHex": "#FF0000" // ✅ 또는 문자열

}

소수점으로 시작

{

"value": .5 // ❌ 0 누락

}

해결:
{

"value": 0.5 // ✅ 0 추가

}

소수점으로 끝

{

"value": 5. // ❌ 소수 부분 누락

}

해결:
{

"value": 5.0 // ✅ 또는

"value": 5 // ✅ 정수로

}

7. 구조 오류

중괄호/대괄호 불일치

{

"users": [

{ "name": "홍길동" },

{ "name": "김철수" }

// ❌ ] 누락

}

해결:
{

"users": [

{ "name": "홍길동" },

{ "name": "김철수" }

] // ✅ ] 추가

}

쉼표 누락

{

"name": "홍길동" // ❌ 쉼표 누락

"age": 30

}

해결:
{

"name": "홍길동", // ✅ 쉼표 추가

"age": 30

}

콜론 누락

{

"name" "홍길동" // ❌ 콜론 누락

}

해결:
{

"name": "홍길동" // ✅ 콜론 추가

}

8. 인코딩 문제

UTF-8 BOM

// ❌ UTF-8 BOM이 있으면 파싱 실패

{

"name": "홍길동"

}

해결:
  • UTF-8 without BOM으로 저장
  • BOM 제거

잘못된 인코딩

한글이 깨지는 경우:

// Node.js에서 파일 읽기

const fs = require('fs');

// ❌ 인코딩 미지정

const data = fs.readFileSync('file.json');

// ✅ UTF-8 명시

const data = fs.readFileSync('file.json', 'utf8');

디버깅 도구

1. JSONLint

JSONLint.com 기능:
  • 오류 위치 정확히 표시
  • 오류 메시지
  • 자동 포맷팅

2. JSON Simplify

JSON Simplify 기능:
  • 실시간 검증
  • 한국어 오류 메시지
  • 시각적 트리 뷰

3. VS Code

내장 검증:
  • 실시간 오류 표시
  • 빨간 밑줄로 표시
  • 마우스 오버로 오류 확인

확장:
  • JSON Tools
  • JSON Validator

4. 브라우저 개발자 도구

try {

const data = JSON.parse(jsonString);

} catch (error) {

console.error('JSON 파싱 오류:', error.message);

console.error('위치:', error);

}

JavaScript에서 오류 처리

기본 try-catch

function safeParse(jsonString) {

try {

return JSON.parse(jsonString);

} catch (error) {

console.error('JSON 파싱 실패:', error.message);

return null;

}

}

const result = safeParse(invalidJson);

if (result === null) {

// 오류 처리

}

상세한 오류 정보

function parseWithDetails(jsonString) {

try {

return {

success: true,

data: JSON.parse(jsonString)

};

} catch (error) {

// 오류 위치 찾기

const match = error.message.match(/position (\d+)/);

const position = match ? parseInt(match[1]) : -1;

return {

success: false,

error: {

message: error.message,

position,

context: position >= 0

? jsonString.substring(Math.max(0, position - 20), position + 20)

: null

}

};

}

}

const result = parseWithDetails(jsonString);

if (!result.success) {

console.log('오류:', result.error.message);

console.log('주변 텍스트:', result.error.context);

}

사용자 정의 reviver로 복구

function tolerantParse(jsonString) {

return JSON.parse(jsonString, (key, value) => {

// NaN을 0으로

if (typeof value === 'number' && isNaN(value)) {

return 0;

}

// Infinity를 큰 숫자로

if (value === Infinity) {

return Number.MAX_SAFE_INTEGER;

}

return value;

});

}

Python에서 오류 처리

import json

def safe_parse(json_string):

try:

return json.loads(json_string)

except json.JSONDecodeError as e:

print(f"JSON 파싱 오류: {e.msg}")

print(f"라인: {e.lineno}, 컬럼: {e.colno}")

print(f"위치: {e.pos}")

return None

# 사용

result = safe_parse(invalid_json)

if result is None:

# 오류 처리

pass

일반적인 실수 예방

1. JSON 생성 시

❌ 문자열 연결로 JSON 생성:
const json = '{"name":"' + name + '"}';  // 위험!
✅ JSON.stringify 사용:
const json = JSON.stringify({ name });  // 안전

2. 템플릿 리터럴 주의

// ❌ 위험

const json = {"name": "${name}"};

// ✅ 안전

const json = JSON.stringify({ name });

3. 객체를 JSON으로 직접 사용

// ❌ 잘못된 가정

const obj = { name: "홍길동" };

sendToServer(obj); // JSON이 아님!

// ✅ 올바른 방법

const json = JSON.stringify(obj);

sendToServer(json);

4. Linter 설정

.eslintrc.json:
{

"extends": ["plugin:json/recommended"],

"plugins": ["json"]

}

5. 스키마 검증

const Ajv = require('ajv');

const ajv = new Ajv();

const schema = {

type: 'object',

properties: {

name: { type: 'string' },

age: { type: 'number' }

},

required: ['name']

};

const validate = ajv.compile(schema);

if (!validate(data)) {

console.log('검증 실패:', validate.errors);

}

자동 수정 도구

prettier

npm install --save-dev prettier
# JSON 포맷팅

prettier --write "*/.json"

.prettierrc:
{

"printWidth": 80,

"tabWidth": 2,

"trailingComma": "none"

}

jq (명령줄)

# 검증 및 포맷

jq '.' input.json > output.json

# 오류 확인

jq '.' invalid.json

# parse error: Expected separator between values at line 2, column 3

복잡한 오류 디버깅

큰 JSON 파일

// 청크로 나누어 검사

function findJsonError(jsonString) {

const chunkSize = 1000;

for (let i = 0; i < jsonString.length; i += chunkSize) {

const chunk = jsonString.substring(0, i + chunkSize);

try {

JSON.parse(chunk);

} catch (error) {

console.log(오류 위치: 약 ${i}~${i + chunkSize} 사이);

console.log('주변 텍스트:', chunk.substring(i, i + 100));

break;

}

}

}

이진 검색으로 오류 찾기

function binarySearchError(jsonString) {

let left = 0;

let right = jsonString.length;

while (left < right) {

const mid = Math.floor((left + right) / 2);

const substring = jsonString.substring(0, mid);

try {

JSON.parse(substring);

left = mid + 1;

} catch (error) {

right = mid;

}

}

console.log('오류 위치:', left);

console.log('주변:', jsonString.substring(left - 50, left + 50));

}

모범 사례

1. 항상 검증

// API 응답 검증

async function fetchData(url) {

const response = await fetch(url);

const text = await response.text();

try {

return JSON.parse(text);

} catch (error) {

console.error('응답이 유효한 JSON이 아닙니다');

console.error('응답:', text);

throw error;

}

}

2. 타입 검증

function validateUser(data) {

if (typeof data.name !== 'string') {

throw new Error('name은 문자열이어야 합니다');

}

if (typeof data.age !== 'number') {

throw new Error('age는 숫자여야 합니다');

}

return true;

}

3. 기본값 제공

function getConfig(jsonString) {

try {

return JSON.parse(jsonString);

} catch (error) {

console.warn('설정 파일 파싱 실패, 기본값 사용');

return {

theme: 'light',

language: 'ko'

};

}

}

4. 로깅

function parseAndLog(jsonString, source) {

try {

return JSON.parse(jsonString);

} catch (error) {

console.error(JSON 파싱 실패 [${source}]:, error.message);

console.error('JSON 내용:', jsonString);

throw error;

}

}

결론

JSON 오류는 작은 실수에서 발생하지만 디버깅하기 어려울 수 있습니다. 좋은 도구를 사용하고, 항상 검증하며, 자동화된 포맷팅을 적용하면 대부분의 오류를 예방할 수 있습니다.

핵심 요약:
  • ✅ 후행 쉼표 제거
  • ✅ 쌍따옴표만 사용
  • ✅ 주석 사용 금지
  • ✅ 특수 문자 이스케이프
  • ✅ 검증 도구 활용

지금 바로 JSON Simplify에서 JSON을 검증해보세요!

Share:

관련 글

Read in English