빠른 비교
// JavaScript object literal
const obj = {
user: "Kim",
active: true,
note: undefined,
};
// JSON text
const text = '{"user":"Kim","active":true}';갈리는 기준
JSON은 JavaScript에서 유래했지만 JavaScript object literal 문법을 그대로 따르지 않는다
JSON의 이름에 "JavaScript"가 들어가 있어 JavaScript object literal과 같은 문법이라고 오해하기 쉽습니다. 실제로 JSON은 JavaScript 초기 문법에서 영감을 받았지만, 오늘날의 JSON spec(RFC 8259)은 JavaScript와 독립적으로 정의됩니다. JSON에서는 key를 반드시 큰따옴표로 감싸야 하고("user": "Kim"), JavaScript object literal처럼 따옴표를 생략하거나 단일 따옴표를 쓸 수 없습니다. 이 규칙이 엄격한 이유는 언어 중립적인 파서가 grammar 예외 없이 key를 일관되게 읽을 수 있어야 하기 때문입니다.
JavaScript에서 되는 문법 중 JSON이 허용하지 않는 것들
JavaScript object literal에는 // 주석, trailing comma, undefined, 함수, Symbol, 메서드 문법이 허용됩니다. JSON은 이 모두를 허용하지 않습니다. 실무에서 자주 생기는 문제는 다음 두 가지입니다. 첫째, 프런트엔드 코드의 object literal을 API fixture JSON이나 설정 파일로 복사할 때 trailing comma나 작은따옴표가 따라오는 경우. 둘째, JSON.stringify()로 직렬화할 때 undefined 필드가 조용히 사라지거나, 배열 안의 undefined가 null로 바뀌는 경우입니다. 이 변환은 오류 없이 일어나기 때문에 데이터 손실을 발견하기 어렵습니다.
또한 object literal은 코드 안의 "값 표현"이고 JSON은 네트워크로 주고받는 "텍스트 형식"입니다. 둘 다 중괄호를 쓴다고 해서 같은 층위의 개념으로 보면 parse 에러와 직렬화 손실을 한데 섞어 오해하게 됩니다.
JSON.parse("{'foo': 1}"); // SyntaxError — 작은따옴표 key
JSON.parse('{"foo": 1}'); // OKJSON.stringify()는 "모든 값을 보존하는" 직렬화가 아니다 — 손실 없는 왕복 직렬화를 기대하면 안 된다
JavaScript 값을 JSON.stringify()로 직렬화한 뒤 JSON.parse()로 다시 읽으면 처음 값과 동일하다고 가정하기 쉽습니다. 그러나 undefined는 object 멤버에서 제거되고 array 안에서는 null로 바뀝니다. 함수와 Symbol도 제거됩니다. Date 객체는 ISO 8601 문자열로 변환되고, 다시 파싱하면 Date 객체가 아닌 string으로 돌아옵니다. BigInt는 기본적으로 예외를 던집니다. 이 동작은 명시된 spec이지만, 모르면 데이터 손실이나 타입 변환 버그로 이어집니다.
JSON과 JavaScript object literal의 차이를 활용하는 방법 — 변환 도구를 쓰거나 타입별 규칙을 정의한다
JavaScript object를 JSON 호환 형태로 변환해야 할 때는 JSON.stringify() + JSON.parse() 조합이 가장 간단하지만, 손실되는 타입을 감수해야 합니다. Date, BigInt, Map, Set 같은 타입을 보존하려면 replacer 함수로 직렬화 규칙을 정의하고, reviver 함수로 역직렬화 규칙을 대칭으로 정의해야 합니다. 팀 내 API나 설정 파일 규약을 정할 때 "어떤 JavaScript 타입을 JSON으로 어떻게 인코딩할지"를 명시해 두는 것이 나중에 파싱 코드의 암묵적 가정을 줄입니다.
JSON.parse('{"user":"Kim","active":true}');
JSON.parse("{ user: 'Kim' }"); // SyntaxError선택 기준
| 상황 | 적합한 선택 |
|---|---|
| 언어 간 데이터 교환 | JSON (큰따옴표 key, 주석 없음, trailing comma 없음) |
| JavaScript 내부 구조체 | object literal (편의 문법 자유롭게 사용 가능) |
Date·BigInt 직렬화 | replacer/reviver로 변환 규칙 정의 |
| JS 코드를 JSON 파일로 옮길 때 | JSON validator로 검증 후 사용 |
| object와 JSON string을 오갈 때 | "값인가 문자열인가"를 먼저 확인 |
주의할 점
"JSON처럼 생겼다"와 "실제로 유효한 JSON이다"는 다릅니다. 특히 JavaScript object literal을
설정 파일이나 API fixture로 옮길 때는 JSON validator로 다시 확인해야 합니다. JSON.stringify()는
undefined, 함수, Symbol을 조용히 제거하거나 null로 바꾸므로, 직렬화 전후 값이
동일하다는 가정은 위험합니다.
JSON.stringify({
createdAt: new Date("2026-04-07T12:00:00Z"),
note: undefined,
});이 결과는 Date를 문자열로 바꾸고 undefined를 제거합니다. "객체를 그대로 JSON으로 저장했다"라고 생각하면 타입 손실과 필드 누락을 뒤늦게 발견하기 쉽습니다.
즉 "JS object를 들고 있다"와 "표준 JSON text를 들고 있다"는 다른 상태입니다. 둘을 구분하지 않으면 JSON.parse()를 객체에 호출하거나, 이미 문자열인 값을 다시 JSON.stringify()하는 실수가 반복됩니다.
참고 링크
2 sources