2010년 3월 31일 - 참고자료 시작 부분에 세 개의 비디오 링크 추가
2010년 10월 4일 - 참고자료 시작 부분에 이 시리즈의 Part 2 링크 추가
예제 애플리케이션: 데이터베이스가 통합된 블로그 체크 프로그램
다음과 같은 웹 애플리케이션을 생각해 보자.
그림 1. 데이터베이스가 통합된 블로그 체크 프로그램
이 웹 애플리케이션에서는 블로그 웹 서비스상에 노출되는 블로그 데이터를 처리한다. 블로거가 소유한 모든 블로그 정보가 포함된 데이터와 이러한 블로그에 관한 모든 설명이 Atom XML 형식으로 리턴된다(예제는 Listing 1 참조). 이 웹 애플리케이션에서는 블로거가 자신의 블로그에서 신속하게 댓글을 쿼리하여 문제가 되는 내용이 포함된 댓글을 삭제할 수 있다. 이 웹 애플리케이션은 XHTML 웹 페이지와 양식에 데이터를 표시한다. 소스 데이터가 XML 형식으로 되어 있고 브라우저의 데이터도 XML(HTML이나 XHTML)이라는 점을 감안하면 기본적으로 XML 데이터를 처리하는 것이 당연하다.
Listing 1. Atom XML 설명 피드 예제
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">WebSphere Community Blog</title>
...
<entry>
<id>tag:blogger.com,1999:blog-1417695962027703953.post-6498982274841848264</id>
<published>2009-10-17T13:06:00.000-05:00</published>
<updated>2009-10-17T13:06:00.000-05:00</updated>
<atom:title xmlns="" xmlns:atom="http://www.w3.org/2005/Atom" type="text">
Questionable spamming comment title
</atom:title>
<atom:content xmlns="" xmlns:atom="http://www.w3.org/2005/Atom" type="html">
Questionable spamming comment content
</atom:content>
...
<atom:author xmlns="" xmlns:atom="http://www.w3.org/2005/Atom">
<atom:name>Joe Smith</atom:name>
<atom:uri>http://joe.uri.com</atom:uri>
<atom:email>jsmith@email.com</atom:email>
</atom:author>
</entry>
...
</feed> |
시간이 지나면서 블로거는 문제가 되는 댓글이 같은 사용자나 도메인 이름에서 시작된다는 사실을 눈치채게 된다(Listing 1에 있는 atom:author 요소 참조).
이 시점에서 애플리케이션을 업데이트하여 블로거가 댓글을 삭제할 때 이러한 사용자나 도메인을 스패머로 플래그 지정할 수 있게 한다. 이 정보는 원래의 설명 웹 서비스에는
저장하지 않으므로 데이터 저장소에서 유지해야 한다. 데이터는 이미 XML 형식으로 되어 있으므로 데이터를 XML 데이터베이스에 유지하는 것이 당연하다. 이렇게 하면
나중에 애플리케이션을 사용하여 특정 스패머에 대한 통계 보고서를 작성하고 어떤 댓글을 삭제해야 하는지 권고할 수 있다.
이러한 애플리케이션을 구현하는 가장 좋은 방법은 무엇일까?
과거, 데이터베이스에서 기본적으로 XML을 지원하기 전에는 일반적으로 두 가지 방법을 사용하여 XML 데이터를 처리했다. 첫 번째 방법에서는 데이터를 문자열로 직렬화한 다음, 데이터를 CLOB(Character Large Object)로 데이터베이스에 저장한다. 이 방법은 성능상에 문제가 있으며 XML로 데이터베이스 내부의 데이터를 쿼리할 수 없다.
두 번째 방법에서는 데이터를 분할하여 XML 데이터의 구조가 대략적으로 표현된 관계형 테이블에 맵핑한다. 이 방법은 관계형 데이터와 XML 데이터를 다른 방식으로 표현하기 때문에 충실도에 문제가 있으며 사용자가 맵핑 코드를 유지보수해야 하고 원시 XML 쿼리도 허용되지 않는다. 게다가 새로운 요구사항으로 인해 XML 데이터 스키마가 변경되면서 관계형 맵핑을 변경하는 과정이 일반적으로 너무 힘들어졌다.
엔터프라이즈에서 XML을 사용하는 경우가 증가하면서 이제는 데이터베이스에서 관계형 데이터뿐만 아니라 XML 데이터를 저장하기 시작했다. 데이터베이스에서는 기본적으로 XML 데이터를 XML 컬럼에 저장한다. XML 컬럼을 지원하는 데이터베이스로는 Apache Derby, IBM DB2®, Oracle Database 및 Microsoft® SQLServer가 있다.
또한, 이전에는 중간 티어의 데이터를 데이터베이스로 가져오는 작업이 매우 어려웠다. JDBC 4.0 이전에는 String이나 CLOB 데이터 유형을 사용하는 것이 유일한 옵션이었다. 앞서 말했듯이 이러한 유형을 사용하는 경우에는 데이터를 직렬화해야 하기 때문에 성능상에 문제가 있다. 또한, 데이터를 구문 분석하여 XML 컬럼에 저장하는 방법을 비표준 SQL 확장이 인식해야 했다. JDBC 4.0에서는 SQLXML 유형에 대한 표준화된 지원이 도입되었으며 이 덕택에 데이터베이스에서 XML 형식으로 XML을 읽거나 쓸 수 있게 되었다. JDBC 4.0에서는 문자열이나 판독기 및 출력기 스트림 또는 JAXP 소스 및 결과를 통해 XML 데이터를 액세스할 수 있다. JDBC 4.0에서 이러한 기능을 지원하게 되면서 기본적으로 중간 티어와 데이터베이스 전체에서 XML을 자연스럽게 사용할 수 있게 되었으며 데이터베이스와 중간 티어에서 불필요한 맵핑이나 성능 오버헤드가 발생하지 않게 되었다.
JDBC 4.0을 사용하여 XML 데이터를 가져오는 간단한 예제
JDBC 4.0 지원을 사용하는 예제를 살펴보도록 하자. JDBC 4.0에서 XML 데이터를 읽는 과정은 다른 데이터 유형을 처리하는 과정과 비슷하다.
XML 데이터를 읽는 기본적인 단계는 다음과 같다.
- 준비된 명령문을 작성한다.
- 결과 세트를 얻는 준비된 명령문을 실행한다.
- 결과 세트에서 SQLXML 오브젝트를 가져온다.
- 지원되는 GET 메소드 중 하나를 통해 SQLXML 오브젝트를 읽는다.
- SQLXML 오브젝트를 해제한다.
매우 기본적인 예제는 다음과 같다.
Listing 2. JDBC 4.0을 사용하여 XML 데이터 읽기
PreparedStatement ps =
dbConnection.prepareStatement("SELECT somexmlcolumn FROM somexmltable");
ResultSet result = ps.executeQuery();
result.next();
SQLXML xml = result.getSQLXML("somexmlcolumn");
StreamSource source = xml.getSource(StreamSource.class);
// Read from the stream source
xml.free(); |
이 예제에서는 JAXP 소스 오브젝트 특히, StreamSource를 통해 소스를 읽는다. 소스 오브젝트를 이용하면 JAXP 소스를 인식하는 모든 API를 통해 데이터를
읽을 수 있다. StreamSource 소스를 사용하면 어떤 것이든 원하는 인메모리 표현을 사용할 수 있다. 오브젝트 및 API 호출 오버헤드를 초래하는 SAX나
DOM과 같은 소스와 비교했을 때 스트림을 사용하는 것이 일반적으로 가장 효과적이다.
마찬가지로 JDBC 4.0을 통해 XML 데이터를 쓰는 단계는 다음과 같다.
- 준비된 명령문을 작성한다.
- 연결에서 SQLXML 오브젝트를 작성한다.
- 지원되는 SET 메소드 중 하나를 통해 SQLXML 오브젝트에 액세스한다.
- SQLXML 오브젝트를 명령문 매개변수로 설정한다.
- SQLXML 오브젝트의 액세스 메소드에 쓴다.
- 명령문을 실행한다.
- SQLXML 오브젝트를 해제한다.
다음은 매우 기본적인 예제이다.
Listing 3. JDBC 4.0을 사용하여 XML 데이터 쓰기
PreparedStatement ps = dbConnection.prepareStatement(
"UPDATE somexmltable SET somexmlcolumn = ?");
SQLXML xml = dbConnection.createSQLXML();
StreamResult result = new StreamResult(xml.setBinaryStream());
ps.setSQLXML(1, xml);
// Write to the stream result
ps.executeUpdate();
xml.free(); |
위에서 살펴본 바와 같이 관계형 데이터로 분할하거나 CLOB를 사용할 때와 비교하여 XML 데이터베이스를 사용하면 성능과 XML 충실도가 향상되며 개발 과정이 단순화된다. 최악의 경우, 별도로 직렬화와 구문 분석을 해야 하는 다른 데이터 모델로 데이터를 복사하는 대신, 데이터를 하나의 형식으로 유지하기 때문에 성능이 좋아진다. XML 충실도는 변경되지 않은 원본 XML 데이터를 XML 데이터를 유지하는 데 사용하는 관계형 테이블에서 대략적으로 재구성하지 않고 그대로 데이터베이스에서 유지하는 것을 의미한다. 이렇게 하면 XML 데이터를 관계형 테이블에 맵핑하는 코드가 필요 없기 때문에 개발이 단순해진다.
그러면 이제 중간 티어를 살펴보도록 하자. 중간 티어에서는 기본적으로 XML을 사용하여 이와 같은 장점을 얻을 수 있으며 더욱 중요한 점은 중간 티어와 데이터베이스 모두에서 장점을 얻을 수 있다는 점이다. 또한, XML 데이터베이스보다 중간 티어에 많은 소스에 연결되기 때문에 웹 서비스 피드와 같은 다른 XML 데이터 소스로 가치가 확장될 수 있다.
데이터베이스와 중간 티어 간이나 다른 XML 데이터 소스와 중간 티어 간에 데이터를 복사하지 않기 때문에 엔드-투-엔드 성능이 개선된다. 또한, 각 티어에서 메모리에 고성능 XML 표현을 작성하면서 계속해서 데이터 표현 위에서 W3C 표준 프로그래밍 모델을 제공할 수 있기 때문에 각 티어의 성능이 개선된다.
또한, 신뢰도가 유지된다. 이와 같은 간단한 예제에서는 XML 신뢰도가 그다지 중요하지 않을 수도 있다. 그러나 교환될 XML 문서가 세금 양식이나 재무 보고서만큼 중요한 경우에는 모든 처리 프레임워크에서 XML 데이터를 기본 양식으로 유지하는 것이 중요하다.
마지막으로 단순성은 일관된 XML 프로그래밍 모델 세트 전체에서 하나의 데이터 모델을 사용함으로써 달성된다. 중간 티어에서는 시나리오를 단순하게 하기 위해 Java™ 프로그래머가 오브젝트를 DOM이나 JAXB에 맵핑하는 것이 더 쉬울 수 있지만 앞서 언급한 세금 양식 문서에서는 이러한 시나리오가 단순하지 않다. 또한, 사용자가 JDBC와 XML뿐만 아니라 XML 프로그래밍 모델과 쿼리 모델을 배워야 한다. 콜렉션과 결과에 따라 XML 데이터를 처리하면 프로그래머만 XML 데이터를 탐색하고 변환, 쿼리하는 데 필요한 W3C 표준과 XML 데이터 모델을 알면 된다. 이미 XML 데이터베이스에서 XPath와 XQuery를 사용하여 데이터를 탐색하고 쿼리했다는 점에서 이러한 기술이 이미 알려졌을 가능성이 있다.
데이터 소스에서 데이터를 검색하고 처리하여 데이터베이스에 저장하는 것과 같은 하위 레벨 작업 대부분을 처리하는 프레임워크를 사용하면 이러한 단순성은 매우 쉽게 달성되며 데이터를 복사하는 데 따른 오버헤드도 제거할 수 있다. 샘플 애플리케이션에서는 이렇게 하기 위해 IBM WebSphere Application Server V7.0 Feature Pack for XML을 사용한다. XML Feature Pack은 데이터베이스에 있던 원래의 XML 양식으로 XML을 처리하기 때문에 불필요한 성능상의 오버헤드가 제거된다. 또한, 데이터가 XML 형식으로 유지되기 때문에 XML Feature Pack에서 데이터를 쉽게 탐색, 변환하거나 쿼리할 수 있다.
IBM WebSphere Application Server V7.0 Feature Pack for XML
IBM WebSphere Application Server V7.0 Feature Pack for XML에는 중간 티어에서 W3C 표준 XPath 2.0, XSLT 2.0 및 XQuery 1.0 프로그래밍 모델을 사용하여 원시 XML을 탐색하고 변환, 쿼리하는 기능이 도입되었다. 데이터베이스 티어에서 XML 데이터가 많이 사용된다는 점을 감안하여 여기에서는 제품에 관계없이 널리 사용하는 위의 JDBC 4.0 방식을 IBM DB2 with pureXML®, Apache Derby 또는 Oracle Database와 같은 XML 데이터베이스를 사용하여 XML Feature Pack에 적용한다.
그림 2. XML Feature Pack과 XML 데이터베이스의 간단한 토폴로지 다이어그램
이 다이어그램을 보면 XML 데이터베이스, SQLXML을 지원하는 JDBC 4.0 및 XML Feature Pack이 데이터베이스와 중간 티어에서 XML 데이터를 어떻게 지원하는지 알 수 있을 것이다.
XML Feature Pack에 있는 소스 코드와 샘플로 따라 하거나 자신의 애플리케이션에서 이 시나리오를 시험할 수 있다. XML Feature Pack 및 Derby, DB2 Express 다운로드 링크는 참고자료에 있다.
데이터베이스에서의 원시 XML 지원과 JDBC 4.0 및 XML Feature Pack을 함께 사용하면 단순하고 우수한 아키텍처를 설계할 수 있다.
XML Feature Pack, JDBC 4.0 및 XML 데이터베이스를 사용하여 애플리케이션을 구현하는 방법을 살펴보도록 하자. 먼저, Atom 피드를 리턴하는 블로그 웹 서비스를 이용하여 블로그에서 악성 댓글을 검색한다(그림 1 참조). 이러한 악성 댓글을 처리하면서 데이터베이스에서 히스토리 정보를 확인하여 이전에 악성 블로거(스패머)가 작성한 댓글이 있는지 확인한다. 모든 과정에서 데이터는 XML 형식으로 유지된다. 먼저, Atom 피드에서 블로그 댓글에 관한 정보를 검색하자.
XML Feature Pack에서는 Atom 피드 데이터를 HTTP 연결을 통해 블로거 웹 서비스로 로드하여 XQuery 프로그램의 입력 문서로 사용한다. XQuery 프로그램은 XML Feature Pack Java API를 사용하여 호출한 XML Feature Pack 런타임에서 실행된다.
XQuery 프로그램에서 다음과 같은 XPath 명령문을 사용하여 Atom 피드에서 문제가 되는 댓글을 검색한다.
Listing 4. XPath 명령문
declare variable $comments := ( /atom:feed/atom:entry[atom:author/atom:name = 'Anonymous'] | /atom:feed/atom:entry[matches(atom:content, $my:vulgarwords, 'i')]) [atom:published > current-dateTime() - $my:monthsAgo]; |
XPath를 사용하여 익명 사용자가 게시했거나 저속한 단어가 포함된 모든 댓글을 사용자 정의 창에서 검색한다. 이러한 기준에 부합하는 모든 항목을 comments 변수에 저장한다.
이제, 다음과 같이 XQuery를 사용하여 해당 스패머가 이전에 문제가 될만한 댓글을 올렸다고 데이터베이스에 올라 있는지 확인한다 (여기서 $i는 위에 있는 댓글의 서브쿼리이다.)
Listing 5. XQuery 명령문
let $spammedbefore := local:hasEmailHasSpammedBefore($i/atom:author/atom:email/text()) |
이 함수의 정의를 살펴보면 데이터베이스에서 XML 데이터를 로드하는 방법을 알 수 있다.
Listing 6. XQuery 함수
declare function local:hasEmailHasSpammedBefore($emailaddress) as xs:boolean {
let $domainName := substring-after($emailaddress, '@')
return
if ($domainName = '') then
false()
else
let $jdbcURI := concat('jdbc://getAuthorsWhoHaveSpammedFromDomain?', $domainName)
let $domainSpammers := collection($jdbcURI)
return
not(empty($domainSpammers/spammers/spammer/email[. eq $emailaddress]))
}; |
이메일 주소에서 도메인 이름을 가져온 다음, 이 값을 이름 지정 쿼리 jdbc://getAuthorsWhoHaveSpammedFromDomain과 연결한다. 그러면 XPath 2.0 콜렉션
URI jdbc://getAuthorsWhoHaveSpammedFromDomain?DOMAINNAME을 얻게 된다.
XPath 2.0 콜렉션은 XQuery나 XSLT 프로그램의 기본 입력 문서에 포함되지 않은 XML 데이터의 시퀀스를 통합하는 쉬운 방법이다. 콜렉션 함수는 정의되고 종속적인 방식으로 구현되며 따라서 각 XPath 2.0 런타임은 자체적으로 기본 콜렉션 분석기를 제공할 수 있으며 그렇지 않으면 사용자가 런타임을 확장하여 동적으로 콜렉션을 구현할 수 있게 할 수 있다. XML Feature Pack 런타임을 이용하면 사용자가 XCollectionResolver 인터페이스를 통해 자체 콜렉션을 구현할 수 있다.
이 샘플에서는 XCollectionResolver를 구현했으며 이 분석기는 jdbc:// URI 스킴으로 시작하는 모든 콜렉션을 처리하고 사전 정의된 이름 지정 쿼리 세트를 대상으로 나머지 URI를 분석한다. 이 콜렉션 분석기는 사용자가 제공한 이름 지정 쿼리를 검색하여 위치 매개변수를 첨부한 다음, 데이터베이스를 대상으로 JDBC 명령문을 실행한다.
Listing 7에서는 몇 가지 기본적인 이름 지정 쿼리를 정의한 후, 이 분석기를 인스턴스화하는 위치를 확인할 수 있다. 또한, 여기서는 분석기에 데이터베이스 연결을 전달하므로 이 분석기는 모든 JDBC 연결을 대상으로 작업할 수 있다.
Listing 7. 분석기 구성
dbStatementsSupportsSQLXML = new HashMap<String, String>();
dbStatementsSupportsSQLXML.put("getAuthorsWhoHaveSpammedFromDomain",
"SELECT CONTACTS from SPAMMERS where DOMAINNAME = ?");
dbStatementsSupportsSQLXML.put("updateAuthorsWhoHaveSpammedByDomain",
"UPDATE SPAMMERS SET CONTACTS = ? WHERE DOMAINNAME = ?");
dbStatementsSupportsSQLXML.put("insertAuthorsWhoHaveSpammedByDomain",
"INSERT INTO SPAMMERS (CONTACTS, DOMAINNAME) VALUES (?, ?)");
Connection conn = getDatabaseConnection();
JDBCCollectionResolver inputResolver =
new JDBCCollectionResolver(conn, dbStatementsSupportsSQLXML); |
Listing 8에서 구현된 분석기의 일부를 확인할 수 있다. 완전히 구현된 분석기는 XML Feature Pack 샘플 소스 코드를 참고한다. 이 분석기는 JDBC 4.0을 통해 XML 데이터를 읽는 간단한 샘플(앞서 살펴본)과 기본적으로 동일하다.
재사용 가능성을 높이기 위해 이 분석기에 다음과 같은 기능을 추가했다.
- 이 분석기는 SQL문을 직접 하드 코딩하는 대신 외부에서 제공한 이름 지정 쿼리를 검색한다.
- 이 분석기는 리턴된 행과 열에서 메타데이터 유형을 조사하여 SQLXML 유형의 XML 컬럼만 읽는지 확인한다.
- 마지막으로, 이 분석기는 두 개의 다른 XML Feature Pack 구문(
XSequenceCursor및XItemView)을 사용하여 JDBC 쿼리에서 리턴된 XML 데이터의 시퀀스를 구성한다.
Listing 8. 분석기 구현
public XSequenceCursor getCollection(String uri, String base) {
// look up query from query collection provided from Listing 7
String query = lookupNamedQuery(uri);
PreparedStatement p = dbConnection.prepareStatement(query);
ResultSet rs = p.executeQuery();
...
// Loop through the result returned from the query
ResultSetMetaData metadata = rs.getMetaData();
int colType = metadata.getColumnType(jj+1);
if (colType = Types.SQLXML) {
SQLXML sqlx = rs.getSQLXML(...);
StreamSource source = sqlx.getSource(StreamSource.class);
XItemView item = itemFactory.item(source);
sqlx.free();
}
// Use the XML Feature Pack API to create a sequence from the returned XML data
...
XItemView itemView[] = items.toArray(new XItemView[0]);
XSequenceCursor sequence = itemFact.sequence(itemView);
return sequence;
} |
이제, 모든 XQuery 프로그램에서 사용할 매우 일반적인 콜렉션 분석기를 작성했다. 이 분석기는 일정한 입력을 받아서 XPath 2.0이나 XSLT 2.0, XQuery 1.0을 통해
처리할 XML 데이터 콜렉션을 리턴한다. 예제를 두 가지 더 살펴보자. 첫 번째 예제에서는 name 요소를 사용하는 모든 스패머의 목록을 작성하고 두 번째 예제에서는
11개 이상의 댓글을 게시한 스패머의 수를 리턴한다.
Listing 9. 추가 XQuery 예제
Java:
dbStatementsSupportsSQLXML.put("getAllSpammers", "SELECT CONTACTS from SPAMMERS");
XQuery:
let $allSpammers := collection('jdbc://getAllSpammers')
return
for $i in $allspammers
let $first := $i/name/first
order by $i/name/last
return
<name>
<first>{ $first }</first>
<last>{ $i/name/last }</last>
</name>
Java:
dbStatementsSupportsSQLXML.put("getAllSpamAuthorsWhereSpamCountGreaterThan",
"SELECT CONTACTS from SPAMMERS where COUNT > ?");
XQuery:
let $minCount := 10
let $allSpammers := collection(concat(
'jdbc:// getAllSpamAuthorsWhereSpamCountGreaterThan?',
$minCount)
)
return
count($allSpammers)
} |
또한, 콜렉션 분석기는 XPath 2.0의 일부이므로 XQuery 1.0에서와 마찬가지로 XSLT 2.0에서도 콜렉션 분석기가 유용하다. 다음 예제는 콜렉션 분석기를 사용하는 간단한 XSLT 2.0 예제이다.
Listing 10. 추가 XSLT 예제
<xsl:variable name="allSpammers" select="collection('jdbc://getAllSpammers')"/>
<xsl:template match="/">
<p>The current spammer database contains the following domains and spammers.</p>
<xsl:for-each select="$allSpammers">
<table>
<tr>
<th>Name</th><th>Email</th>
</tr>
<xsl:for-each select="$allSpammers">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="email"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template> |
마찬가지로 XML 데이터베이스에 데이터를 쓰는 것이 가능하다. XSLT 2.0에서는 xsl:result-document 명령어를 사용하여 URI로 식별하기 때문에 결과를 다수의 문서에
쓸 수 있다. 앞서와 마찬가지로 이 URI 분석은 런타임 구현에 종속적이다. 결과를 쓸 위치를 사용자가 지정할 수 있도록 하기 위해 XML Feature Pack에서는 XResultsResolver
인터페이스를 제공한다. 이 샘플에서는 —XML— 초계값이 표시된 XML 매개변수와 더불어 이름 지정 명령문과 위치 매개변수를 사용하는 비슷한 JDBC 결과를 구현했다.
이렇게 하면 Listing 11에서와 같이 데이터베이스에 데이터를 쓸 수 있다.
Listing 11. XSLT 결과 문서
<!-- Is this an insert or an update -->
<xsl:variable name="insert" select="count($spammersByDomain/spammers/spammer) eq 0"/>
<!-- Create the insert statement named query -->
<xsl:variable name="insertJdbcURI"
select="concat('jdbc://insertAuthorsWhoHaveSpammedByDomain?--XML--&', $domain)"/>
<!-- Create the update statement named query -->
<xsl:variable name="updateJdbcURI"
select="concat('jdbc://updateAuthorsWhoHaveSpammedByDomain?--XML--&', $domain)"/>
<!—
If insert, insert the xmldoc into the database.
Otherwise, update the database with the xmldoc.
-->
<xsl:template match="/">
<xsl:when test="$insert">
<xsl:result-document href="{$insertJdbcURI}" method="xml" indent="yes">
<xsl:copy-of select="$xmldoc"/>
</xsl:result-document>
</xsl:when>
<xsl:otherwise>
<xsl:result-document href="{$updateJdbcURI}" method="xml" indent="yes">
<xsl:copy-of select="$xmldoc"/>
</xsl:result-document>
</xsl:otherwise>
</xsl:template> |
특정 도메인에 스패머가 존재하지 않는 경우에 이 샘플을 실행하면 xsl:when 명령문의 삽입 경로가 실행된다. 이런 경우에 XML 런타임은 요청을 확인하여
xmldoc 변수의 내용을 다음과 같은 결과 URI에 쓴다.
Listing 12. 결과 URI
jdbc://insertAuthorsWhoHaveSpammedByDomain?--XML--&domain.com |
그러면, 이 샘플의 결과 분석기가 이 명령문을 분석하여 다음과 같이 사전 정의된 이름 지정 쿼리를 작성한다.
Listing 13. 이름 지정 쿼리
INSERT INTO SPAMMERS (CONTACTS, DOMAINNAME) VALUES (?, ?) |
그런 다음 이 결과 분석기는 xmldoc 변수의 XML 내용을 첫 번째 위치 매개변수에 첨부하고 domain.com은 두 번째 위치 매개변수에 첨부한다.
결과에 XML 데이터를 쓰는 기능은 콜렉션에서 XML 데이터를 읽는 기능과 마찬가지로 XML 언어에 고유한 것은 아니다. 앞서 살펴본 쓰기 예제에서는 XSLT를 사용했다(Listing11 참조). 동일한 결과 분석기 방식으로 XQuery 1.0 프로그램을 사용하여 XML 데이터베이스에 출력을 쓸 수 있다.
일반적인 JDBC 분석기를 사용할지 아니면 다른 방식을 사용할지에 대한 참고
여기에서 기술한 방식에서는 JDBC 4.0으로 구현된 XML Feature Pack의 결과 분석기와 JDBC 입력 및 출력 콜렉션을 정의한다. 이 방식은 XML Feature Pack과 XML 데이터베이스를 자연스럽고 유용하게 통합할 수 있는 유일한 방법이다.
또한, 다음과 같이 더 구체적인 사용자 정의 XPath 2.0 확장 함수로 입력을 구현할 수도 있다.
Listing 14. 덜 일반적인 XQuery 함수
declare function local:hasEmailHasSpammedBefore($emailaddress) as xs:boolean {
let $domainName := substring-after($emailaddress, '@')
return
if ($domainName = '') then
false()
else
let $domainSpammers := my:getAuthorsWhoHaveSpammerFromDomain($domainName)
return
not(empty($domainSpammers/spammers/spammer/email[. eq $emailaddress]))
}; |
이 방식은 입력과 출력이 더 긴밀하게 정의된다는 장점이 있다. 그러나 가능한 모든 쿼리에 대해서 한 번씩, 쿼리할 때마다 확장 함수를 써야 하고 입력에만 적용된다는 단점이 있다. (출력에 확장 함수를 쓰는 것이 언제나 당연하거나 가능한 것은 아니다.) 더 일반적인 콜렉션과 결과 분석기를 사용하는 방식에서는 대부분의 경우를 자연적이고 일반적인 방식으로 처리한다.
앞서 살펴본 콜렉션 분석기와 결과 분석기는 XML Feature Pack 샘플 코드에 포함되어 있다. 따라서 여기서 소개한 코드는 하나의 샘플이다. 이 코드를 프로덕션 애플리케이션에서 사용하려면 작성하고자 하는 애플리케이션의 요구에 맞게 샘플을 확장해야 한다.
이 기사에서는 XML 프로그램을 의도적으로 단순화해서 독자가 기사를 쉽게 이해할 수 있도록 했다. 이미 언급한 바와 같이 XML Feature Pack 샘플과 여기에 포함된 모든 소스 코드를 완전히 사용하여 샘플 애플리케이션을 실행할 수 있다.
개요 부분에서 언급한 바와 같이 관계형 데이터로 분할하거나 CLOB를 사용할 때와 비교하여 XML 데이터베이스를 사용하면 성능과 XML 충실도가 향상되며 개발 과정이 단순화된다. 최악의 경우, 추가로 직렬화와 구문 분석을 해야 하는 다른 데이터 모델로 데이터를 복사하는 대신 하나의 형식으로 데이터를 유지하기 때문에 성능이 좋아진다. XML 충실도는 변경되지 않은 원본 XML 데이터를 XML 데이터를 유지하는 데 사용하는 관계형 테이블에서 대략적으로 재구성하지 않고 그대로 데이터베이스에서 유지하는 것을 의미한다. 이렇게 하면 XML 데이터를 관계형 테이블로 맵핑하는 코드가 필요 없기 때문에 개발이 단순해진다.
중간 티어에서는 기본적으로 XML Feature Pack을 통해 XML을 사용함으로써 이와 같은 장점을 얻을 수 있으며 더욱 중요한 점은 중간 티어와 데이터베이스 모두에서 장점을 얻을 수 있다는 점이다. 또한, 중간 티어가 XML 데이터베이스보다 많은 소스에 연결되기 때문에 웹 서비스 피드와 같은 다른 XML 데이터 소스로 가치가 확장될 수 있다.
교육
- 다중 티어에서 XML 프로그래밍하기, Part 2: XML 데이터베이스 서버를 활용하는 효과적인 Java EE 애플리케이션 작성하기: JDBC 4.0, SQLXML, WebSphere XML Feature Pack 및 DB2 pureXML을 사용하여 완전한 XML 솔루션을 최적화하기(Andrew Spyker, Cynthia M. Saracco, Bert Van Der Linden 및 Guogen Zhang, developerworks, 2010년 10월): 이 시리즈의 Part 2에서 서버측 Java 애플리케이션의 일시적 XML과 지속적 XML을 상세하게 살펴보자. 실용적 예제와 샘플 코드를 사용하는 과정에서 XML 데이터베이스에서 XML 인덱싱과 쿼리 필터링 기능을 사용하여 대용량 XML 데이터를 처리하는 방법을 확인할 수 있다.
- 비디오: Getting started with the WebSphere Application Server Feature Pack for XML: 이 기사에서 설명한 샘플 애플리케이션을 설치하고 WebSphere Application Server Feature Pack for XML을 시작한다.
- 비디오: XML Feature Pack and Sample for XML Database Integration Setup(With DB2 pureXML) Part 1/2: 이 기사에서 설명한 블로그 체크 프로그램 샘플 애플리케이션을 실행하도록 WebSphere Application Server와 DB2를 구성한다.
- 비디오: XML Feature Pack and Sample for XML Database Integration Setup(With Apache Derby) Part 2/2: 이 기사에서 설명한 블로그 체크 프로그램 샘플 애플리케이션을 실행하도록 WebSphere Application Server와 Apache Derby를 구성한다.
- WebSphere Application Server V7.0 Feature Pack for XML: XML 기반의 문서 중심 애플리케이션 개발을 단순화하는 방법에 관해 자세히 배우자.
- WebSphere Application Server V7.0 Feature Pack for XML Information Center: 완전한 제품 문서를 확인하자.
- 샘플 애플리케이션 관련 문서: XML Feature Pack에 포함된 샘플 애플리케이션을 사용할 수 있게 도와주는 지시사항과 설치 문서 및 소스 코드를 얻자.
- SQLXML 유형: 세부사항은 완전한 클래스 문서를 참조하자.
- XPath 2.0 콜렉션: W3C 웹 사이트에서 콜렉션 함수에 대한 설명을 확인하자.
- WebSphere Community Blog: WebSphere Application Server Feature Pack for XML 관련 링크 목록을 확인하자.
- JDBC 4.0 SQLXML 인터페이스: 관련 문서를 확인하자.
- developerWorks의 XML 영역: XML 영역에서 기술 향상에 도움이 되는 참고자료를 얻을 수 있다.
- IBM XML 인증: XML 및 관련 기술에 대한 IBM 인증 개발자가 되는 방법을 찾아볼 수 있다.
- XML 기술 자료: developerWorks XML 영역에서 다양한 기술 관련 기사와 팁, 튜토리얼, 표준 및 IBM Redbook을 볼 수 있다.
- developerWorks 기술 행사 및 웹 캐스트: 이러한 세션에 참가하여 최신 기술에 대한 정보를 얻을 수 있다.
- Twitter의 developerWorks 페이지: 오늘 가입하여 developerWorks 트윗을 팔로우하자.
- developerWorks
podcasts: 소프트웨어 개발자의 흥미로운 인터뷰와 토론을 확인할 수 있다.
제품 및 기술 얻기
- 이 기사에 있는 샘플 웹 애플리케이션을 빌드하려면 다음과 같은 소프트웨어를 다운로드해야 한다.
- WebSphere Application Server V7.0 Feature Pack for XML: 개발자의 생산성을 개선하고 새로운 애플리케이션 개발 시나리오를 다루는 업데이트된 XML 프로그래밍 모델 표준이다.
- DB2 Express-C: 완전한 기능을 갖춘 유연한 관계형 및 XML 데이터 서버이다.
- Apache Derby: 완전히 Java 기술로 구현한 오픈 소스 관계형 데이터베이스이다.
- IBM 제품 평가판을 다운로드하거나 IBM SOA Sandbox의 온라인 시험판을 살펴보고 DB2®, Lotus®, Rational®, Tivoli® 및 WebSphere® 애플리케이션 개발 도구와 미들웨어 제품을 사용해 볼 수 있다.
토론
- XML 영역 토론 포럼: 여러 XML 관련 토론에 참여해 볼 수 있다.
- developerWorks 포럼 & 블로그를 통해 developerWorks 커뮤니티에 참여하자.
Bert joined IBM in 2001 to work on the XML project in DB2 as one of the early architects. Bert came to IBM from a startup company, Propel, where he led the design and implementation of the distributed and fault-tolerant middleware, which hosted a scalable e-commerce application. Before that, Bert worked for many years at Tandem Computers on the NonStop SQL, a database that runs many critical applications in the financial industry.
Andrew Spyker는 WebSphere Application Server 개발팀 STSM(Senior Technical Staff Member)으로 주로 세 가지 분야에 집중한다. 그는 5년간의 경험을 활용하여 WebSphere Application Server 성능팀을 이끌어 가고 있으며 이 팀에 조언을 아끼지 않는다. 그는 SOA 런타임 아키텍트로서 WebSphere SOA 런타임 전체의 일관성을 추진하며 주로 벤치마킹 전략, 성능 및 XML 일관성에 집중한다. 끝으로 그는 대부분의 시간을 WebSphere 포트폴리오의 XML 전략을 작성하고 추진하면서 보낸다. 최근에는 WebSphere Application Server XML Feature Pack 수석 아키텍트로 활동했다.