ajax로 검색한 결과 :: 시소커뮤니티[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

회원가입 I 비밀번호 찾기


SSISO Community검색
SSISO Community메뉴
[카페목록보기]
[블로그등록하기]  
[블로그리스트]  
SSISO Community카페
블로그 카테고리
정치 경제
문화 칼럼
비디오게임 스포츠
핫이슈 TV
포토 온라인게임
PC게임 에뮬게임
라이프 사람들
유머 만화애니
방송 1
1 1
1 1
1 1
1 1
1

ajax로 검색한 결과
등록일:2008-04-02 15:10:12
작성자:
제목:자바 개발자를 위한 Ajax: Ajax용 자바 객체 직렬화 (한글)


ajax 애플리케이션에서 데이터를 직렬화 할 수 있는 다섯 가지 방법

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

이 페이지를 이메일로 보내기

이 페이지를 이메일로 보내기

토론


난이도 : 중급

Philip McCarthy, 소프트웨어 개발 컨설턴트, Independent Consultant

2005 년 10 월 04 일

Asynchronous JavaScript and XML(ajax)를 사용하여 자바 웹을 개발하고 있다면 서버에서 클라이언트로 데이터를 전달하는 일은 아마도 최고의 관심사일 것이다. Philip McCarthy는 다섯 가지 자바 객체 직렬화 방법을 설명하고 애플리케이션에 가장 잘 맞는 데이터 포맷과 기술을 선택할 때 필요한 것이 무엇인지를 설명한다.

이 시리즈의 첫 번째 글에서는 ajax의 구현 블록을 소개했다.

  • JavaScript의 XMLHttpRequest 객체를 사용하여 웹 페이지에서 비동기식 요청을 서버로 보내는 방법
  • 자바 서블릿으로 그 요청을 핸들 하여 응답하여 XML 문서를 클라이언트에 리턴 하는 방법
  • 클라이언트에서 응답 문서를 사용하여 페이지 뷰를 업데이트 하는 방법

이번에는 ajax 개발의 기초를 계속해서 설명하고 많은 자바 웹 개발자들이 관심을 갖고 있는 부분에 초점을 맞추겠다. 즉 클라이언트용 데이터를 만들어내는 문제를 집중 설명하겠다.

대부분의 자바 개발자들은 모델-뷰-컨트롤러(MVC) 패턴을 웹 애플리케이션에 적용했다. 전통적인 웹 애플리케이션에서 뷰 컴포넌트는 JSP로 구성되거나 Velocity 같은 또 다른 프리젠테이션 기술들로 구성되었다. 이러한 프리젠테이션 컴포넌트들은 완전히 새로운 HTML 페이지를 만들어서 사용자 인터페이스를 업데이트 하여 사용자기 이전에 봐왔던 것을 대체해버린다. 하지만 ajax UI를 가진 자바 웹 애플리케이션의 경우, JavaScript 클라이언트 코드는 XMLHttpRequest에 대한 응답으로 받은 데이터에 기반하여 사용자가 보고 있는 것을 업데이트 하는 궁극적인 책임이 있다. 서버의 관점에서 보면 뷰는 클라이언트 요청에 응답할 때 보내는 데이터 표현이 된다.

이 글은 자바 객체의 데이터 중심 뷰를 만드는 기술에 초점을 맞춘다. JavaBeans를 XML 문서로 변환할 때 사용할 수 있는 다양한 방법들을 설명하고 각각의 장단점도 설명한다. XML이 언제나 해결책이 되는 것은 아니다. 평이한 텍스트를 이동하는 것으로도 간단한 ajax 요청을 처리할 수 있다. 마지막으로 JavaScript Object Notation(JSON)을 소개한다. JSON은 데이터가 직렬화 된 JavaScript 객체 그래프의 형태로 전송하여 클라이언트 측 코드와 잘 작동되도록 한다.

예제에 대하여

예제 애플리케이션과 여러 사용 케이스들을 통해 이 글에서 논의되는 기술의 특징과 기술들을 설명할 것이다. 그림 1은 이 예제 사용 케이스를 나타내는 간단한 데이터 모델이다. 모델은 온라인 스토어의 사용자 계정을 나타내고 있다. 사용자는 이전 주문의 컬렉션을 갖고 있고 각 주문은 여러 Item들로 구성된다.


그림 1. 객체 모델
Object model representing customer's account

XMLHttpRequest가 요청 데이터를 보내는데 사용되는 포맷에는 제한이 없지만 대부분의 경우 전통적인 형식 매개변수들을 보내는 것이 알맞다. 따라서 나의 논의도 서버의 응답에 초점을 맞춘다. 응답은 텍스트 기반 포맷을 갖고 있지만 이름에서 시사하듯, XMLHttpRequest는 XML 응답 데이터를 처리하는 빌트인 기능을 갖고 있다. 이것 때문에 XML이 ajax 응답의 기본 수단이 된다.




위로


자바 클래스에서 XML 만들기

ajax 응답을 XML로 전달하는 많은 이유가 있다. 모든 ajax를 실행할 수 있는 브라우저에는 XML 문서들을 검색할 수 있는 메소드를 갖고 있고 XML 데이터로 잘 작동하는 서버 측 기술이 있다. ajax 클라이언트와 서버 간 콘트랙트를 정의하는 것은 쉽다. 스키마를 만들어서 교환될 문서의 유형을 기술하고 서비스 지향 방식을 취한다면 XML을 사용하는 것으로도 비 ajax 클라이언트는 데이터 피드를 소비할 수 있다.

자바 객체에서 XML 데이터를 만들 수 있는 세 가지 방법들과 각각의 장단점도 분석해 보자.




위로


'Roll-your-own' 직렬화

우선, 자신의 객체 그래프에서 XML을 프로그램 방식으로 생성할 수 있다. 이 방식은 JavaBean 클래스에 toXml()을 구현하는 것만큼 간단하다. 그런 다음 알맞은 XML API를 선택하여 각 빈이 엘리먼트를 제거하여 상태를 표현하고 객체 그래프를 반복적으로 호출하도록 한다. 분명한 것은 이 방식은 많은 클래스 까지는 적용될 수 없다는 점이다. 각자 고유의 XML 생성 코드가 작성되어야 하기 때문이다. 구현이 쉽고, 추가 설정 또는 보다 복잡한 구현 프로세스의 관점에서 볼 때 오버헤드가 없으며 두 개의 호출로 JavaBeans로 구성된 어떤 그래프도 XML 문서로 변환될 수 있다는 점은 장점이다.

이전 글에 쓰였던 예제 코드에서 toXml() 메소드를 구현했다. XML 마크업의 스트링을 함께 붙였다. 그 때 언급했듯이 이것은 toXml() 메소드의 코드에 대한 태그 밸런스를 확인하고 엔터티가 인코딩 되는지를 확인해야 하는 까다로운 방식이다. 자바 플랫폼에서 사용할 수 있는 여러 XML API들은 이 작업을 수행한다. 따라서 XML의 내용에만 집중할 수 있다. Listing 1은 JDOM API를 사용하여 온라인 스토어 예제에서 주문을 나타내는 클래스에 toXml()을 구현하는 모습이다. (그림 1)


Listing 1. Order 클래스를 위한 toXml()의 JDOM 구현


public Element toXml() {

Element elOrder = new Element("order");
elOrder.setAttribute("id",id);

elOrder.setAttribute("cost",getFormattedCost());

Element elDate = new Element("date").addContent(date);
elOrder.addContent(elDate);

Element elItems = new Element("items");
for (Iterator<Item> iter =
items.iterator() ; iter.hasNext() ; ) {
elItems.addContent(iter.next().toXml());
}
elOrder.addContent(elItems);

return elOrder;
}

JDOM을 사용하여 엘리먼트를 생성하고, 애트리뷰트를 설정하며, 엘리먼트 콘텐트를 추가하는 것이 얼마나 쉬운지를 알 수 있다. 합성 JavaBeans의 toXml() 메소드에 대한 반복 호출로 하위그래프의 Element 구현을 얻을 수 있다. 예를 들어, items 엘리먼트의 콘텐트는 Order에 모아진 각 Item 객체에 대해 toXml()을 호출하면 생성된다.

일단 JavaBeans 모두 toXml() 메소드를 구현하면 어떤 임의의 객체 그래프도 XML 문서로 직렬화 하고 이를 ajax 클라이언트로 리턴 하기는 간단하다. (Listing 2)


Listing 2. JDOM 엘리먼트에서 XML 응답 만들기


public void doGet(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException, ServletException {

String custId = req.getParameter("username");
Customer customer = getCustomer(custId);

Element responseElem = customer.toXml();
Document responseDoc = new Document(responseElem);

res.setContentType("application/xml");
new XMLOutputter().output(responseDoc,res.getWriter());
}

JDOM이 여기에서도 능력을 발휘한다. 객체 그래프의 루트로서 리턴된 XML 엘리먼트 주위에 Document를 래핑하고 XMLOutputter를 사용하여 서블릿 응답에 이 문서를 작성하면 된다. Listing 3은 이 방식으로 만들어지고, XMLOutputter를 JDOM의 Format.getPrettyFormat()으로 초기화 하여 포맷된 XML 샘플이다. 이 예제에서 사용자는 두 개의 Item으로 구성된 한 개의 주문만 했다.


Listing 3. 사용자를 나타내는 XML 문서 샘플


<?xml version="1.0" encoding="UTF-8"?>
<customer username="jimmy66">
<realname>James Hyrax</realname>
<orders>
<order id="o-11123" cost="$349.98">
<date>08-26-2005</date>
<items>
<item id="i-55768">
<name>Oolong 512MB CF Card</name>
<description>512 Megabyte Type 1 CompactFlash card.
Manufactured by Oolong Industries</description>
<price>$49.99</price>
</item>
<item id="i-74491">
<name>Fujak Superpix72 Camera</name>
<description>7.2 Megapixel digital camera featuring six
shooting modes and 3x optical zoom. Silver.</description>
<price>$299.99</price>
</item>
</items>
</order>
</orders>
</customer>


'Roll-your-own' 직렬화의 단점

재미있게도, Listing 3은 JavaBeans가 스스로를 XML로 직렬화 할 때의 단점을 드러내고 있다. 이 문서가 사용자에게 Order History 뷰를 제공하는데 사용되었다고 가정해 보자. 이 경우 지난 주문 시 모든 Item의 전체 디스크립션 까지는 디스플레이 하지 않거나 사용자에게 이름을 묻고 싶지는 않을 것이다. 하지만 이 애플리케이션이 검색 결과를 Item 빈의 리스트로 리턴하는 ProductSearch 클래스를 갖고 있을 경우 Item의 XML 표현에 이 디스크립션이 포함되도록 하는 것이 유용하다. 더욱이 현재 재고 수준을 나타내는 Item 클래스에 대한 추가 필드는 Product Search 뷰에 디스플레이 하기에 유용한 정보이다. 하지만 이 필드는 Item을 포함하고 있는 객체 그래프에서 직렬화 된다. 현재 재고 레벨이 Customer의 Order History와 관계가 없을지라도 말이다.

디자인 관점에서 보면 이것은 뷰 생성과 연결되는 데이터 모델의 전통적인 문제이다. 각 빈은 일방으로 스스로를 직렬화하고 one-size-fits-all 접근 방식으로 쓸모 없는 데이터를 교환하고 클라이언트 코드가 문서에서 필요한 정보를 배치하는 것이 어려워지고 클라이언트 측에서 대역폭 소비와 XML 파싱 시간이 늘어난다는 것을 의미한다. 이러한 커플링의 다른 결과는 XML 문법이 자바 클래스와 독립적으로 돌아갈 수 없다는 것이다. 예를 들어 사용자 문서의 스키마 변경이 여러 자바 클래스에 영향을 미쳐서 이것도 변경 및 재 컴파일 되도록 한다.

나중에 더 자세히 설명하도록 하고, 우선은 ‘Roll-your-own’ 직렬화 방식의 확장성 문제에 대한 솔루션부터 살펴보기로 하자.




위로


XML 바인딩 프레임웍

최근 몇 년 동안, XML 문서를 자바 객체 그래프로의 바인딩 과정을 간소화 할 여러 자바 API들이 개발되었다. 대부분이 XML 마샬링과 언마샬링을 제공한다. 다시 말해서 자바 객체 그래프와 XML간 투웨이(two-way) 변환을 수행한다는 의미이다. 이러한 프레임웍들은 XML을 핸들링 하는 모든 작업들을 캡슐화 한다. 애플리케이션 코드는 오직 순수 자바 객체만 처리한다. 또한 밸리데이션 같은 유용한 기능들도 제공한다. 일반적으로 이러한 프레임웍은 두 개의 다른 접근 방식을 취한다. 코드 생성과 객체-XML 매핑이 그것이다.

코드 생성 방식

코드 생성 방식을 적용하는 바인딩 프레임웍에는 XMLBeans, JAXB, Zeus, JBind가 포함된다. Castor 역시 이 기술을 사용한다. 이 프레임웍의 시작점은 문서의 데이터 유형을 기술하는 XML 스키마이다. 이 프레임웍에서 제공하는 툴을 사용하여 스키마 정의된 유형들을 나타내는 자바 클래스를 생성한다. 마지막으로 이렇게 생성된 클래스를 사용하여 모델 데이터를 나타내고 이들을 직렬화 하여 XML로 직렬화 한다.

코드 생성 방식은 애플리케이션이 큰 XML 문법을 사용할 경우에 유용하다. 수십 개의 클래스들에 걸쳐 XML 직렬화 메소드를 작성하는 문제가 사라진다. 한편 자신의 JavaBeans를 더 이상 정의하지 않아도 된다. 프레임웍에서 생성된 자바 클래스는 일반적으로 XML의 구조를 따른다. 생성된 클래스들은 "죽은" 데이터 컨테이너가 된다. 일반적으로 작동을 추가할 수 없기 때문이다. 애플리케이션 코드가 스키마에서 생성된 유형과 잘 작동하도록 해야 한다. 또 다른 단점은 스키마에서 변경사항이 생기면 생성된 클래스도 변경된다. 더 나아가 관련 코드에도 영향을 미친다.

이러한 유형의 XML 바인딩 프레임웍은 데이터 언마샬링(XML 문서를 소비하고 이들을 자바 객체로 변환하기)에 가장 유용하다. 거대한 데이터 모델이 아닌 이상, 그리고 클래스를 생성하여 혜택을 보는 경우가 아니라면 코드 생성 기반 프레임웍은 ajax 애플리케이션에는 과분하다.

매핑 방식

매핑을 사용하는 프레임웍에는 Castor와 Apache Commons Betwixt가 있다. 매핑은 코드 생성 보다 유연하고 경량의 솔루션이다. 우선 일상적인 방식으로 JavaBeans를 코딩한다. 그런 다음, 런타임 시 프레임웍 내부의 마샬러(marshaler)에 호출하여 객체 멤버의 이름, 유형, 값을 기반으로 XML 문서를 만들어 낸다. 클래스에 대해 매핑 파일을 정의하면 디폴트 바인딩 전략을 무시하고 마샬러에게 원하는 클래스 표현 방식을 권할 수 있다

이 방식은 확장성과 유연성을 서로 타협한 방식이다. 원하는 방식으로 자바 클래스를 작성하고 마샬러가 XML을 처리한다. 하지만 매핑 정의 파일을 쉽게 작성할 수 있고 확장성도 좋지만 매핑 규칙들은 표준 바인딩 작동을 너무 많이 변경할 수 있고 객체의 구조와 XML 간 커플링이 어느 정도 남아있게 된다. 결과적으로 자바 표현 아니면 XML 표현 중 하나를 타협해야 한다.

데이터 바인딩 요약

Dennis Sosnoski는 코드 생성과 코드 매핑에 대한 XML 데이터 바인딩 API에 대해 자세히 연구했다. 그의 글을 읽어보기 바란다.(참고자료)

대체로, 코드 생성 방식은 ajax 애플리케이션에 유연성과 편의를 제공한다. 한편 매핑 기반 프레임웍은 필요한 XML을 객체에서 만들어낼 정도로 충분한 매핑 전략을 만드는 한 괜찮은 방식이다.

XML 바인딩 API 모두 수동 직렬화 기술에 단점이 있다. 바로 모델과 뷰의 커플링이다. 각 객체 유형에 대한 한 개의 XML 구현으로 제한한다는 것은 네트워크를 통해 이동하는 과잉의 데이터가 생긴다는 것을 의미한다. 더 심각한 문제는 어떤 경우에는 직렬화 된 뷰를 획득할 수 없다는 것이다.

전통적인 웹 애플리케이션 개발에서, 페이지 템플릿 시스템은 뷰 생성을 컨트롤러 로직과 모델 데이터에서 깨끗하게 분리하는데 사용된다. 이 방식 역시 ajax 시나리오에 도움이 된다.




위로


페이지 템플릿 시스템

범용 페이지 템플릿 기술은 XML을 생성하는데 사용될 수 있는 기술이다. ajax 애플리케이션이 데이터 모델에서 임의의 XML 응답 문서를 만든다. 더욱이 이 템플릿들은 단순하고 표현적인 마크업 언어를 사용하여 작성될 수 있다. Listing 4는 Customer 빈을 사용하여, 클라이언트 코드가 Order History 컴포넌트를 만들기에 적합하도록 커스텀 XML 뷰를 렌더링 한다.


Listing 4. 주문 히스토리 문서를 만드는 JSP 페이지


<?xml version="1.0"?>
<%@ page contentType="application/xml" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="cust" value="${requestScope.customer}"/>

<orderhistory username="${cust.username}">
<c:forEach var="order" items="${cust.orders}">
<order id="${order.id}" cost="${order.formattedCost}">
<date>${order.date}</date>
<items>
<c:forEach var="item" items="${order.items}">
<item id="${item.id}">
<name><c:out value="${item.name}" escapeXml="true"/></name>
<price>${item.formattedPrice}</price>
</item>
</c:forEach>
</items>
</order>
</c:forEach>
</orderhistory>


이 템플릿은 Order History 뷰에 필요한 데이터만 만든다. 아이템의 디스크립션 같은 쓸모 없는 것은 만들지 않는다. 각 아이템에 대한 전체 디스크립션과 재고 레벨이 포함된 Product Search 뷰에 대한 커스텀 XML을 만들기도 쉽다.

이 템플릿의 문제점

이 템플릿의 문제는 필요한 모든 다른 뷰에 대해 새로운 JSP를 만들어야 한다는 점이다. 필요한 객체 그래프를 어셈블링하고 이를 직렬화 하는 것과는 대조된다. 디자인 관점에서 볼 때 서버가 만들어낼 문서 유형들을 생각하기 때문에 좋은 것이라고 할 수 있다. 또한 XML 스팩의 API가 아닌 일반 템플릿 환경에서 작업하기 때문에 태그 밸런싱이 되는지, 엘리먼트와 애트리뷰트 순서가 정확한지, XML 엔터티(< 또는 &)가 없어졌는지를 확인하는 것은 나의 몫이다. JSP의 out 태그로 후자의 태스크를 수월하게 할 수 있지만, 모든 템플릿 기술이 그 방식을 제공하는 것은 아니다. 마지막으로 서버 측에서, 스키마에 대해 생성된 XML 문서의 유효성 검사를 할 수 있는 쉬운 방법이란 없다. 하지만 어쨌든 제품 환경에서는 이를 수행해야 하고 개발하는 동안 쉽게 해결할 수 있는 문제이다.




위로


XML 없는 응답 데이터

지금까지, 여기에서 다룬 모든 기술들은 XML 문서 형태로 서버 응답을 만들어 낸다. 하지만 XML에도 몇 가지 문제가 있다. 그 중 하나는 레이턴시(Latency)와 관련이 있다. 브라우저는 XML 문서를 파싱하지 않고 DOM 모델들을 즉시 만들지 않기 때문에 ajax 컴포넌트에 필요한 신속함이 줄어든다. 특히 느린 머신에서 큰 문서를 파싱할 때 그렇다. 한 예로, 검색 결과가 서버에서 보내지고 사용자에게 디스플레이 되는 곳의 "라이브 검색"을 들 수 있다. 라이브 검색 컴포넌트는 빠르게 응답하는 것이 중요한데, 이와 동시에 서버 응답을 빠르고 지속적으로 파싱해야 한다.

레이턴시는 중요한 고려 사항이다. 하지만 XML을 피하는 가장 큰 이유는 어색한 클라이언트 측 DOM API이다. 브라우저 호환 방식으로 DOM을 통해 값을 얻기 위해 어떤 명령도 따라야 한다. (Listing 5)


Listing 5. JavaScript에서 XML 응답 문서 검색하기


// Find name of first item in customer's last order
var orderHistoryDoc = req.responseXML;

var orders = orderHistoryDoc.getElementsByTagName("order");
var lastOrder = orders[orders.length - 1];

var firstItem = lastOrder.getElementsByTagName("item")[0];
var itemNameElement = firstItem.firstChild;

var itemNameText = itemNameElement.firstChild.data;

엘리먼트들 간 공백이 있다면 상황은 더 복잡해 진다. 모든 엘리먼트의 firstChild는 언제나 공백 텍스트 노드가 되기 때문이다. JavaScript 라이브러리는 XML 문서를 보다 손쉽게 처리하는데 도움이 된다. Sarissa(참고자료)와 Google-ajaxSLT가 있는데 이 두 가지 모두 XPath 기능을 대부분의 브라우저에 추가한다.

대안도 생각해 볼 수 있다. responseXML 외에도 XMLHttpRequest 객체는 responseText 속성을 제공한다. 이것은 서버 응답 바디(server's response body)를 스트링으로 제공한다.

responseText 속성

responseText는 서버가 매우 간단한 값을 클라이언트로 보내야 할 때 매우 편리하다. 대역폭을 피하고 XML의 오버헤드를 처리한다. 간단한 true/false 응답은 평이한 텍스트로 서버에 의해 리턴될 수 있다. 간단한 콤마 분리형 리스트로 된 이름 또는 번호 역시 가능하다. 일반적으로 XML 응답과 평이한 텍스트 응답을 같은 애플리케이션에 섞지 않는 것이 가장 좋다. 한 개의 데이터 포맷을 고수하면 코드 추상화와 재사용이 간단해 진다.

responseText는 XML 응답 데이터의 결합에도 유용하다. 응답 문서에서 하나의 값만 추출해야 할 때 "치팅(cheat)" 하는 것이 더 편리할 수 있다. XML을 구조화된 문서 보다는 텍스트의 스트링으로 간주한다. Listing 6은 사용자의 Order History에서 첫 번째 주문 날짜를 추출할 때 정규식을 사용하는 방법을 보여준다. 이것은 핵(hack)일 뿐이므로 XML 문서의 어휘 표현에 의존해서는 안된다.


Listing 6. XMLHttpRequest의 responseText 객체로 정규식 사용하기


var orderHistoryText = req.responseText;
var matches = orderHistoryText.match(/<date>(.*?)<\/date>/);

var date = matches[1];

이러한 방식으로 responseText를 사용하면 어떤 상황에서는 편리할 수 있다. 이상적으로는 JavaScript에서 쉽게 검색될 수 있는 포맷에 복잡하고 구조화된 데이터를 표현하는 방식이다. XML의 프로세싱 오버헤드가 없다.




위로


JavaScript Object Notation

JavaScript 객체들은 대부분 공동 어레이, 숫자 인덱싱 어레이, 스트링, 숫자, 이러한 유형들의 중첩 결합으로 구성된다. 모든 유형들이 JavaScript에서 선언될 수 있기 때문에 객체 그래프를 한 문장에 정적으로 정의할 수 있다. Listing 7은 JSON 신택스를 사용하는 객체를 선언하고 이것이 액세스 되는 방법을 보여준다. 중괄호는 공동 어레이(객체)를 의미한다. 키 값 상은 콤마로 분리된다. 대괄호는 숫자 인덱싱 어레이를 나타낸다.


Listing 7. JSON을 사용하여 JavaScript에 객체 선언하기


var band = {
name: "The Beatles",
members: [
{
name: "John",
instruments: ["Vocals","Guitar","Piano"]
},
{
name: "Paul",
instruments: ["Vocals","Bass","Piano","Guitar"]
},
{
name: "George",
instruments: ["Guitar","Vocals"]
},
{
name: "Ringo",
instruments: ["Drums","Vocals"]
}
]
};

// Interrogate the band object
var musician = band.members[3];
alert( musician.name
+ " played " + musician.instruments[0]
+ " with " + band.name );

JSON은 재미있는 언어 기능이기는 한데 이것이 ajax와 어떤 관계가 있는가? JSON을 사용하여 JavaScript 객체 그래프를 네트워크를 통해 ajax 서버의 응답으로 보낼 수 있다. DOM API를 통해 클라이언트 상에서 XML을 검색하는 것에서 탈피하여 JSON 응답을 계산하고 JavaScript 객체 그래프에 지속적으로 액세스 할 수 있다는 의미이다. 우선 JavaBeans를 JSON으로 변경해야 한다.

자바 클래스에서 JSON 만들기

다른 XML 생성 기술들에 적용되는 것과 같은 장단점이 JSON을 만드는데도 적용된다. 프리젠테이션 템플릿 기술을 다시 사용해야 하는 케이스가 있다. 하지만 JSON을 사용하면 개념상으로는 애플리케이션 상태 뷰를 만드는 것 보다 애플리케이션 티어 사이에 직렬화 된 객체를 전달하는 것에 더 가깝다. org.json 자바 API를 사용하여 toJSONObject() 메소드를 구현하는 방법을 설명하겠다. JSONObjects는 JSON으로 직렬화 될 수 있다. Listing 8은 Listing 1을 되풀이하여 Order클래스용 toJSONObject() 구현을 보여준다.


Listing 8. Order 클래스용 toJSONObject() 메소드 구현


public JSONObject toJSONObject() {

JSONObject json = new JSONObject();
json.put("id",id);
json.put("cost",getFormattedCost());
json.put("date",date);

JSONArray jsonItems = new JSONArray();
for (Iterator<Item> iter =
items.iterator() ; iter.hasNext() ; ) {
jsonItems.put(iter.next().toJSONObject());
}
json.put("items",jsonItems);

return json;
}

org.json API는 매우 간단하다. JSONObject는 JavaScript 객체(공동 어레이)를 나타내고 String 키와 값(프리머티브 String 유형 또는 또 다른 JSON 유형)을 갖고 있는 다양한 put() 메소드를 취한다. JSONArray는 인덱싱 어레이를 나타내기 때문에 put() 메소드는 하나의 값만 취한다. Listing 8을 보면 jsonItems 어레이를 만들고 이것을 put()과 함께 json 객체에 추가하는 대안 방식은 각 아이템에 대하여 json.accumulate("items",iter.next().toJSONObject());를 호출한다. accumulate() 메소드는 put()과 비슷하다. 다만 그 값을 키로 구분된 인덱싱 어레이에 붙인다는 것만 다르다.

Listing 9는 JSONObject를 직렬화하고 이것을 서블릿의 응답에 작성하는 방법을 보여준다.


Listing 9. JSONObject에서 직렬화 된 JSON 응답 만들기


public void doGet(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException, ServletException {

String custId = req.getParameter("username");
Customer customer = getCustomer(custId);

res.setContentType("application/x-json");
res.getWriter().print(customer.toJSONObject());
}

사실 아무것도 없다. 암시적으로 호출된 JSONObject에 대한 toString() 메소드가 모든 일을 한다. application/x-json 콘텐트 유형은 약간 모호하다. 이것을 작성할 당시 JSON의 MIME 유형에 대한 동의가 없었다. 하지만 application/x-json은 지금으로서는 최선의 선택이다. Listing 10은 서블릿 코드에 대한 응답 예제이다.


Listing 10. Customer 빈의 JSON 구현


{
"orders": [
{
"items": [
{
"price": "$49.99",
"description": "512 Megabyte Type 1 CompactFlash card.
Manufactured by Oolong Industries",
"name": "Oolong 512MB CF Card",
"id": "i-55768"
},
{
"price": "$299.99",
"description": "7.2 Megapixel digital camera featuring six
shooting modes and 3x optical zoom. Silver.",
"name": "Fujak Superpix72 Camera",
"id": "i-74491"
}
],
"date": "08-26-2005",
"cost": "$349.98",
"id": "o-11123"
}
],
"realname": "James Hyrax",
"username": "jimmy66"
}

클라이언트에서 JSON 소비하기

이 프로세스의 마지막 단계는 JSON 데이터를 클라이언트 상의 JavaScript 객체로 변환하는 것이다. JavaScript 식을 포함하고 있는 스트링을 인터프리팅하는 함수인 eval()을 호출하면 된다. Listing 11은 JSON 응답을 JavaScript 객체 그래프로 변환하고 사용자의 마지막 주문에서 첫 번째 아이템의 이름을 획득하는 Listing 5의 태스크를 수행한다


Listing 11. JSON 응답 계산하기


var jsonExpression = "(" + req.responseText + ")";
var customer = eval(jsonExpression);

// Find name of first item in customer's last order
var lastOrder = customer.orders[customer.orders.length-1];
var name = lastOrder.items[0].name;

Listing 11을 Listing 5와 비교해 보면 JSON을 사용하는 클라이언트에 어떤 이점이 있다는 것을 알 수 있다. ajax 프로젝트가 클라이언트 상에서 수 많은 복잡한 서버 응답을 검색해야 한다면 JSON이 제격이다. JSON과 XMLHttpRequest를 함께 두면 ajax 인터랙션이 시작하여 SOA 요청 보다는 RPC 호출 처럼 보인다. 다음 글에서 자세히 설명하겠다.

JSON의 단점

JSON도 단점이 있다. 여기에서 설명한 JSON 방식을 사용하면 요청 기반으로 객체의 직렬화를 맞출 방법이 없기 때문에 불필요한 필드가 네트워크를 통해 보내질 수 있다. 게다가 toJSONObject() 메소드를 각 JavaBean에 추가하면 스케일링이 잘 되지 않는다. 내부검사와 JavaBean을 JSON 시리얼라이저에 작성하는 것은 간단하더라도 말이다. 마지막으로 서버 측 코드가 서비스 지향이고 ajax 클라이언트에서 요청을 핸들링 하도록 지정되지 않았다면 유비쿼터스 지원이 되는 XML이 더 낫다.




위로


직렬화 기술 비교

서버 측 자바 상태를 ajax 클라이언트로 전송할 때의 다섯 가지 다른 기술들을 보았다. 직접적인 XML 직렬화, 코드 생성을 통한 XML 바인딩, 매핑 메커니즘을 통한 XML 바인딩, 템플릿 기반 XML 생성, JSON으로의 직렬화를 설명했다. 이들 모두 저마다의 장단점을 갖고 있고, 가장 잘 맞는 애플리케이션 아키텍쳐도 다르다.

각 방식의 장단점을 다음 여섯 가지 범주로 분류하여 표 1에 요약했다.

확장성(Scalability)
이 방식이 대규모의 데이터 유형들과 얼마나 잘 맞는가? 코딩과 설정 워크로드가 그 추가 유형으로 인해 증가하는가?
통합 용이성(Ease of integration)
해당 기술을 프로젝트와 수월하게 통합되는가? 좀더 복잡한 구현 프로세스가 필요한가? 개발 복잡성이 늘어나는가?
Java class API
이 방식에 적용된 서버 측 자바 객체와 쉽게 작동하는가? 표준 빈을 작성해야 하거나 어색한 문서로 작업해야 하는가?
아웃풋 제어(Control over output)
직렬화 된 클래스 구현을 얼마나 정밀하게 제어할 수 있는가?
뷰 유연성(View flexibility)
다양하게 개인화 된 데이터 직렬화가 같은 객체 세트에서 구현될 수 있는가?
클라이언트 데이터 액세스(Client data access)
JavaScript 코드가 서버의 응답 데이터와 쉽게 작동하는가?

표 1. 데이터 생성 기술 비교

Roll-your-own XML코드 생성을 통한 XML 바인딩매핑을 통한 XML 바인딩페이지 템플리팅 XML핸드코딩 JSON 직렬화
확장성나쁨좋음보통보통나쁨
통합 용이성좋음나쁨보통보통좋음
Java class API좋음나쁨좋음좋음좋음
아웃풋 제어좋음좋음보통좋음좋음
뷰 유연성나쁨나쁨나쁨좋음나쁨
클라이언트 데이터 액세스나쁨나쁨나쁨보통좋음



위로


맺음말

표 1의 내용은 어떤 직렬화 기술이 더 좋은지를 가려내려는 것이 아니다. 여섯 가지 범주의 중요도는 프로젝트의 특성에 따라 달라진다. 수 백 가지의 데이터 유형들을 다루어야 할 경우 확장성이 필요하다. 따라서 코드 생성 방식을 사용하는 것이 좋다. 여러 가지 다른 뷰를 가진 데이터 모델을 생성하려면 페이지 템플리팅이 최선의 방법이다. 규모가 작은 프로젝트라서 직접 작성해야 하는 JavaScript의 양을 줄이려면 JSON이 제격이다.

직렬화 기술을 선택할 때 도움이 되기 바란다. 참고자료 섹션에 이 글에 설명한 기술들을 보다 자세히 공부할 수 있도록 링크를 수록하였다. 다음 시리즈도 기대해 주기 바란다. Direct Web Remoting(DWR)을 사용하여 자바 ajax 애플리케이션을 작성하는 방법을 설명할 것이다. DWR 프레임웍에서는 JavaScript 코드에서 직접 자바 클래스에 대해 메소드를 호출할 수 있다. 데이터 직렬화를 관리하여 보다 고급 추상화 레벨에서 ajax를 사용할 수 있다.


기사의 원문보기



위로


참고자료

교육

제품 및 기술 얻기

토론



위로


필자소개


Philip McCarthy, 소프트웨어 개발 컨설턴트