본문으로 바로가기

jQuery custom event

category Web Tech/jQuery 2016. 6. 16. 17:27

Event 란?

웹 프로그래밍에서의 이벤트란 사용자의 어떤 액션(개체를 클릭하거나, 마우스를 움직이는 행동)에 의해서 야기되는 사건을 의미하며, 그러한 이벤트에는 클릭, 마우스 오버, 키 입력 등이 있습니다. 

그리고, 일반적으로 그러한 이벤트가 발생하는 경우 특정 로직을 수행하기 위해서 해당 이벤트와 특정 메서드를 연결해서 사용하곤 합니다. 

이러한 연결을 이벤트 처리기 매핑(event hanlder mapping)이라고 하며, 매핑에 의해서 연결된 메서드들을 이벤트 처리기라고 합니다. 

Click, MouseOver, KeyPress 등등을 알고 있을 것입니다. 

이들이 이벤트 처리기들입니다. 

예를 들면, 여러분은 자바스크립트를 사용해서 다음과 같이 이벤트 처리기를 매핑할 수 있습니다.

javascript
Window.onload = pageLoad;

이 코드에서 이벤트는 onload 이고(일반적으로, 이벤트명 앞에는 on을 써서 표기합니다). 

이벤트 처리기는 pageLoad 입니다. 그리고, 그 둘을 연결하는 위의 코드를 이벤트 처리기 매핑 코드라고 부릅니다. 

즉, load 이벤트가 발생하는 경우에는 pageLoad라는 이벤트 처리기를 실행하라는 의미입니다. 

대개 이벤트 처리기(event handler)를 이벤트 핸들러 ~라고 원어 그대로 부르기도 합니다만, 어떻게 부르던 이해할 수만 있으면 됩니다.

사실 이벤트라는 것을 사용하는 것 자체는 하나도 복잡할 것이 없으며, 어려움없이 쉽게 사용할 수 있지만, 이벤트의 내부 동작방식을 이해하는 것은 살짝 어렵게 느껴질 수 있습니다. 




지금부터 이야기할 jQuery의 이벤트 관련 기능들은 대부분 이벤트 매핑을 쉽게 하는 방법에 대한 것입니다. 

기본적인 자바스크립트 이벤트 매핑 방식(위에서 보여드린 Window.onload = pageLoad;과 같은 것)도 나름대로 깔끔한 편이라 사용하기에 그리 큰 불편함은 없습니다만, 페이지의 구성이 복잡해지게 되면 사용상의 제약이나 코딩 상의 불편함이 생겨나곤 합니다. 

예를 들어, 버튼 개체에 동일한 이벤트를 여러 번 추가해야 하는 경우를 생각해 봅시다. 

즉, 페이지에 상단에서 button.onclick = button_click;와 같이 이벤트 매핑을 해 두었는데, 페이지의 하단에서 button.onclick = btn_click;와 같이 동일 이벤트에 대해 또 다른 이벤트 처리기를 덧붙여야 한다면 어떻게 해야 할까요?

어쩌면... 그럴 일이 왜 있지?! 그리고, 그런 경우가 생기면 설계가 잘못된거야! 걍 코드를 전부 button_click() 함수 안에 다 넣었어야 하는거 아닌가?! 라고 말씀하실 수 있습니다. 

물론, 일반적인 경우라면 그렇게 하면 됩니다. 


하지만, 동적으로 페이지를 꾸미는 경우에는 그렇게 하기가 어려운 경우도 있습니다. 

예를 들면, 마스터 페이지에서 클릭 이벤트를 매핑하고, 콘텐츠 페이지에서도 이벤트 처리기를 다시금 매핑해야 하는 경우도 생각보다 자주 있을 수 있기 때문입니다(Load 이벤트의 경우는 꽤 자주 이러한 처리가 필요합니다).

또한, 어떤 개체에 동적으로 이벤트 처리기를 매핑해야 하는 경우도 있을 수 있습니다. 다만, 동적으로 이벤트를 매핑한다고 해서 기존 매핑을 뒤집어 써서는 안될 것입니다.  이러한 다중 처리기 매핑의 경우는 기본 자바스크립트 매핑만으로는 설정하기가 다소 까다롭습니다.


그리고, 자바스크립트 기본 매핑 방식으로 설정하기가 좋지 않은 또 다른 예로는 “일회성 이벤트 매핑”을 들 수 있습니다. 

일회성 이벤트 매핑이란 것은 특정 이벤트가 한번만 동작하고 그 이후로는 동작되지 않는 것을 말합니다. 

예를 들면, 버튼이 처음 클릭되는 경우에는 처리기 메서드가 호출되지만 그 이후로는 클릭해도 메서드가 동작하지 않게 처리하게 하는 방법입니다.

기본 스크립트로 이러한 처리를 하려면, 버튼 클릭 이벤트 처리기 내부에서 이벤트 매핑을 제거하는 코드를 넣어야 합니다. 

사실, 이런 방식으로 코딩하는 것은 조금 깔끔하지 않은 프로그래밍처럼 느껴지곤 합니다. 

이벤트 매핑의 주체가 이벤트 처리기 자신이다보니 일종의 무한반복 호출 코드처럼 비춰질 수 있기 때문입니다.


이 외에도, 자바스크립트 기본 매핑을 사용할 경우 작업하기가 약간 복잡한 다양한 사례들이 존재합니다. 

비록 작업이 불가능하지는 않지만, 뭔가 개발이 복잡해지고, 지저분해지며, 관리하기에도 어려워진다는 것입니다. 

그렇기 때문에, jQuery는 이벤트와 관련한 코드를 간결하게 작성할 수 있도록 돕는 다양한 기능 또한 제공하고 있습니다.

이제부터 아래에서 jQuery에서 제공하는 사용자 정의 이벤트에 대해 알아보도록 하겠습니다.



jQuery 사용자 정의 이벤트 

상호 작용하는 웹 애플리케이션에서 브라우저의 DOM에서 자연스럽게 발생하는 이벤트는 매우 중요합니다.

하지만 jQuery 코드를 작성할 때 이런 이벤트들만 사용할 수 있는 것은 아니며 자유롭게 자신의 사용자 정의 이벤트(custom event)를 추가할 수 있습니다.

이는 플러그인 개발에서 jQuery UI 위젯에서도 많이 이용되는 방법입니다.

사용자 정의 이벤트는 코드에서 직접 발생시켜야 합니다. 어떤 의미에서는 사용자 정의 이벤트는 우리가 직접 정의하는 일반 함수와 유사한 면을 가지고 있습니다.

코드의 한 부분에서 이벤트를 발생시키면 다른 부분의 코드가 실행되기 때문입니다.

다시 말해서, on('click', ..) 이나 .bind()함수를 선언하는 것과 같고 .trigger()함수를 호출하는 것과 같은 셈입니다.

하지만 이벤트 핸들러는 이벤트를 발생시키는 코드에서 분리됩니다.

이는 이벤트를 발생시킬 때 어떤 일이 일어날지 알지 못해도 언제든 이벤트를 발생시킬 수 있다는 뜻입니다.

일반 함수처럼 단일 이벤트 핸들러를 실행시킬 수 있고, 혹은 여러 개의 핸들러를 실행시키거나 아예 실행시키지 않을 수도 있습니다.




jQuery Custom Event(제이쿼리 사용자 정의 이벤트)

jQuery 를 이용하면 두 가지 패턴을 이용하여 사용자 정의 이벤트를 만들 수 있습니다.


[단계 1]  이벤트 객체를 생성합니다.

[단계 2]  이벤트가 발생할 때 이벤트 리스너에 보낼 데이터를 생성합니다.

[단계 3]  이벤트를 발생시킵니다.


JavaScript
// [ 방법 1 ]
var event = jQuery.Event("사용자 정의 이벤트 이름 정의");
event.데이터1 = 값;
event.데이터2 = 값;

// 블라블라 코드 생략..

$이벤트를발생시킬대상.trigger(event);

// [ 방법 2 ]
var event = jQuery.Event("사용자 정의 이벤트 이름 정의");
$이벤트를발생시킬대상.trigger(event, [,데이터1 = 값, 데이터2 = 값,  ..... ])




Usage

아래와 같은 마크업과 JS가 있습니다.

html
<div class="test1">
  test1
</div>
<div class="test2">
  test2
</div>


JavaScript
// abc 이벤트를 등록해서 evt라는 변수명으로 연결해 놓는다.
// 클릭 다음에 오는 {} 객체로 이벤트가 발생할때 이벤트 객체에 값을 넣어 줄수 있다
var evt = jQuery.Event("abc", {
  relatedTarget: this,
  keyCode: 100,
});

//.test1을 클릭하면 .test2에 위에서 만들어 놓은 evt이벤트를 발생시킨다
$('.test1').on('click', function() {
  $(".test2").trigger(evt);
  return false;
});


// .test2에 abc 이벤트가 발생할때 콜백함수를 실행하도록 등록한다
$('.test2').on('abc', function(e) {
  console.log(e);
  console.log('keyCode: ', e.keyCode);
  console.log('relatedTarget: ', e.relatedTarget);
});


위의 스크립트 코드에서 .test1을 클릭하면 이벤트 핸들러에서 하는 일은 실질적으로 false 를 반환하는 역할 밖에 없습니다.

위에서 언급했듯이 .on() 메서드는 함수를 선언하는 것과 같고 .trigger()를 통해 함수를 호출하는 것과 같습니다.

이벤트가 발생했을 때 실행되는 코드는 위에서 사용자 정의된 abc 이벤트에서 모든 일을 처리하고 있습니다. 

abcevt 에 참조되어있기 때문에 trigger에 evt를 전달했으며, abc 이벤트는 .test2에 연결, 등록되어 있는 구조입니다.




방법 1, 2의 차이점 알아보기

위의 방법1,2 의 차이점은 이벤트 발생시에 리스너에게 데이터를 보내는 방법에 차이점이 있습니다.


이 둘의 차이점을 다음의 코드를 통해 알아보도록 하겠습니다.


다음은 [방법 1] 을 이용한 코드입니다.


See the Pen 사용자정의 이벤트 타입1 by jaeheekim (@jaehee) on CodePen.


사용자 정의 이벤트를 등록할 때는 on() 메서드를 사용하면 됩니다.

그리고 이벤트에 담은 데이터는 이벤트 리스너의 첫 번째 파라미터인 e(코드상)에 담겨 넘어오기 때문에 e.itemName, e.itemLength 로 접근하여 데이터를 사용하면 됩니다.



다음은 [방법 2] 를 이용한 코드입니다.


See the Pen 사용자정의이벤트 타입2 by jaeheekim (@jaehee) on CodePen.


방법 1과는 달리 이벤트 리스너로 넘기는 데이터를 이벤트 객체를 생성한 event(코드상의 이벤트객체)에 직접 생성하는 것이 아니라, trigger() 메서드의 매개변수 값으로 넘겨서 호출한다는 점이 다릅니다. 


보내질 데이터는 배열로 만들어줍니다.


그리고 on() 메서드를 이용하면 이벤트 리스너에는 두 번째 매개변수부터 trigger() 에 담아서 보낸 배열 데이터가 담기게 됩니다.



또 다른 방법을 이용한 코드는 다음과 같습니다.

See the Pen 사용자 정의 이벤트 테스트 by jaeheekim (@jaehee) on CodePen.



Jaehee's e-room