감기에 걸려 약먹고 high해져 헤롱거리고 있습니다.
이번에도 결과물을 먼저 보죠.
티스토리 동영상 사이즈 조절이 안 되는군요. 최대 크기 제한이야 이해를 하지만 그보다 작으면 그냥 원래 사이즈로 나오게 해 줄 것이지 원-_-


part 5.에서 캐릭터가 나오고 사라질 때 fade-in/out 효과를 추가했습니다.
이것만으론 의미가 없겠죠?
내부적으로 캐릭터의 생명주기, 페이드 속도, 이동 속도를 외부 URL에 있는 XML로부터 로딩하도록 하였습니다.
즉, 외부 XML을 읽고 필요한 정보를 추출한 것이지요.

이 예제의 소스 코드는 여기.
이 예제의 매니페스트 XML 경로는 http://3m4you.co.kr/gongdo/gadgets/test05/test05.xml 입니다. 테스트 해보세요 :)

개짓에서 XML을 다루는 것은 매우 쉽게 구현되어 있습니다.
AJAX에 어느정도 익숙하신 분이야 HTTPRequest를 통하여 외부 URL의 리소스를 비동기로 가져오는 방식에 익숙하실 텐데요.

자바스크립트의 비동기 호출은 치명적인 약점을 가지고 있습니다.
바로, 자신을 로드한 도메인이 아니면 억세스를 할 수 없다는 것입니다.

이 문제를 해결하기 위해 웹서버 측에 프록시를 만들어 외부 리소스에 접근하는 방법을 사용하거나 아파치의 경우엔 컨피그에 접근을 허용하는 목록을 작성할 수 있는 걸로 알고 있는데요, 어느쪽이든 단순 웹 호스팅을 받고 있는 웹서버라면 접근이 불가능합니다.

사실 문제라기 보단 자바 스크립트의 엄격한 클라이언트 보안 대책이라고 해야 맞겠지요. 그래도 개발자에겐 불편하기 짝이 없는 장애물인데다가 프록시를 쓸 경우 서버의 부하도 늘어나고 반응 속도도 한참 떨어지게 됩니다.

라이브 개짓에서는 크로스 도메인 억세스가 가능한 비동기 요청 메소드를 제공하고 있습니다. 물론 이것도 내부적으로 프록시를 사용할테니 속도가 떨어진다는 점은 여전하지만 꽤 수고를 덜 수 있습니다.

개짓의 외부 리소스 요청은 Web.Network.createRequest() 메소드를 통해 이루어집니다.
자세한 사항은 레퍼런스를 참고하시면 되겠고, 여기서는 간단한 소개 정도만 하겠습니다.

createRequest는 자주 사용되는 리소스 형태에 대한 사전 정의를 세번째 파라미터를 통해 전달 할 수 있는데요, 개짓 API 가이드에서 볼 수 있는 사전 정의는 다음과 같은 종류가 있습니다.

  • RSS Proxy - {proxy:"rss", numItems:#}
    Start.Util.ParseRssResponse()라는 유틸리티 메소드를 통해 수신 받은 리소스를 RSS 피드로 파싱합니다.
    해당 메소드가 반환하는 객체는 rss.channel[index].item[num].title 과 같은 방식으로 편리하게 RSS 피드를 사용할 수 있습니다.
  • XML Generic Proxy - {proxy:"generic"}
    response.responseXML.documentElement라는 프로퍼티를 통해 수신 받은 리소스를 XML DOM으로 파싱된 document 엘리먼트를 얻을 수 있습니다.
    여느 XML DOM과 같은 방법으로 엘리먼트와 어트리뷰트에 접근할 수 있습니다.
  • Bypassing Proxy - {proxy:"none"}
    서드 파티에서는 사용할 필요가 없는 방법으로 프록시를 거치지 않고 직접 해당 리소스에 접근합니다. 하지만 위에서 밝혔듯이 자바스크립트는 자신을 로드한 도메인이 아니면 다른 도메인에 접근할 수 없으므로 의미가 없습니다.
    아마 MS 내부에서 사용하려고 만들었겠지요.
  • null - null
    수신 받은 리소스를 별도로 파싱하지 않고 그대로 반환합니다. 이것은 요청의 내용에 따라 수신 데이터가 달라지므로 모든 것은 콜백 함수에서 처리됩니다.
어쨌든 HTTPRequest보다 20배쯤 편합니다. 게다가 프록시도 제공되는 걸 감안하면 200배쯤 편하죠!

이 비동기 통신을 통해 얻은 리소스로 뭘 할 것인가는 전적으로 개발자에게 달렸습니다. :)
우선 RSS 프록시를 통해 파싱한 RSS 객체로는 손쉽게 웹상의 RSS 피드를 요리할 수 있겠고 null 프록시를 통해서 jpg와 같은 이미지 파일을 로딩할 수도 있을테고 웹 서비스를 받을 수도 있습니다.

이 예제에서 사용한 것 처럼 일반적인 XML 포맷이라면 generic 프록시를 사용하면 되는 데요, 이 부분을 좀 더 살펴보죠.

예제에서 사용된 config.xml 파일은 다음과 같이 정의 되어 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<config MaxTimeouts="10">
  <GhostSpeed>3</GhostSpeed>
  <FadeSpeed>10</FadeSpeed>
</config>
root 엘리먼트인 <config>가 있고 그 하위에 <GhostSpeed>와 <FadeSpeed>엘리먼트가 있습니다.
response.responseXML.documentElement프로퍼티로 전달 받은 객체는 곧 root 엘리먼트에 대한 Node 객체가 됩니다.
var root = response.responseXML.documentElement;
위와 같은 코드로 root 엘리먼트를 받을 수 있습니다.
config.xml의 루트 엘리먼트는 <config>엘리먼트이고 이 엘리먼트 안에 있는 MaxTimeouts 어트리뷰트의 값은 root.getAttribute("MaxTimeouts");와 같은 코드로 얻을 수 있습니다.

<config> 엘리먼트의 하위 엘리먼트인 <GhostSpeed>와 <FadeSpeed>엘리먼트는 root.childNodes[#] 프로퍼티로 얻을 수 있는데요 여기서 주의할 점은 <GhostSpeed> 엘리먼트 태그 사이에 있는 3이란 값은 <GhostSpeed> 엘리먼트의 값이 아니라 하위 엘리먼트의 값이라는 점입니다. 즉, 3이란 값도 지정된 이름이 없는 하나의 엘리먼트로 취급된다는 것이죠.

따라서 3이란 값을 얻기 위해선 root.childNodes[0].nodeValue가 아니라 root.childNodes[0].childNodes[0].nodeValue처럼 한 단계 더 내려가야 합니다.

XML DOM에 익숙하신 분이라면 이 같은 실수는 안하시겠지만 XML DOM을 제대로 모르는 저는 또 몇 시간 헤맸답니다. 좀 허탈했죠. =_=


총 6회에 걸쳐 개짓 개발 시작을 해서 겪은 과정을 포스팅 했습니다.
정리해보자면,
- 개짓 개발 준비
- 기본 구성 요소 작성
- HTML DOM을 동적으로 추가
- JavaScript로 이벤트 처리
- 동적인 화면를 위한 타이머 처리
- 외부 리소스를 로딩하는 방법
입니다.


이젠 구상하고 있던 것을 어느 정도 구현할 수 있을 것 같습니다.
과연 컨테스트 마감일까지 만들 수 있을지는 의문이지만 비록 컨테스트 참여를 못하더라도 의미 있는 코드를 만들어보고 싶네요.

한 가지 덧붙이고 싶은건 진행하는 내내 디버깅이 엄청나게 불편하고 문제가 생기면 정확히 어느 시점에서 생겼는지 확인하기가 정말 힘들었습니다.
제대로 개발을 하려면 디버깅을 위한 트레이스 툴 정도는 만들어놓고 시작해야 할 것 같네요.


▒차회 예고목표▒
- 좀 더 객체 지향적인 코드를 위해 사용자 정의 클래스를 작성하여 데이터와 명령을 관리합니다.
- 원활한 디버깅을 위해 트레이스 툴을 하나 만들어봅니다.
신고
Posted by gongdo


티스토리 툴바