본문으로 바로가기

폼 검증을 위해 값의 변경을 감지한 후, 이벤트를 수신하여 유효성 검증을 하고 오류 메세지를 표시하는 작업에 열을 올리고 있었습니다. 실시간으로 변경되는 값을 수신하고 싶었고 관련하여 이벤트의 종류와 기능을 살펴보다가 어느정도 결론에 도달하여 내용을 공유합니다.

폼 검증시 사용되는 이벤트

기본적으로 폼 검증시에는 해당 input 필드에 값이 입력되고 포커스가 해제되면 발생하는 blur이벤트를 많이 사용한다. 대부분의 경우 유효한 방법이지만, 작성이 완료된 필드에 다시 돌아가는 일은 사용자 입장에서 여간 귀찮은 일이 아닐수 없다. 경우에 따라서는 키가 입력되는 순간 순간에 유효성을 검증해야 하는 경우도 생긴다. 아래의 예처럼 말이다.

실시간 이벤트 감지 사례

회원가입 폼에 대한 유효성 검증중에 비밀번호와 비밀번호 재입력란을 처리하고 있었다. 미리 입력된 패스워드와 재입력하는 부분을 비교해서 값이 다르다면 오류 메세지를 표시해야 하는데, 비밀번호를 재입력하는 부분에서는 실시간으로 비밀번호와 비교해서 오류메세지를 띄워야 사용자 경험이 더 좋을거라 판단했다.

비슷한 기능을 하는 이벤트로 change가 있다는 것을 얼핏 알고 있었는데, 이 또한 포커스가 해제되었을때 발생하는 이벤트라서 패스~, 좀 더 검색을 해보니 keyup 이벤트를 추천하고 있었다. 이는 키보드를 눌렀다가 떼었을때 발생하는 이벤트이다. 일단, 원하는 목적은 비밀번호를 타이핑할때에 발생하는 이벤트이니 목적은 달성할 수 있었다.

여기서 호기심 발동!, 복사&붙여넣기는 어떨까? input type="password" 필드를 type="text"로 변경한 후에, 이를 복사&붙여넣기를 실행해 보았다.

정상 작동하길래 마무리하려 했으나... 여기엔 함정이 있었다. 복사&붙여넣기를 키보드로 했다는 것! 그렇다. 마우스를 이용한 붙여넣기가 아닌 키입력이 발생하는 Ctrl + v를 이용한 것이였다.

마우스를 이용한 붙여넣기(컨택스트 메뉴를 이용한)를 실행해보니 역시나 이벤트가 수신되지 못하고 있다. 재밌는건 화상키보드를 이용하면 그것은 마우스로 누르지만 키보드 입력을 받는 것과 같은 결과를 가져온다.

물론, keyup 이벤트와 blur 이벤트를 함께 수신하면 문제는 해결된다. 마우스를 이용해서 붙여넣는다고 하더라도 포커스를 잃게 되는 순간 검증은 될터이니...

필자의 지랠같은 성격으론 이래서는 잠을 못이룬다. 해결되지 않는 것이 있다면 꿈속에서도 그것을 찾드라...

input 이벤트의 소개

input 이벤트는 input 혹은 textarea 요소에 값이 변경되면 동기적으로 발생하는 이벤트이다. 즉 값이 변경되자마자 즉시 발생하는 이벤트로, 키보드 및 다른 장치를 이용한 입력 모두에도 작동하는 이벤트이다. 붙여넣기를 하든 무엇을 하든 입력이 발생하면 이벤트가 발생한다.

모던 브라우저들에서는 모두 작동하나, IE9 는 버그를 포함하고 있고, IE8 이하에서는 작동하지 않는 이벤트이다.

input 이벤트 폴리필

IE9의 버그를 해결하고 IE8 까지 작동하는 input 이벤트를 대체하는 폴리필을 발견했다.

이 플러그인은 브라우저간의 차이를 추상화하여, 모든 브라우저에서 input 이벤트를 흉내내는 textchange 라는 합성 이벤트를 제공한다. 코드를 들여다보면 자세한 주석이 달려있다.

추상화란 개념 이해가 부족해서 찾아보았더니 아래와 같은 문구를 발견했습니다.

일반화: 여러가지 객체로 부터 공통된 점을 추출하여 새로운 객체를 만들어 내는 것. 예를 들어 남학생과 여학생을 일반화 한다면 학생 이라는 개념으로 일반화 시킬 수 있다.

추상화: 어떤 실제 객체로 부터 관심이 있는 부분만을 추출하고 나머지 부분은 무시하는 것(또는 숨기는 것). 대표적인 추상화의 예로 지하철 노선도를 들 수 있다. 지하철 노선도는 실제 지하철 노선 지도로 부터 각 지하철역의 위치 관계만을 추출한 것이다.

textchange 이벤트 사용법

jQuery를 삽입한 후에 해당 플러그인을 호출하여, 기타 jQuery 이벤트를 사용하듯 사용하면 된다.

$("#monkey").on("textchange", function() {
    // ...
});

사용자 입력으로 발생하는 모든 값의 변화에 이벤트가 발생하여 이를 수신할 수 있게 된다. 기본적으로 input 요소의 type="text"type="password" 만 이벤트를 확인한다. 아래의 수정된 버전은 textarea 도 이벤트를 확인한다.

필자와 같은 고민으로 시작해 결과를 얻어낸 플러그인다. 그의 고민의 흔적을 A near-perfect oninput shim for IE 8 and 9에서 엿 볼수 있다.

textchange 수정 버전

원본 소스가 관리가 안되고 있나본데 다른 사용자가 몇가지 버그와 기능을 추가한 버전을 배포했다

textchange v1.2 alpha2

  • Group all updates to a target element together and defer textchange event triggering to the next tick using setTimeout(..., 0)
    • Fixes cursor reset in textarea when textchange event handler sets a value
    • Reduces number of textchange notifications during drag & drop operations
  • Support drag & drop between input controls and dropping text from outside the browser
    • When text is moved from one element to another via drag & drop, one textchange event for each element is fired
  • Reduce use of activeElement
  • Permanently override value, not just when element has focus
  • Add version information (currently random choice of 1.2 alpha1)
  • Tested in IE8 on Windows XP, IE9 on Win7 (both using ModernIE VM), simulated IE8 and IE9 mode in IE11 on Windows 8.1, Chrome and Firefox

A textchange event is fired the first time an element is focused (even though focusing did not change the value)