Tag Archives: ajax

Prototype Javascript Framework – Ajax

이번엔 신나고 재미있는 Ajax에 대해서 알아보도록 하죠.

Ajax 개발을 해보신분들이라면 아시겠지만 Ajax는 생각해야 할것이 굉장히 많습니다.

그래서 크로스 브라우징이니 예외처리니 신경 쓸것이 많이 있죠.

하지만 Prototype의 Ajax 클래스를 보게되면 깜짝 놀라실 겁니다. 별로 신경 쓸것이 없기 때문이죠.

한번 볼까요?

1. Ajax.Request

Prototype에서 제공하는 Ajax 래핑 매서드중에 가장 기본적인 메서드입니다.

Hash 타입의 옵션을 줄 수 있고 onComplete, onSuccess같은 Ajax 콜백 함수를 제공합니다.

Javascript타입의 결과가 리턴될 경우에는 해당 JS를 자동으로 실행하여 주기도 합니다.

Ajax의 옵션은 뒤에 설명하겠습니다. 기본적인 예제를 한번 볼까요?

[code]var url = ‘/proxy?url=’ + encodeURIComponent(‘http://www.google.com/search?q=Prototype’);
new Ajax.Request(url, {
  // GET 방식으로 전송
  method: ‘get’,
  // 실행이 성공하여 정상적으로 결과가 반환 되었을 때
  onSuccess: function(transport) {
    // notice 엘리먼트를 찾습니다.
    var notice = $(‘notice’);
    // 결과 텍스트가 “/href=http://prototypejs.org/ 일때
    if (transport.responseText.match(/href=”http:\/\/prototypejs.org/))
      // notice에 다음의 글을 출력하고 배경 색을 바꿈
      notice.update(‘Yeah! You are in the Top 10!’).setStyle({ background: ‘#dfd’ });
    else
      // notice에 다음의 글을 출력하고 배경 색을 바꿈
      notice.update(‘Damn! You are beyond #10…’).setStyle({ background: ‘#fdd’ });
  }
});[/code]

기본적으로 실행은 new를 붙여 새로운 객체를 생성해야 합니다.

정확히는 각각의 브라우저마다 다른 Ajax 컨트롤을 생성하기 위해서 new로 선언합니다.

Request의 라이프사이클은 다음과 같습니다.

1. Ajax 컨트롤 생성
2. 초기화
3. Request 전송
4. Response 수신 (패킷이 전송되는 동안 시간이 꽤 걸릴수도 있습니다)
5. Response 수신 종료, Request 작업 종료

일반적으로 Ajax 개발을 해보셨다면 아시겠지만 onSuccess라는 콜백 함수가 조금 생소하실 겁니다.

위의 onSuccess는 Ajax에서 기본적으로 제공하는 콜백 함수가 아니라 Prototype에서만 존재하는 함수입니다.

Ajax 전송이 성공 하였을 경우에만 실행이 되죠. 기존의 경우에는 다음과 같이 처리했어야만 했습니다.

[code]new Ajax.Request(‘/your/url’, {
   onComplete: function(transport) {
   if (200 == transport.status)
   // 작업 처리
   }
}); [/code]

onComplete 콜백 함수에서 status가 200인걸 확인하는게 보이십니까? 200은 정상적으로 수신되었음을 뜻합니다.

위의 과정을 Prototype에서는 다음과 같이 처리 할 수 있습니다.

[code]new Ajax.Request(‘/your/url’, {
   onSuccess: function(transport) {
   // 역시나 작업 처리
   }
);[/code]

간편한것이 좋군요.

특히나 Prototype은 순수한 자바스크립트 Reponse에 대해 자동으로 그것을 실행하는 기능도 갖추고 있습니다.

이 기능을 사용할려면 Response의 헤더의 MIME 타입이 다음중 한가지여야 합니다.


  • application/ecmascript

  • application/javascript

  • application/x-ecmascript

  • application/x-javascript

  • text/ecmascript

  • text/javascript

  • text/x-ecmascript

  • text/x-javascript

이번엔 Response의 헤더를 가져오는 방법을 알아보도록 하죠.

[code]new Ajax.Request(‘/your/url’, {
  onSuccess: function(response) {
  // 헤더의 ‘Server’ 정보를 가져와 Apache라는 단어가 있는지 확인한다
  if ((response.getHeader(‘Server’) || ”).match(/Apache/))
    ++gApacheCount;
  }
});[/code]

마지막으로 이런것을 하나만 알아보고 넘어가도록 하죠. 결과 Response에는 headerJSON이라는 값이 있습니다.

결과 리턴시에 X-JSON 이라는 헤더에 JSON 값을 넣어 넘길 수 있습니다.

이것은 굳이 Body가 필요없는 작은 데이터이거나 메인 데이터 이외의 메타 데이터를 넘겨줄때 유용합니다.

[code]new Ajax.Request(‘/your/url’, {
  onSuccess: function(transport) {
    transport.headerJSON
  }
});[/code]

headJSON은 자동으로 JSON형식의 객체로 바뀌어 반환되며 X-JSON 헤더가 없거나 잘못된 JSON형식일 경우에는 null이 반환됩니다.

2. Ajax.Updater

이 메서드는 Ajax.Request를 좀더 특별하게 만든 녀석입니다. 결과 텍스트를 원하는 컨테이너 역할을 할 엘리먼트의 내용으로 넣습니다.

[code]new Ajax.Updater(‘items’, ‘/items.jsp’, {
  parameters: { text: $F(‘text’) }
});[/code]

위에서 알 수 있듯이 text인자에 text라는 id를 가진 폼 엘리먼트의 값을 담아 parameters에 담아 items.jsp 페이지를 호출합니다.

그리고 결과를 items라는 이름의 id를 가진 엘리먼트에 바로 삽입 합니다.

정말 간편하죠. JS 코드라던가 HTML 코드가 모두 사용 가능합니다. 삽입 위치까지 지정할 수 있습니다.

관련 옵션을 한번 봐볼까요?

evalScript (디폴트 : false)
결과중에 <script>태그가 존재할경우 그 내용을 수행합니다.

insertion (디폴트 : NONE)
기본적으로 Ajax.Updater는 결과를 원하는 컨테이너의 내용으로 넣지만(update 메서드 이용함) 기존의 내용을 해치지 않으며 값을 원하는 위치에 넣을 수 있습니다.
top, bottom, before, after 의 인자를 사용합니다. 어떤건지는 각자 생각해 보시길.^^

자, 다음으로는 evalScript에 대해서 알아봅시다.

이 옵션이 true로 설정되면 <script> 태그 이하의 스크립트가 실행됩니다. 그렇지만 이것이 HTML 결과 페이지에 <script>로 붙는것을 의미하는것은 아닙니다.

실행해 보시면 알겠지만 저 옵션이 켜지면 Ajax.Updater의 실행 결과에서 해당 부분이 빠져있습니다.

이것은 간단하게 Javascript Native 함수인 eval()을 거치기 때문입니다.

여기서는 두가지 중요한 점이 있습니다.

스크립트에서 선언한 변수와 함수들이 Local Scope를 가지고 있을 경우 이것은 그 해당 <script> 내부에서만 유효합니다. var 등으로 선언된 변수는 실행이 끝남과 동시에 폐기됩니다.

function을 이용해 선언한 함수들은 외부에서 접근할 수 없습니다. 외부에서 접근이 가능한 함수를 만들려면 다음과 같은 것을 생각해야 합니다.

[code]// Ajax.Updater에서 호출된 스크립트중 아래와 같은 함수는 작동하지 않음
function coolFunc() {
  // 내부 실행 코드
}[/code]

[code]// Ajax.Updater에서 호출된 스크립트중 아래와 같이 선언한 함수는 정상 작동 함
coolFunc = function() {
  // 내부 실행 코드
}[/code]

이것이 무슨 말인고 하니 아래의 내용을 참고하시면 되겠습니다.

[code]// Ajax.Updater를 통해 호출된 함수 1
function Func1() { alert(‘Hello’) }

// Ajax.Updater를 통해 호출된 함수 2
Func2 = function () { alert(‘World’) }

// 특정 버튼 클릭시 함수 실행
$(‘input’).observe(‘click’, function() {
  Func1(); // 에러남
  Func2(); // 정상 실행 됨
});[/code]

다음으로 결과를 담을 컨테이너를 성공시와 실패시로 구분지어 사용하는 방법이 있습니다.

무조건 성공할 경우에만 결과를 출력할려면 다음과 같이 하면 됩니다.

[code]new Ajax.Updater({ success: ‘items’ }, ‘/items’, {
  parameters: { text: $F(‘text’) },
  insertion: Insertion.Bottom
}); [/code]

첫번째 컨테이너 옵션에 success를 붙여 넣었군요. success말고 failure도 지정할 수 있습니다.

실패시에는 이 id를 가진 엘리먼트를 사용하겠다는것인데 솔직히 이용 용도를 모르겠습니다-_-a

[code]new Ajax.Updater({ success: ‘items’, failure: ‘notice’ }, ‘/items’, {
  parameters: { text: $F(‘text’) },
  insertion: Insertion.Bottom
}); [/code]

성공시에는 items로 실패시에는 notice에 결과가 삽입되겠군요.

3. Ajax.PeriodicalUpdater

이번엔 매우 재미 있는 클래스를 알아봅시다. 이녀석은 Ajax.Updater를 특정한 간격으로 지속적으로 실행시켜주는 역할을 합니다.

Ajax.Updater와 동일하지만 두가지 추가된 옵션이 있습니다.

frequency (디폴트 : 2)
이것은 몇초마다 수행할 것인가를 정하는 옵션입니다. 디폴트로 2초로 되어있습니다. 정한 초마다 Ajax.Updater를 수행하게 됩니다.

decay (디폴트 : 1)
이것은 매우 신비한 옵션입니다. 아마도 서버 부하를 줄이기 위해 태어난 옵션이 아닐까 생각합니다. Decay를 사전에서 검색해 보니 썩다, 부패하다 이런 뜻이네요. 그럴싸 합니다.
frequency에서 지정한 대로 새로운 Ajax.Updater를 수행한 후에 그 결과물이 이전과 동일하다면 실제로 결과값을 바꾸는 작업을 수행하지 않습니다. 그리고 Ajax.PeriodicalUpdater 의 decay 값이 옵션으로 입력한 decay와 곱한 값 만큼 증가 합니다. 그리고 다음 실행할 시간은 requency * decay 값으로 지정됩니다. 결과물이 이전과 다르다면 내용을 update하고 decay값은 1로 바뀝니다.

예) 다음의 경우 어떻게 수행 될 것인가?
[code]new Ajax.PeriodicalUpdater(‘items’, ‘/items’, {
  method: ‘get’, frequency: 3, decay: 2
});[/code]

사용자 삽입 이미지
다음과 같이 중지 시켰다가 재시작 할 수도 있습니다.
[code]var updater = new Ajax.PeriodicalUpdater(‘items’, ‘/items’, {
  method: ‘get’, frequency: 3, decay: 2
});

// 중지
updater.stop();

// 시작
updater.start();[/code]

4. Ajax.Responders

이번에도 매우 흥미로우면서도 재미있는 녀석입니다. 이녀석은 Ajax 전역 핸들러입니다.

페이지내 모든 Ajax 콜백에 대하여 해야할 명령들을 지정할 수 있습니다. 마치 스프링 프레임워크의 AOP를 보는 기분이네요.

Prototype 소스에 보면 다음과 같이 사용하고 있는 부분이 있습니다.

[code]Ajax.Responders.register({
  onCreate:   function() { Ajax.activeRequestCount++ },
  onComplete: function() { Ajax.activeRequestCount– }
});[/code]

모든 Ajax 컨트롤의 생성시에 Ajax.activeRequestCount 값을 증가시키고 해당 작업 종료시에는 그 값을 감소시킵니다.

Ajax.activeRequestCount 값을 찍어보면 현재 실행중인 Ajax 컨트롤의 숫자를 알 수 있겠군요.

[code]Ajax.Responders.register({
  onComplete: function() {
    alert(‘Ajax 통신 종료’);
  }
});[/code]

위와 같이 한다면 통신이 종료될 때 마다 Alert창을 띄우겠네요. register 명령으로 다수의 콜백함수를 지정할 수 있습니다.

반대로 Ajax.Responders.unregister() 메서드로 등록한 콜백함수를 제거할 수도 있습니다.

5. 기타

Ajax.Response 와 Ajax 옵션들을 정리할려고 했는데 이건 굿이 정리 안해도 프로토타입의 잘 만들어져 있는 API문서를 보시면 될것 같습니다.

Ajax.Request 에서 결과값으로 받는 response에 대한 정보 보기 [ Ajax.Response ]

Ajax 에서 사용하는 옵션들과 콜백 함수 목록 보기 [ Ajax Options ]