개발노트/jQuery

[jQuery] 이벤트 바인딩 삭제하기 (unbind vs off)

dev-mylee 2025. 2. 5. 09:23

오늘 코드 리뷰하다가 이벤트 중복 바인딩 이슈가 있어서 해보는 정리

🤔 이벤트 중복 바인딩이 발생하는 경우

실제로 발견한 중복 코드:

// 상단에 있던 코드
$('#btnSearch').unbind().click(_eventSearch); //검색 버튼 클릭

// 하단에 있던 코드
$('#btnSearch').click(function(e){
    $("#page").val(1);
    _eventSearch();
    e.preventDefault();
});

 

이러면 검색 버튼 누를 때 _eventSearch 함수가 두 번 실행될 수 있음.

근데 다행히 unbind()가 있어서 이전 이벤트는 제거됐었다.

 

 

비슷한 중복 패턴들:

// 패턴 1: document.ready 안에서 중복
$(document).ready(function() {
    $('#btnSave').click(saveData);
});
$(document).ready(function() {
    $('#btnSave').click(checkAndSave);  // 두 개의 ready에서 같은 버튼에 이벤트 등록
});

// 패턴 2: Ajax 로드 후 이벤트 중복 등록
function loadData() {
    $.ajax({
        success: function() {
            $('#btnRefresh').click(refreshList);  // Ajax 성공할 때마다 이벤트가 쌓임
        }
    });
}

// 패턴 3: 모달창 열 때마다 이벤트 중복 등록
function openModal() {
    $('#modal').show();
    $('#modalSaveBtn').click(saveModal);  // 모달 열 때마다 이벤트가 계속 추가됨
}

 

 

 

🛠 해결 방법 1: unbind() 사용

// 이전 방식
$('#btnSearch').unbind().click(function() {
    console.log('검색!');
});

unbind()는 요소에 등록된 모든 이벤트를 제거함. 근데 이제는 잘 안 씀...

 

 

 

🚀 해결 방법 2: off() 사용 (추천!)

위에서 봤던 중복 패턴들의 해결 방법:

// 패턴 1 해결: 한 곳에서만 이벤트 등록
$(document).ready(function() {
    $('#btnSave').off('click').on('click', function() {
        checkAndSave();
        saveData();
    });
});

// 패턴 2 해결: Ajax 성공 시 이전 이벤트 제거
function loadData() {
    $.ajax({
        success: function() {
            $('#btnRefresh').off('click').on('click', refreshList);
        }
    });
}

// 패턴 3 해결: delegate 방식 사용
$(document).on('click', '#modalSaveBtn', saveModal);

★ off()가 더 세밀한 제어가 가능하고 성능도 좋음.

 

 

 

💡 실제로 많이 쓰는 Best Practice

// 동적 요소에 대한 이벤트 처리 - 이게 젤 좋음
$(document).on('click', '#btnSearch', function() {
    console.log('검색!');
});

// Ajax 성공 후 이벤트 재바인딩
$.ajax({
    success: function() {
        $('#btnSearch').off('click').on('click', handler);
    }
});

 

 

 

🌟 오늘의 교훈

  1. 새로운 프로젝트면 무조건 off() 쓰자
  2. 동적 요소는 delegate 방식으로 처리하면 이벤트 제거 신경 안써도 됨
  3. 레거시 코드를 만나면 unbind()도 볼 수 있으니 알아두면 좋음
  4. 이벤트 등록 코드는 한 곳에서 관리하자
  5. 모달이나 Ajax로 동적 생성되는 요소는 delegate 패턴 사용하자