제공: 한빛미디어 네트워크 기사
저자: Stefan Goessner, 한동훈 역
보다 많은 웹 서비스 제공업체들은 자사의 XML API에
JSON API를 제공하려 하는 것 같다. JSON API를 사용할 때 얻을 수 있는 가장 큰 장점은
XmlHttpRequest 객체가 동일 도메인에서만 사용할 수 있다는 제한을 우회해서
다른 도메인간의 요청(cross-domain requests)을 제공할 수 있다는 점이다. 클라이언트 단에서 JSON은 네이티브 언어와 호환되는 데이터 구조를 갖게 되며, XML 처리를 위해 필요한 DOM 호출 보다 훨씬 더 빠르게 수행된다. 마지막으로, JSON 구조를 화면에 표시하기 위한 데이터로 변환하는 것도
JSONT와 같은 도구를 사용해서 쉽게 할 수 있다.
만약, 이 분야에서 일하고 있다면, 다음 정보들을 유지하면서 기존 XML 문서를 JSON 구조로 변환해야 할 필요가 있을 것이다.
이상적인 세상이라면 생성된 JSON 구조는 원본 XML 문서로 쉽게 역변환할 수 있을 것이다. 따라서, XML과 JSON의 양방향 변환에 대한 기초적인 내용들을 기본 패턴으로 논의할 필요가 있다. 이와 비슷한 논의는
BadgerFish와
야후에서 찾을 수 있다.
실용주의 접근
파일 하나로 구성된 XML 문서의 요소들은 다음과 같은 7가지 특징을 갖는다.
- 빈 요소
- 순수 텍스트로 구성된 요소
- 속성을 갖는 빈 요소
- 순수 텍스트와 속성으로 구성된 요소
- 다른 이름으로 된 요소들을 포함하는 요소
- 같은 이름으로 구성된 요소들을 포함하는 요소
- 요소와 연속된 텍스트를 포함하는 요소
다음 테이블은 XML과 JSON 사이에 변환 패턴을 정리한 것이다.
Pattern
|
XML
|
JSON
|
Access
|
1 |
|
"e": null
|
o.e
|
2 |
text
|
"e": "text"
|
o.e
|
3 |
|
"e":{"@name": "value"}
|
o.e["@name"]
|
4 |
text
|
"e": {
"@name": "value",
"#text": "text"
}
|
o.e["@name"]
o.e["#text"]
|
5 |
text
text
|
"e": {
"a": "text",
"b": "text"
}
|
o.e.a
o.e.b
|
6 |
text
text
|
"e": {
"a": ["text", "text"]
}
|
o.e.a[0]
o.e.a[1]
|
7 |
text
text
|
"e": {
"#text": "text",
"a": "text"
}
|
o.e["#text"]
o.e.a
|
패턴7의 요소가 반구조화된 요소(Semistructured element)로 알려져있지만, 모든 패턴들은 구조화된 요소들을 기술하기 위한 것이다. XML 문서를 JSON 구조로 변환하거나 그 반대로 변환하기 위한 실용주의 접근은 위의 7가지 패턴에 기초한다. 항상 정규화된 XML 문서가 입력된다고 가정하며, 다음과 같은 경우는 고려하지 않는다.
- XML 선언
- 처리 명령(processing instruction)
- 네임스페이스 선언의 명시적인 처리
- XML 주석
순서 보존하기
JSON은 두가지 내부 자료구조로 구성되어 있다.
- 유일한 이름으로 된 이름/값 쌍의 집합(연관배열)
- 값들의 정렬된 리스트(배열)
다음과 같이 구조화된 XML 문서는
some
textual
content
다음과 같은 JSON 객체로 변환하는 시도는
"e": {
"a": "some",
"b": "textual",
"a": "content"
}
잘못된 결과를 만들어 낸다. "a"는 연관 배열에서 유일한 이름이 아니다. 따라서, 배열에서 같은 이름을 갖는 모든 요소들을 모아야 한다. 패턴 5와 6을 사용해서 다음과 같은 결과를 만들어 낼 수 있다.
"e": {
"a": [ "some", "content" ],
"b": "textual"
}
이제, 요소 순서를 보존하지 못하게 된 구조를 갖고 있다. 이 결과는 XML 요소의 순서가 중요한가에 따라 허용할 수도 있고, 허용할 수 없는 것이 될 수도 있다.
따라서, 우리의 일반적인 목표는 다음과 같다.
다음 조건을 만족하는 경우에 한 해서 구조화된 XML 요소는 역변환이 가능한 JSON 구조로 변환할 수 있다.
- 모든 하위 요소가 정확히 한 번만 등장하거나 또는…
- 동일한 이름(identical names)을 갖는 하위 요소들이 순차적으로 나열된 경우
그리고
다음 조건을 만족하는 경우에 한해 구조화된 XML 요소는 역변환 가능하며, 의미적으로도 동일한 JSON 구조로 변환할 수 있다.
- 같은 이름을 같지만 의미는 다른 하위 요소들(homonymous subelements)이 순서에 관계없이 등장하는 경우와 …
- 요소들의 순서가 중요하지 않은 경우
위 두가지 조건중에 어느 하나라도 만족하지 않는다면 앞에서 본 패턴을 사용해서 XML과 JSON을 변환할 수 있는 실용적인 방법은 없다. 내부적으로 요소들의 순서에 의존하는 SVG와 SMIL 문서를 살펴보자.
반구조화된 XML(Semi-Structured XML)
XML 문서는 일반적으로 문서 표기에서 흔히 볼 수 있는, 텍스트 내용과 자식 요소들의 혼합으로 구성된 반구조화된 요소들을 포함할 수 있다. 텍스트 내용은 다음과 같이 연속적일 수 있다.
some textual
content
패턴7을 적용해서 다음과 같은 결과를 얻을 수 있다.
"e": {
"#text": "some textual",
"a": "content",
}
그러나, 어떻게 하면 요소들과 혼합된 텍스트 요소를 변환할 수 있는가? 예를 들어:
some
textual
content
"e": {
"#text": ["some", "content"],
"a": "textual"
}
이는 배열에서 모든 텍스트 요소들을 수집하는 대부분의 경우에 아무 의미도 없으며, 순서나 맥락정보를 보존하지 않는다.
따라서, JSON에서 혼합된 반구조화된 문서를 다루는 가장 좋은 방법은 XML이 CDATA 섹션을 다루는 방법과 같은 방법을 사용하는 것이다. 즉, 알려지지 않은 표기법(markup)을 사용하는 것이다.
"e": "some textual content"
다음과 같이 구성된 XML 요소들의 규칙은
- 텍스트 내용과 요소 노드들로 혼합된 것과
- CDATA 섹션
패턴 2와 4에 따라 완전한 XML 표기법을 포함하고 있으며, 역변환 가능한 JSON 문자열로 변환할 수 있다는 점이다.
예제
지금까지 살펴본 내용을 토대로 두 가지 예제를 살펴보자.
마이크로포맷을 예제로 살펴볼 것이다. 마이크로포맷은 오픈 표준이며, 간단한 설명을 위해 사용할만큼 간결하기 때문에 예제로 가장 적합하다.
XOXO는 XHTML기반의 문서개요 포맷이며, 마이크로포맷중에 하나다. 다음은
초안에 있는 예제를 약간 수정한 것이다.
- Subject 1
- subpoint a
- subpoint b
- Subject 2
- subpoint c
- subpoint d
XML 문서 조각을 JSON 구조로 변환하기 위해 위 패턴을 적용해보자.
- 두 리스트 항목으로 구성된 바깥 요소는 패턴6을 사용해서 변환할 수 있다.
- 첫번째 리스트 항목은 하나의 텍스트 내용 "Subject 1"과 그 내부 리스트 요소로 구성되어 있다. 따라서, 패턴7에 따라 이를 처리할 수 있다.
- 첫번째 내부 리스트는 패턴 6에 따라 변환할 수 있다.
- 바깥쪽 목록의 두번째 항목은 패턴5를 적용한다.
- 두번째 내부 리스트는 패턴3과 6을 조합해서 변환할 수 있다.
변환된 JSON 구조는 다음과 같으며, 이 구조는 어떤 정보 손실없이 역변환이 가능하다.
"ol": {
"li": [
{
"#text": "Subject 1",
"ol": {
"li": ["subpoint a", "subpoint b"]
}
},
{
"span": "Subject 2",
"ol": {
"@compact": "compact",
"li": ["subpoint c", "subpoint d"]
}
}
]
}
hCalendar는
iCalendar 표준에 기반한 마이크로포맷이다. iCalendar 포맷이 JSON 포맷으로 더 쉽게 변환할 수 있다는 사실은 무시하고, hCalendar 이벤트
예제를 살펴볼 것이다. 이 예제는 혼합된, 반구조화된 문서 조각들을 포함하게 수정하였다.
Web 2.0 Conference
October 5
7
Argent Hotel, San Francisco, CA
패턴 2, 3, 4, 5, 6을 사용해서 다음 JSON 구조로 변환할 수 있다.
"span": {
"a": {
"@class": "url",
"@href": "http://www.web2con.com/",
"span": [
{ "@class": "summery", "#text": "Web 2.0 Conference" },
{ "@class": "location", "#text": "Argent Hotel, San Francisco, CA" }
},
"abbr": [
{ "@class": "dtstart", "title": "2005-10-05", "#text": "October 5" },
{ "@class": "dtend", "title": "2005-10-08", "#text": "7" }
}
}
}
이 예제는 원본 요소 순서를 보관하지 않고 변환한 것이다. 의미적인 순서는 바뀌지 않지만, 다음과 같은 내용을 고려해야 한다.
- 변환이 완전하지 않다는 것
- 순서가 중요하지 않은 경우라면 결과를 수용할 것
- XML 문서를 JSON으로 변환하기 쉬운 구조로 작성해보기
대부분의 경우에 있어서, 최소한 XML 문서가 이미 표준에 기초한 것인 경우 마지막은 수용하기 어려울 것이다. 그러나, 다른 경우라면 XML과 JSON을 보다 조화롭게 사용할 수 있도록 XML에 변화를 주는 것을 고려해볼 수 있다. hCalendar 예제에서
요소를 요소로 변환하는 것으로도 개선될 수 있다.
XML은 문서 중심 포맷이며, JSON은 구조화된 데이터를 위한 포맷이다. XML은 구조화된 데이터를 기술할 수 있기 때문에, 이 근본적인 차이점은 관계없는 것일 수 있다. XML은 구조화된 문서를 기술하기 위해 사용되기 때문에 JSON과 함께 사용할 수 있을 것이다.
XML 문서가 다음과 같은 경우에 문제가 일어날 수 있다
- 암시적으로 요소들의 순서에 의존하는 경우
- 반구조화된 데이터를 많이 포함하고 있는 경우
지금까지 설명한 내용을 증명하기 위해 위 6가지 패턴을 기반으로 다음과 같은 자바스크립트 함수 2개를 구현했다.
이들 함수는 다음과 같은 경우에 사용할 수 있다
- 클라이언트측 변환
- DOM을 통해 읽어들인 XML 문서를 JSON 구조로 변환
- JSON 구조를 XML 문서(텍스트형식)로 변환
- 어떤 서버측 언어에서도 사용할 수 있는 변환기의 구현
앞으로 나오게 될 XML 문서 설계는 XML과 JSON 양쪽에서 쉽게 사용할 수 있도록 이들 패턴 또는 이와 유사한 패턴의 영향을 받게 될 것이다.