Riot 프레임워크 알아보기. (5/6) Event Emitter(Observable)

emitter

Observer? Observable!

Riot은 기본적으로 커스텀 태그, 이벤트 시스템(Observable), 라우터의 세가지를 제공한다. 이 세가지는 클라이언트 웹어플리케이션을 개발하는데 있어 필수사항이라고 볼 수 있다. 이 요소들은 주로 다음과 같은 목적을 갖고 있다.

  1. 커스텀 태그는 사용자 인터페이스를 위해
  2. 이벤트는 모듈화를 위해
  3. 라우터는 URL과 뒤로가기 버튼 기능을 위해

앞서 시리즈에서는 커스텀 태그에 대해 알아보았으니, 오늘은 Observable에 대해 설명할 생각이다.

Observable은 이벤트를 주고 받기위한 일반적인 수단으로써, 종속적이거나 강하게 결합된 방식없이 모듈화할 수 있도록 돕는다. 이러한 방식은 큰 프로젝트를 다 작고 단순하게 나누고, 프로젝트의 다른 부분에 영향을 주지않고 모듈을 추가, 삭제, 수정하는 작업이 가능하도록 해준다.

주된 사용패턴으로 어플리케이션의 하나의 코어와 여러개의 확장으로 나누는 것이다. 코어는 어떤 사건이 발생했을때 언제든지 이벤트를 발생시킨다. 사건이라함은 아이템이 추가되거나, 삭제되거나 또는 서버로 부터 무언가를 로딩되는등의 일들을 의미한다.

이러한 환경에서 코어는 각 확장 모듈들에 대해 알지 못한다. 단지, 확장모듈들이 코어를 바라볼 뿐이므로 코어와 다른 확장모듈에 영향을 주지않고 모듈의 추가, 수정, 삭제가 가능하다. 이러한 방식을 “약한 결합(loose coupling)”이라고 부른다.

결국, 확장모듈을 쉽게 개발하기 위해서는 코어와 이벤트를 잘 설계하고 유지해야만 한다.

riot.observable(el)

특정 객체가 observable을 지원하도록 만들거나 observable 인스턴스를 만들어 리턴을 하든, Riot에서 Observable 객체를 만들고 사용하는것은 매우 간단하다. Riot 문서의 예제에 있는 샘플 부터 보겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Car() {
// Make Car instances observable
riot.observable(this)
// listen to 'start' event
this.on('start', function() {
// engine started
})
}
// make a new Car instance
var car = new Car()
// trigger 'start' event
car.trigger('start')

이렇게 car인스턴스를 observable하게 만들수도 있고

1
2
3
4
5
const el = riot.observable({})
el.on('start', function() {
// engine started
})
el.trigger('start')

이렇게 빈객체를 가지고도 observable 인스턴스를 손쉽게 만들 수 있다. 이 둘의 차이점은 없다. “.on(…)” 이벤트 핸들러가 포함되어 있나, 아니냐의 차이뿐이다. 물론, 경우에 따라 편리한 방법대로 사용하면 된다.

이벤트 핸들러는 이벤트와 함께 원하는 파라미터를 콜백 인자로 받을 수도 있다.

1
2
3
4
5
6
7
// listen to 'start' event and expect extra arguments
el.on('start', function(engine_details, is_rainy_day) {
})
// trigger start event with extra parameters
el.trigger('start', { fuel: 89 }, true)

engine_details는 { fuel: 89 }가 되고, is_rainy_day는 true이다.

이벤트명은 간단히 “.”표기법을 이용해 네임스페이스를 구분할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// listen to start and start.honda events
el.on('start.honda', function() {
})
// trigger all start events (including start.honda)
el.trigger('start')
// trigger only start.honda events
el.trigger('start.honda')
// remove only honda start events
el.off('start.honda')
// remove all start events (including start.honda)
el.off('start')