JSON 은 왜 그모양일까 ?
JSON의 정의와 관련된 ECMA-404 문서를 통해 숫자 문자열 '900101'이 JSON으로 인식되는 이유를 자세히 알아봅니다.
Contents
이것은 JSON 일까 ?
JSON 관련된 코드를 테스트 하다, 예상과 다른 코드의 동작 때문에 장애를 낼 뻔한 적이 있다. 다음의 코드를 살펴보자
const is = {
  jsonString: (str: string) => {
    try {
      JSON.parse(str);
    } catch (e) {
      return false;
    }
    return true;
  }
}
const birthday = '900101';
if(is.jsonString(birthday)) {
  throw new Error(`${birthday} is JSON`);
}
위의 코드를 실행하면 에러가 발생할까 ? 놀랍게도 위의 코드는 에러를 발생시키는 코드이다.
처음에는 자바스크립트는 왜 그 모양일까 ? 책에 나올법한 또다른 자바스크립트의 버그일 것이라 생각했다. 하지만 python의 json 내장 라이브러리, 자바/코틀린의 jackson-databind 라이브러리 모두 동일한 동작을 하는 것을 확인했다. 어떠한 이유로 900101 은 JSON 인 것일까 ?
ECMA-404
json.org 문서를 읽어보다, ECMA-404 문서에 JSON 의 정의가 명시되어 있다는 힌트를 얻었다. ECMA-404 (2nd Edition) 공식문서를 찾았고, 위의 문제에 대한 실마리를 찾을 수 있었다.

핵심적인 내용을 정리하면 다음과 같다.
- A JSON text is a sequence of tokens formed from Unicode code points that conforms to the JSON value grammar. The set of tokens includes six structural tokens, strings, numbers, and three literal name tokens.
 - A JSON value can be an object, array, number, string, true, false, or null. 
(각 값들의 정의는 
ECMA-404문서에 구체적으로 정의되어 있으니 참고) 
위의 정의에 명시된 six structural tokens 은 다음과 같다.
[ U+005B left square bracket
{ U+007B left curly bracket
] U+005D right square bracket
} U+007D right curly bracket
: U+003A colon
, U+002C comma
three literal name tokens 는 다음과 같다.
true U+0074 U+0072 U+0075 U+0065
false U+0066 U+0061 U+006C U+0073 U+0065
null U+006E U+0075 U+006C U+006C
정리해 보면, JSON 은 JSON value 문법을 지키는 문자열(JSON text)을 의미하며, JSON text 는 six structural tokens, numbers, three literal name tokens 이다. 어떠한 문자열이 위의 2가지 정의를 만족한다면, 그 문자열은 JSON 집합에 들어간다.
ECMA-404 요약
- JSON String 이란, 다음의 성질을 만족하는 유니코드의 set 이다.
 - 각 유니코드는 다음의 문자 중 하나여야 한다.
[,],{,},:,,,true,false,null,string,numbers
 - 유니코드의 집합은, JSON Values 문법에 따라야 한다.
 - JSON Values 란 object , array , number , string , true , false , null
 - insignificant 한 공백은 각 유니코드 앞뒤에 추가될 수 있다
 
다시, 이것은 JSON 일까 ?
ECMA-404 의 정의를 토대로, 다음의 값들을 판별해 보자.
/** true */
is.jsonString(1234);
is.jsonString('"abcd"');
is.jsonString(null);
is.jsonString(true);
/** false */
is.jsonString('abcd');
이때, 가장 마지막 조건인 'abcd' 는 JSON 이 아니다. 이 또한 ECMA-404 에서 그 근거를 찾을 수 있다.

A string is a sequence of Unicode code points wrapped with quotation marks (U+0022). 
따라서, '"abcd"' 는 JSON 이지만, 'abcd' 는 올바른 JSON 이 아니다.
이것도 읽어보세요