여러분께 퀴즈를 내보겠습니다. 첫 번째 문제! 아래의 JSON 파일은 올바른 JSON 형식일까요?
// data.json
{
"version": 1
}
정답은 그렇다 입니다. 우리가 잘 알고 있는 객체 형태의 데이터이니까요. JSON을 한 번이라도 사용해 본 사람이라면 이것은 쉽게 맞출 수 있었을 것입니다.
그렇다면 아래의 JSON 파일은 어떨까요? 딸랑 숫자 1
하나만 들어있는 JSON 파일입니다.
// data.json
1
여기서 조금 헷갈리는 분이 있으실 것 같은데요, 정답은 올바른 형식 입니다. 왜냐하면 JSON 스펙에 그렇게 정의되어 있기 때문입니다. 이 내용은 MDN 문서에도 나와 있는데요.
JSON은 JSON 내부에 포함할 수 있는 모든 형태의 데이터 타입을 취할 수 있습니다. 즉, 배열이나 오브젝트 외에도 단일 문자열이나 숫자 또한 유효한 JSON 오브젝트가 됩니다.
1
뿐만 아니라 "hello"
, null
도 올바른 JSON 형식으로 뜬다
실제로 그런지 온라인 JSON 유효성 검사기 사이트에 들어가 문자열, 불리언, null
같은 값을 넣어보니 올바른 JSON 형식으로 인식하는 것을 확인할 수 있었습니다.
그렇다면 이 JSON 파일을 JavaScript 코드에서 바로 불러오는 것도 가능할까요?
import version from './data.json';
console.log(version); // 1?
정답은 잘 동작한다 입니다. 해당 JSON 파일의 문법은 JavaScript 문법의 부분 집합(subset)이기도 하니까요. 어때요, 앞선 세 문제를 모두 맞히셨나요? 그렇다면 여러분은 JSON의 고수이시군요.
사실 저는 여태껏 JSON의 최상위 레벨에 배열 또는 객체가 와야 한다고 잘 못 알고 있었습니다. 그래서 단순히 숫자로 구성된 JSON도 올바른 JSON 형식이라고는 생각을 못 했었죠.
깜짝
그런데 사실 최초의 JSON 스펙에서는 최상위 레벨에 오직 배열 또는 객체만 올 수 있었다는 사실을 알고 계셨나요? 저도 검색하다가 알게 된 사실인데요, 여기서 호기심이 생겨서 JSON의 역사를 찾아보았는데 치열한 막장 드라마 한 편을 또 찾게 되어 어러분에게 소개 시켜 드리려고 합니다.
이번 글을 통해 JSON 표준의 등장 과정과 스펙의 변화에 대해 궁금하신 분들에게 도움이 되었으면 좋겠습니다.
TL;DR
- IETF에 올라온 최초의 JSON 제안에서는 최상위 레벨에 배열이나 객체만 올 수 있었다.
- ECMA 인터내셔널에서 위 규칙을 독단적으로 수정한 후 표준으로 발표했고, IETF도 이를 따르게 되었다.
- 업계에 두 개의 JSON 표준이 존재하면서 두 조직 간에도 트러블이 있었지만 현재는 원만한 합의를 통해 현재에 이르고 있다.
JSON의 등장
JSON(JavaScript Object Notation) 은 더글라스 크락포드(Douglas Crockford)가 2001년에 고안한 데이터 저장 및 교환을 목적으로 하는 텍스트 전용 형식입니다.
XML은 일단… 너무 못 생겼고 태그 열고 닫는 거도 귀찮음
JSON이 등장하기 전까지는 데이터를 저장할 때 XML(eXtensible Markup Language) 형식을 주로 사용하곤 했습니다. 웹 개발에서 비동기 통신을 사용할 때 자주 언급되는 AJAX(Asynchronous JavaScript and XML) 의 X가 XML을 의미하는 것만 봐도 당시의 대세(?)를 짐작할 수 있었죠.
하지만 XML은 마크업 언어의 특성을 계승하다 보니 문법이 복잡하고 장황하다는 특징이 있었습니다. 간단한 데이터를 저장할 때에도 태그를 여닫으며 수십 줄의 코드를 작성해야 했으니 여간 비효율적인 게 아니었죠.
반면 JSON은 그 이름에서 알 수 있듯이, JavaScript 문법에 강하게 영향을 받은 형식입니다. 정확하게는 ECMAScript 3에서 정의하는 문법의 부분집합(subset)이죠.
그래서 일반적인 JSON은 JavaScript에서 객체 리터럴 그 자체와 거의 동일합니다. 다만 JavaScript의 모든 데이터 타입을 다를 수 있는 것은 아니고, 문자열(String), 숫자(Number), 불리언(Boolean), 널(null) 외에도 배열(Array)과 객체(Object) 정도를 표현할 수 있었죠.
물론 당시에는 아직까지 XML이 대세였고 JSON이 표준이 아니라는 이유로 JSON 도입을 꺼리는 곳이 많았습니다. 이에 열받은(?) 크락포드는 ‘표준이 없어서 문제라면 내가 직접 표준을 만든다!’ 라는 생각으로 json.org라는 웹 사이트를 만들었죠.
크락포드가 직접 만든 JSON 스펙. 지금은 여러 언어로 번역되어 있다.
사실 지금 보기에는 표준이라 하기에는 민망하기도 한데, 공신력 있는 단체에서 인증을 받은 게 아니라 개인 웹사이트에 본인이 정의한 JSON 문법을 정리해 올린 것이 전부였기 때문이죠.
그럼에도 불구하고 간단한 문법과 높은 호환성으로 인해 JSON은 JavaScript 뿐만 아니라 다양한 프로그래밍 언어에서도 사용될 만큼 널리 퍼지기 시작했고, 입소문을 탄 JSON은 XML을 조금씩 대체해 나가기에 충분했습니다.
RFC 4627
다만 크락포드가 만든 JSON 형태의 데이터를 HTTP를 통해 주고받을 방법은 따로 없었습니다. 왜냐하면 이것은 IETF(Internet Engineering Task Force, 국제 인터넷 표준화 기구) 라는 단체를 통해 표준화를 거쳐야 하는 문제였기 때문이죠.
그래서 크락포드는 2006년, HTTP의 Content-Type
헤더에 올 수 있는 미디어 타입(MIME)에 application/json
를 추가하는 제안서를 작성하게 됩니다. 이것이 바로 RFC 4627 입니다. 일반적으로 JSON의 최초 스펙이라고 알려져 있는 문서이지만 사실은 JSON을 HTTP를 통해 전송하기 위한 MIME 타입을 정의한 문서입니다.
MIME 타입을 정의하는 문서라고 제목에 분명히 나와 있다
해당 문서를 살펴보면 JSON 문법에 대한 정의도 함께 포함되어 있는데, 여기서는 최상위 레벨에 배열 또는 객체만 올 수 있다고 명시되어 있습니다.
최초 제안에는 JSON 최상위 레벨에는 배열 또는 객체만 올 수 있다고 명시되어 있다
즉 최초 스펙 상으로는 숫자 1
이 올바른 JSON 형식이 아니었던 것이죠. 이 외에도 자잘한 차이점이 있었지만 사용법이 지금과 크게 다르지는 않습니다.
이처럼 RFC 4627은 JSON 스펙이 IETF에 공식적으로 제안된 문서라는 점에서 의의가 있습니다만… 몇 가지 문제점이 있었습니다.
가장 큰 문제점은 이 RFC 문서가 informational
상태로 작성되었다는 점입니다. IETF에서는 누구나 제안서를 작성할 수 있고, 이 제안서를 RFC(Request for Comments) 라고 부릅니다. 각 제안서에는 상태(status)라는 것이 존재하는데, 이 상태에 따라 제안서의 목적이나 의의가 크게 달라집니다.
크락포드는 RFC 4627을 informational
상태로 설정했는데, 이 상태의 문서는 표준화가 주목적이 아니라 단순 정보 전달이 목적이라서 커뮤니티의 피드백을 받는 과정이 전혀 없습니다. 어느 정도냐면 만우절 농담으로 작성된 글이 informational
상태입니다. 비유를 하자면 인터넷 커뮤니티의 자유 게시판에 JSON 스펙이라고 글을 작성해 놓고 ‘이게 표준 문서다’ 라고 주장하는 것과 정도의 급(…)이죠.
보통 이렇게 널리 사용되는 기술의 스펙을 정의하는 경우라고 하면 standard track
, 즉 표준 트랙 상태로 제안을 하는 것이 일반적이거든요. 그러면 커뮤니티의 피드백을 받아 문서가 계속 수정되고 보완되면서 proposed
, draft
, standard
등의 상태로 변경되는 것이죠. IETF 입장에서는 자기네 피드백을 받지 않은 일개 제안서 따위(?)가 표준처럼 여겨지고 있으니 불편했을 것입니다.
이 외에는 객체의 중복 키를 허용한다거나, 깨진 유니코드 문자열을 허용한다는 등의 문제가 있었는데 이것은 차후 문서에서 수정이 되었습니다.
ES5.1
ES5.1에서는 RFC 4627을 참조하지만, JSONObject나 JSONArray 외에도 JSONValue가 올 수 있다고 명시되어 있다
그러던 2011년, ECMA 인터내셔널이라는 단체에서 스크립트 언어의 표준을 지정하는 ECMA 262의 5.1 버전을 발표됩니다. 조금 쉽게 설명하자면 JavaScript를 비롯한 스크립트 언어에서 구현해야 할 스펙에 대한 문서인데요.
ECMAScript, JavaScript의 용어가 헷갈린다면 이 글을 참고해 주세요.
이 ECMA 262에서 JSON 스펙을 구현할 때, RFC 4627을 참조하라고 명시를 해둔 것이죠. informational
상태의 RFC를 참조하라고 한 것은 그렇다 치는데, 심지어 일부 스펙은 따르지 말고 수정을 하라고 이야기하기(?)까지 합니다.
위 사진에서 목록의 첫 번째 내용을 살펴보면 되는데요, 분명히 JSONObject
나 JSONArray
외에도 JSONValue
가 올 수 있다고 명시되어 있습니다. 즉 최초 표준과 구현체가 서로 달라지는 문제가 발생한 것이죠. 참고로 목록의 두 번째 내용에서는 JSON이 아닌 형식과 확장자를 어떻게 처리할 지에 대한 내용이 다르게 명시되어 있네요.
갑작스러운 경쟁(?)
갑자기 분위기 싸해지는 거임
이 상황을 지켜보는 IETF는 기분이 어떨까요? informational
RFC이긴 하지만 어쨌든 자기네 쪽에 제안된 내용을 ECMA 인터내셔널이 가져다가 고쳐가며 쓰고 있으니 심기가 불편하겠죠.
그래서 IETF는 2013년 1월, RFC 4627을 개정하려는 목적으로 JSON 워킹 그룹이라는 것을 만듭니다. 크록포드 역시 이 개정판 작성에 참여를 하게 됐지만, IETF의 업무 처리 프로세스가 혼란하다는 이유로 결국 중도 포기를 하게 됩니다. 이 작업은 당시 구글에서 일하던 팀 브레이(Tim Bray)라는 개발자가 이어받게 됩니다.
JSON에 대한 표준이 IETF와 ECMA 인터내셔널이라는 서로 다른 두 조직에서 각자 다른 방식으로 제안되자 분위기가 이상해지기 시작합니다. 어느 순간부터 누가 먼저 JSON 공식 표준을 발표하는가 에 대한 경쟁이 시작된 것이죠.
두 단체의 갑작스러운(?) 경쟁 분위기 속에서 과연 누가 먼저 JSON 표준을 발표했을까요?
ECMA 404
명목 상 승자는 ECMA 인터내셔널이었습니다. EMCA 인터내셔널은 2013년 10월에 ECMA 404라는 JSON 형식에 대한 문서를 발표합니다. IETF에서 JSON 워킹 그룹을 구성한 지 10개월 만이었죠.
여기에 대해 브레이는 자신의 블로그에서 이를 강하게 비난했습니다.
“우리는 마치 새끼 고양이들 싸움 같은 우스운 전쟁을 펼쳤다. 누군가 ECMA 인터내셔널에 ‘IETF가 미쳐버려서 JSON 표준을 완전히 새로 작성해 인터넷 세계를 붕괴시킬 것이다’ 고 말한 모양이다. 그렇지 않고서야 ECMA 인터내셔널은 이렇게 훨씬 빠른 속도로 내달리면서 JSON 표준을 발표하지 않을 이유가 없다.”
“심지어 이 표준은 너무 빨리 발표하느라 극도로 단순한 문법만 다루고 있고 JSON의 의미에 대해선 다루지도 않고 있다. RFC 4627을 개정해야 하는 이유에 대해서는 아무런 언급도 못 하고 있다.”
꽤나 살벌하죠…? ECMA 404는 이러한 분위기 속에서 발표된 문서입니다. 브레이의 말이 맞는 것 같기도 한 게, 실제로 ECMA 404 문서를 읽어보면 진짜로 별 내용이 없습니다. 목차랑 빈 페이지 제외하면 A4 6장 분량이거든요.
유한 상태 머신 비스무리하게 그림이 있어서 읽기는 편하다
아무튼 ECMA 404에서는 JSONValue
라는 값을 위와 같은 그림으로 정의합니다. 문서 자체에 최상위 레벨에도 JSONValue
가 올 수 있다는 것이 명시되어 있군요!
RFC 7159
RFC의 제목도 바뀌었고, 표준 트랙에도 진입해서 proposed
까지 달성했다
ECMA 인터내셔널보다 한 발 늦은 IETF이지만, 곧바로 2014년 3월에 RFC 7159를 발표합니다. 이번에는 저자가 팀 브레이로 되어 있고, 표준 트랙에도 진입할 수 있도록 제안을 작성하였습니다.
두 번째 제안부터는 JSON 최상위 레벨에 값(Values)이 올 수 있다고 명시되어 있다
RFC 7159부터는 ECMA 404와 마찬가지로 JSON의 최상위 레벨에 값(Values) 이 올 수 있다는 내용이 추가되었습니다. 친절하게도 ‘이전 버전의 JSON 사양에서는 객체나 배열만 올 수 있었음에 주의하라’ 라고 알려주고 있네요. 이것은 아무래도 ECMA 404의 영향을 받지 않았을까 싶긴 합니다.
참고로 RFC 7159의 레퍼런스에는 ECMA 262와 ECMA 404가 함께 걸려있는 것을 확인할 수 있습니다. 레퍼런스로 우리를 뒤통수친 조직 이름을 걸어줘야 한다니… 브레이 형님이 많이 빡치셨겠는걸요.
ES6
그로부터 1년이 지났습니다. 2015년이죠, 우리가 잘 알고 있는 ES6가 발표된 해입니다.
ECMA 262에서 기존에 RFC 4627을 참조하던 부분이 ECMA 404를 참조하도록 변경되었습니다. 아무래도 자기네들이 만든 표준이니까… 밀어주는 것이겠죠.
사실상 JSON 최상위에서 값을 바로 쓸 수 있다는 스펙 자체는 RFC 7159부터 이미 통일되었는데, 표준 전쟁으로 생긴 감정적 불편함(?)이 더 메인 소재가 되는 걸 느꼈다면… 여러분이 잘못 느낀 게 아닙니다. 실제로 이런 일이 있었다구요! 아무튼 이런 사건 때문에 IETF와 ECMA 인터내셔널 사이에서는 냉전이 지속되고 있었습니다.
RFC 8259와 ECMA 404 개정판
그러다가 2017년, IETF의 새로운 JSON 표준 제안인 RFC 8259와 ECMA 인터내셔널의 ECMA 404 개정판이 거의 동시에 나옵니다.
새로운 개정판이 나오게 된 이유는 여러 시스템 간 JSON 데이터를 주고받아야 할 경우 ‘텍스트의 인코딩을 UTF-8으로 유지한다’ 는 내용이 추가되는 간단한 수정 때문이었습니다. 하지만 두 표준의 수정 내용이 동일하고, 발표 일자도 거의 동일한 것을 보니 분명 두 조직 사이에 무슨 이야기가 오간 것 같은데요…
브레이에 따르면 실제로 두 조직 간의 합의가 있었다고 합니다.
“IETF와 ECMA 인터내셔널 사이에서 두 표준이 충돌할 여지가 있다. 그래서 우리는 서로 간의 표준을 오랜 시간 동안 검토한 후, 쌍방의 표준을 서로 참조하기로 하고 오류가 있는 경우에는 일관성을 유지하기로 했다.”
ECMA 404에도 IETF의 RFC가 걸리면서 일단은(?) 원만한 합의를 하셨다
다만 브레이가 자기 블로그에서 ECMA 인터내셔널을 깡패(…)라고 부르는 걸 보니 아직까지 마음이 상한 게 다 회복되진 않았나 봅니다.
해당 시점 이후로 JSON의 스펙은 현재까지 변함이 없고 이것이 오늘날까지 이르고 있습니다.
마무리
난 그냥 JSON 기능이 왜 없어졌는지 살펴보려고 했는데 이런 막장 드라마가 숨겨져 있을 줄은…
저는 사실 그냥 숫자 1
이 올바른 JSON 형태인지가 궁금했던 것인데… 이런 뒷소식을 알게 되니 재밌었습니다. JSON의 최상위 레벨에서도 모든 데이터 타입을 쓸 수 있다 라는, 그냥 담백한 기술적 설명에 대해서도 이런 이야기를 알아낼 수 있다는 것이 참 신기하기도 하구요. 뭔가 들여다보면 안 되는 심연(?)을 본 것 같기도…?
내가 지금 당연하게 쓰고 있는 기술도 알고 보면 수많은 이해 당사자 간의 치열한 다툼과 경쟁, 합의를 거쳐 나온 결과물이라는 것을 새삼 깨닫게 되었습니다. 아무튼 브레이 형님이 지금은 멘탈을 잘 추슬렀길 바라면서 글을 마무리하겠습니다.