Internet Explorer 8 의 네이티브 JSON

 

 

이 글의 제목을 보고 아셨을지 모르겠지만, Internet Explorer 8 은 Beta 2에서 네이티브 JSON 구문해석기능과 serialization 기능을 제공합니다. 이 새로운 네이티브 JSON 기능에 의해 Internet Explorer 8 은 AJAX 응용 프로그램을 빠르고 안전하게 실행할 수 있습니다.

JSON 란?

AJAX 개발자가 아닌 분들에게  약간의 배경 정보만을 제공하는 것을 양해해 주세요. JSON (JavaScript Object Notation) 은 단순하고 독해 가능한 데이터 교환 포맷으로, AJAX 응용 프로그램이 서버와 웹 응용 프로그램 사이에 데이터를 송신할 때에 자주 이용됩니다.

예를 들면, 연락처를 확인하기 위해 즐겨 찾기의 웹 메일 클라이언트에서 받는 사람을 선택했을 경우를 상상해 주세요. 서버는 이러한 데이터 스트림에서 브라우저로 실행되는 웹 응용 프로그램에 데이터를 송신할 수 있습니다.

     {

          "firstName": "cyra",

           "lastName": "richardson",

           "address": {

               "streetAddress": "1 Microsoft way",

                "city": "Redmond",

                 "state" : "WA",

                "postalCode": 98052

          },

          "phoneNumbers": [

               "425-777-7777", 

                "206-777-7777"

           ]

     }

다행히도, 이 포맷은 JavaScript 와 구문적인 호환성이 있습니다. 많은 응용 프로그램이 현재는 데이터 페이로드를 JavaScript 개체로 변환할 때에 JavaScript 의 eval() 을 사용합니다. eval() 을 사용하는 방법은 위험한 접근 방식입니다. eval() 은 문자열을 일반적인 JScript 의 표현으로 해석하여 실행합니다. 만약eval() 에게 건네지는 문자열에서 변경이 있는 경우, 예상치 않는 데이터나 다른 누군가의 코드가 포함되어 있을지도 모르고, 이것이 웹 응용 프로그램에 삽입될지도 모릅니다.

JavaScript 에서 기술되어 신뢰할 수 없는 JSON 페이로드를 보다 안전하게 분석하기 위해서 설계된 라이브러리가 있습니다. 몇가지 라이브러리는 JScript 에서 기술된 파서를 사용하여, 데이터 페이로드에 대해서, 엄격한 유효성 검사를 실행합니다 (https://www.json.org/json_parser.js) . json2.js 과 같은 몇가지 라이브러리는 정규 표현을 이용하여 입력된 문자열의 안전성 체크를 실행한 후, 고속eval() 을 이용한 분석을 실행합니다. 이상적인 해결책은 빠르게 어디에서나 이용할 수 있는 코드 인젝션에서 응용 프로그램을 보호하는 네이티브 구현입니다.

Internet Explorer 8 JScript 의 네이티브 JSON

현재 Internet Explorer 8 에 탑재된 JScript 엔진은 ES3.1 Proposal Working Draft (영어) 의 JSON  지원과 호환성을 유지하면서, 직렬화(serialize), 역직렬화(deserialize) 라는 serialization 속도를  크게 개선하여, 신뢰할 수 없는 페이로드 분석의 전체적인 안전성을 개선한 완전한 네이티브 JSON 를 구현합니다.

API

새로운 내장 개체인 JSON 를 정의했습니다. 개체는 변경이나 치환 (override)이 가능합니다. 그것은 math 나 그 외의 고유한 글로벌 개체와 같습니다. 또 JSON 개체에 추가하고, Date, Number, String, boolean 개체의 프로토타입에 toJSON() 라는 특별한 함수를 추가했습니다. JSON 개체 자체는 parse()stringify() 라는 두 개의 함수를 가지고 있습니다.

예시:

var jsObjString = "{\"memberNull\" : null, \"memberNum\" : 3, \"memberStr\" : \"StringJSON\", \"memberBool\" : true , \"memberObj\" : { \"mnum\" : 1, \"mbool\" : false}, \"memberX\" : {}, \"memberArray\" : [33, \"StringTst\",null,{}]";

var jsObjStringParsed = JSON.parse(jsObjString);

var jsObjStringBack = JSON.stringify(jsObjStringParsed);

parse() 메서드에서 생성되어 stringify() 메서드에서 직렬화 가능한 개체는 다음과 같습니다. 

var jsObjStringParsed =

{

    "memberNull" : null,

    "memberNum" : 3,

    "memberStr" : "StringJSON",

    "memberBool" : true ,

    "memberObj" :

     {

                "mnum" : 1,

                "mbool" : false

    },

    "memberX" : {},

     "memberArray" :

     [

                 33,

                "StringTst",

                null,

                 {}

     ]

};

JSON.parse(source, reviver)

JSON.parse(source, reviver) 메서드는 역직렬화(deserialize)를 실행합니다. 이것은 JSON 포맷의 문자열 (source 인수에 의해서 주어집니다)을 처리하여, JScript 개체 또는 배열을 생성합니다.

옵션 reviver 인자 는 분석 후의 동작을 변경하기 위한 사용자 정의 기능입니다. 생성된 개체나 배열은 재귀적으로 통과되어 reviver 의 내용은 모든 멤버에 적용됩니다. 각각의 멤버 값은 reviver 가 반환하는 값에 의해서 바뀌는 .reviver 가 null 를 반환하면, 그 개체의 멤버는 삭제됩니다. reviver 호출과 통과는 처리 실행 후에 행해집니다. 어느 개체도 그 모든 멤버가 「업데이트됨」후에「업데이트 됨」 것입니다.

reviver 는 주로 ISO 적인 문자열을 인식하여 Date 개체로 변환하는데 사용됩니다. 현시점에서는 JSON 포맷 (영어) 의 Date 리터럴에 대해서 JScript  표준이 없기 때문에, Date 개체에 관해서는 가역적이지는 않습니다. ES3.1 draft (영어) 에는  reviver 를 사용하여 이 문제를 해결하기 위한 예가 있습니다.

JSON.stringify(value, replacer, space)

이것은 직렬화(Serialization)를 실행하는 메서드입니다. value 인수에서 지정된 개체 또는 배열을 처리하여 JSON 포맷의 문자열을 생성합니다. value 로서 주어진 개체 또는 배열은 재귀적으로 검사되어 JSON 포맷 (영어) 에 따라서 직렬화(Serialization) 됩니다. value 에 'toJSON()'메서드가 포함된 경우, 이것은 최초의 필터로서 기능합니다.  원래의 value는 value.toJSON(key) 에서 바꾸어지고 , 그 결과 값이 직렬화(Serialization) 됩니다. 여기서 인수key 는 문자열에서, (key : value) 와 같은 개체의 멤버를 직렬화(Serialization)하는 경우, 멤버이름으로서 key 입니다. 루트 개체에서는 key 는 비어 있는 문자열입니다.

Date.prototype.toJSON() 은 이스케이프 해야 할 캐릭터를 포함하지 않는 안전한 문자열을 생성합니다. stringify() 는 원래 문자열을 변경하지 않고 그대로 반환하기 때문에 이것이 사실상 직렬화(Serialization) 기능으로 동작합니다. Date 개체는 toJSON() 메서드를 경유하여 직렬화(Serialization) 됩니다.

Number.prototype.toJSON() ,String.prototype.toJSON() ,Boolean.prototype.toJSON() 은 ValueOf()를 반환합니다. 이것들은 "var num = new Number(3.14);" 와 같은 개체를 적정하게 직렬화(Serialization)하는 것을 의도합니다.

옵션 인수 replacer 는 필터로서 동작하여, 재귀적으로 적용됩니다. 이 인수에는 함수 또는 배열을 사용할 수 있습니다. replacer 가 함수인 경우, replacer(key,value) 는 개체 멤버인 key:value 의 각각에 대해 작용합니다. 루트 개체에 대해서는 replacer("",value)를 호출합니다. replacer 가 배열의 경우, 그 배열은 문자열 배열이 되어야 합니다. 배열 요소는 직렬화(Serialization) 대상이 되도록 선택된 멤버이름입니다. 직렬화(Serialization) 순서는 배열중의 이름 순서가 됩니다. 배열 replacer 는 배열을 직렬화(Serialization)할 때는 무시됩니다.

옵션 인수 space 는 출력하는 텍스트의 포맷을 지정합니다. 이 인수가 생략되면, 텍스트는 여분의 공백을 포함하지 않게 압축됩니다. 숫자가 지정되면, 텍스트는 계층별 지정된 수의 공백문자로 들여쓰기 됩니다. '\t'나 ' '와 같은 문자열이 지정되면, 계층별 들여쓰기에 지정한 문자가 사용됩니다.

기존 페이지 미치는 영향

JSON 에 관한 ESS 3.1 제안은 널리 이용되는 json2.js 를 이용한 폼 요소 (form factor)입니다. 우리도 JSON 이름은 상속합니다. 글로벌 JSON 개체는 치환 (override) 가능합니다. 그리고 더 이상 정의되지 않는 개체가 아닙니다. 개발 언어에 새로운 키워드를 도입했을 경우와 같이 이름을 상속하여 기존 코드에 대해서 영향을 미칠지도 모릅니다. json2.js 를 사용하여 생성된 페이지가 영향을 받을 가능성은 거의 없습니다. 극히 일부의 예외를 제외하고, 모든 페이지가 빨라지면서,  지금 그대로 계속 동작합니다.

JSON 개체의 private 구현이 정의된 페이지, 특히 "if(!this.JSON) { JSON=…}". 이러한 패턴에서 JSON 개체의 구현이 정의되어 있으면 영향을 받을 가능성이 있습니다. 이런한 문제에 대한 대처 방법은 크게 두가지 선택사항이 있습니다.

1. 기존의 코드를 네이티브 JSON 지원을 사용하도록 마이그레이션 한다

몇가지 버전의 json2.js 를 기본으로 하여,  private JSON 구현을 한 경우, 매우 간단하게 마이그레이션할 수 있습니다.

2. 네이티브 JSON 지원을 옵트아웃(opt out)하여, 기존의 JSON 개체를 계속 이용한다

이것은 JSON 의 이름 변경, 혹은 오버라이드(override) 하여 실행할 수 있습니다. 이름 변경은 모든 코드상에서 이용되는 "JSON" 이라는 이름을 "MyJSON" 과 같이 다른 이름으로 변경하는 것을 의미합니다. 오버라이드(override) 의미는 모든 private JSON 정의를 기본값의 JSON 정의로 바꾸기 것을 의미합니다. 대부분의 경우,"if(!this.JSON)" 를 없애면 잘 됩니다.

ES3.1 의 표준화 노력을 생각하면, "JSON" 이름을 사용하는 것은 정의에 관한 인터페이스의 상호 운용성을 확보했다는 우리의 희망과 일치합니다.

네이티브 JSON에 대해서는 할 말이 많이 있습니다. 파서는 eval()를 기본으로 하는 것이 아니라, 독자적으로 구현합니다.  JSON 지원 (영어) 에서 제공되는 레퍼런스 파서와 동등합니다. 그것은 https://www.json.org/json_parser.js 와 같은 정도로 안전하고, 상당히 빠릅니다. 만약 eval()나 독자적인 JSON 라이브러리를 사용한다면, 성능과 안전성을 향상시키기 위해서 Internet Explorer 8 에 탑재된 네이티브 구현을 검토해 주세요.

Corneliu Barsan
Senior Developer
JScript team

 

* 이 글은 Internet Explorer 개발 팀 블로그 (영어)의 번역 문서입니다. 이 글에 포함된 정보는 Internet Explorer 개발 팀 블로그 (영어)가 생성된 시점의 내용으로, 제품의 사양이나 기능이 보장되는 것은 아닙니다. 이 글에 포함된 정보의 이용은 사용 조건을 참조해 주세요. 그리고, 이 글 게재 시점에서 Internet Explorer 개발 팀 블로그 (영어)의 내용이 변경될 수 도 있습니다. 최신 정보는 Internet Explorer 개발 팀 블로그 (영어)를 참조하십시오. 

영문 원본 : Internet Explorer 8 의 네이티브 JSON

업데이트 일: 2008 년 9 월 10 일