메시지 전달은 JAF에서 가장 중요한 기능 중 하나이다. 앱과 플러그인은 cast() 또는 broadcast() 함수를 사용해 메시지를 전달하고, API 리스너를 통해 메시지를 수신한다.
앱에서 cast 메서드를 사용해 메시지를 전달하면 이 메시지는 다음과 같은 순서로 전달된다.
반면, broadcast 메서드를 사용해 메시지를 전달하면 다음과 같은 순서로 전달된다.
플러그인에서 메시지를 전달하면 다음과 같은 순서로 전달된다.
예를 들어, 플러그인에서 PRINT라는 메시지를 전달했다고 가정해보자.
그림 1 플러그인에서 PRINT 명령어 전달
플러그인은 그림1처럼 cast() 명령어를 사용해 PRINT 메시지를 ['hello']라는 인수와 함께 전송한다.
그림 2 플러그인에서 PRINT 명령어 전달
그림 3. 앱에 등록된 모든 플러그인에 메시지 전달
전송된 메시지는 플러그인이 등록된 앱으로 전달된 후, 앱에 등록된 모든 플러그인에 다시 전달된다. 이 때, 메시지를 수신할 수 있는 API 리스너가 있을 때만 명령어가 실행된다. 그림 3에서 메시지는 빨간색 동그라미로 표시된 1, 2, 3 순서로 전달된다. 그러나, APP3과 Plugin4에는 PRINT 메시지를 수신할 API 리스너 API_PRINT가 없으므로 PRINT 메시지에는 동작하지 않는다. 즉, PRINT 메시지를 받고 동작을 수행하는 것은 Plugin3과 Plugin5뿐이다.
문서를 읽을 때 JAF는 ONREADY와 ONLOAD 메시지를 자동으로 전달한다. ONREADY 메시지는 웹 브라우저가 문서를 모두 읽고 DOM 준비를 마친 상태가 되었을 때 전달된다. 파이어폭스, IE9 등 최신 웹 브라우저에서 제공하는 DOMContentLoaded 이벤트와 동일한 시점이다. DOMContentLoaded 이벤트에 대한 자세한 정보는 https://developer.mozilla.org/en/Gecko-Specific_DOM_Events 를 참고하면 된다.
ONLOAD 메시지는 DOM 준비를 마쳤을 뿐만 아니라 문서에 포함된 외부 자원 즉, 이미지, 동영상, 음악 등을 모두 읽어들였을 때 전달된다. 대부분의 웹 브라우저에서 제공하는 window 객체의 onload 이벤트와 동일한 시점이다.
API 메시지를 수신하는 API 리스너는 앱이나 플러그인을 정의할 때 ‘API_메시지이름’과 같은 형태로 메서드를 작성하면 된다. 예를 들어, ‘PRINT’라는 메시지에 대한 API 리스너를 정의하려면 앱이나 플러그인을 정의할 때 API_PRINT라는 이름을 가진 메서드를 작성하면 된다.
/**
* PrintPlugin 플러그인
*/
var PrintPlugin = xe.createPlugin("PrintPlugin", {
// PRINT 메시지를 수신하는 API 리스너
API_PRINT : function(sender, params) {
… 실행할 코드 …
}
});
API 리스너의 첫 번째 인수는 메시지를 전송한 객체, 두 번째 인수는 메시지와 함께 전달되는 인수 배열이다.
API 리스너는 메시지를 수신할 때 코드를 실행하는 것은 물론 결과값을 반환할 수도 있다. 먼저 API 리스너에서는 간단하게 return 명령어를 사용해 결과를 반환할 수 있다.
/**
* 100을 더하는 앱
*/
var SumApp = xe.createApp ("Sum", {
// PRINT 메시지를 수신하는 API 리스너
API_SUM : function(sender, params) {
return (params[0] + 100); // 계산 결과 반환
}
});
var sumapp = new SumApp();
xe.registerApp(sumapp);
alert( sumapp.cast(‘API_SUM’, [50]) ); // 150 출력
그리고 cast() 명령어를 사용하면 API 리스너에서 반환한 값을 얻을 수 있다. 단, 값을 반환하는 것은 cast() 명령어 뿐 broadcast() 명령어는 값을 반환하지 않으므로 주의가 필요하다.
후킹이란 API 리스너가 동작하기 전이나 동작한 후를 가로채는 동작을 의미한다. 후킹을 사용하면 API 리스너를 동작하지 않도록 만들거나 전달되는 인수를 조작할 수 있다. 후킹은 후커 메서드를 통해 이루어집니다.
BEFORE 후커는 API 리스너가 동작하기 전을 가로채는 후커이다. API 리스너와 유사한 방법으로 작성하나 API 메시지 이름 앞에 BEFORE_ 를 추가한다는 점이 다르다. 예를 들어, PRINT 메시지에 대한 BEFORE 후커는 API_BEFORE_PRINT와 같이 작성할 수 있다.
BEFORE 후커는 API 리스너가 동작하지 않도록 만들 수 있다. 간단하게 BEFORE 후커에서 false를 반환하면 API 리스너가 동작하지 않는다. 이해를 돕기 위해 앞서 사용한 SumApp을 다시 예제로 사용했다.
/**
* 100을 더하는 앱
*/
var SumApp = xe.createApp ("Sum", {
// PRINT 메시지를 수신하는 API 리스너
API_SUM : function(sender, params) {
return (params[0] + 100);
}
});
var sumapp = new SumApp();
xe.registerApp(sumapp);
var OnlyNumber = xe.createPlugin("OnlyNumber", {
API_BEFORE_SUM : function(sender, params) {
if(typeof params[0] != ‘number’) {
alert(‘숫자값만 사용할 수 있다.’);
return false; // API_SUM 리스너의 동작을 취소한다.
}
}
});
var onlynumber = new OnlyNumber();
sumapp.registerPlugin(onlynumber);
alert( sumapp.cast(‘API_SUM’, [‘Not a Number’]) ); // 경고 메시지 출력 후 undefined 출력
OnlyNumber 플러그인은 전달되는 인수 배열의 첫 번째 값이 숫자인지 확인하고 만약 숫자가 아니라면 경고를 출력한 후 API_SUM 리스너의 동작을 취소한다. 즉, 메시지 인수의 첫 번째 값이 숫자가 아니라면 API_SUM 리스너는 동작하지 않는다. 위 예제에서 인수의 첫 번째 값은 숫자가 아니기 때문에 먼저 실행된 BEFORE_API_SUM 후커에 의해 경고 메시지가 출력되고 동작이 중단된다.
또한 API_BEFORE_BEFORE_PRINT와 같이 BEFORE 후커에 대한 BEFORE 후커도 작성할 수 있다.
AFTER 후커는 API 리스너가 동작한 후를 가로채는 후커이다. BEFORE 후커와 유사하게 작성할 수 있으나 BEFORE_ 대신 AFTER_를 추가한다는 점이 다릅니다. 예를 들어 API_SUM에 대한 AFTER 후커는 API_AFTER_SUM과 같이 작성할 수 있다.
AFTER 후커는 API 리스너 실행 후에 동작하므로 리스너의 실행을 취소하거나 반환되는 값을 수정할 수는 없다.