본문으로 바로가기
TaeyoungKim.dev

JavaScript 길게 누르기 버튼: 손을 떼면 타이머를 취소하는 법

웹작성 약 3분 읽기TaeyoungKim
LinkedInX

‘길게 눌러야 실행’이라고 적힌 버튼을 아주 짧게 누르고 뗐는데 잠시 뒤 작업이 실행된다. 누르기 시작할 때 setTimeout을 예약해 놓고, 손을 뗄 때 그 예약을 취소하지 않았기 때문이다. 길게 누르기는 타이머를 시작하는 코드와 취소하는 코드가 한 쌍이어야 한다.

setTimeout은 누르기가 끝나도 자동으로 사라지지 않는다

도식의 타이머에는 정상적으로 손을 뗀 경로와 브라우저가 입력을 취소한 경로가 모두 연결된다. 제한 시간이 되기 전에 어느 쪽이 와도 같은 정리 함수에서 예약을 해제해야 오래 누르기 동작이 뒤늦게 실행되지 않는다.

setTimeout은 지정한 시간이 지난 뒤 함수를 한 번 실행하도록 예약하고 타이머 ID를 돌려준다. 누르고 있는 동안에만 예약이 유효해야 한다면, 손을 떼거나 입력이 취소될 때 clearTimeout(ID)를 호출한다. 다음 예제는 실제 삭제나 결제를 하지 않고 상태 문구만 바꾸는 설명용 버튼이다.

html
<button type="button" id="hold">길게 눌러 확인</button>
<p id="result" aria-live="polite">대기 중</p>

<script>
  const button = document.querySelector('#hold');
  const result = document.querySelector('#result');
  let timerId = null;

  function cancelHold() {
    if (timerId === null) return;
    clearTimeout(timerId);
    timerId = null;
  }

  button.addEventListener('pointerdown', () => {
    cancelHold();
    result.textContent = '누르는 중';
    timerId = setTimeout(() => {
      timerId = null;
      result.textContent = '확인 완료';
    }, 800);
  });

  button.addEventListener('pointerup', cancelHold);
  button.addEventListener('pointercancel', cancelHold);
  button.addEventListener('pointerleave', cancelHold);
</script>

800밀리초는 동작을 설명하기 위한 예시일 뿐 보편적인 UX 기준은 아니다. 짧게 눌렀다 떼면 예약된 함수를 취소한다. 충분히 누르면 콜백이 먼저 실행되고 timerId가 다시 null이 된다. 누르는 중 다른 곳으로 포인터가 이동하거나 입력 자체가 취소돼도 정리한다. 누르기를 여러 번 시작했을 때 이전 예약이 남지 않도록 pointerdown에서 먼저 취소하는 이유도 여기에 있다.

타이머가 남는지 어떻게 재현하고 테스트할까?

먼저 짧게 누르고 800밀리초보다 길게 기다려 확인 완료가 나오지 않는지 본다. 다음에는 충분히 누른 뒤 한 번만 완료되는지 확인한다. 누르는 중 포인터를 버튼 밖으로 옮기거나 터치 입력이 취소될 때도 결과가 뒤늦게 바뀌지 않아야 한다. 느린 컴퓨터나 백그라운드 탭에서는 타이머 시각이 정확히 맞지 않을 수 있으므로 밀리초 단위의 정밀한 시계로 취급하지 않는다.

이 최소 예제는 포인터 입력만 보여 준다. 키보드 이용자를 위한 별도 조작이나 동등한 확인 수단 없이 실제 중요한 작업의 유일한 관문으로 사용하면 안 된다. 특히 계정 삭제나 결제처럼 되돌리기 어려운 작업을 클라이언트의 타이머만으로 승인하지 않는다. 서버 쪽 권한 확인과 별도의 확인 절차가 필요하다.

핵심 요약: 예약한 타이머의 종료 경로를 함께 설계한다

setTimeout으로 길게 누르기를 예약했다면 pointerup, pointercancel, 이탈처럼 누르기가 끝나는 경로에서 clearTimeout을 호출한다. 짧은 누르기, 긴 누르기, 입력 취소를 각각 테스트하고, 중요한 작업은 프런트엔드 타이머만 믿지 않는다.

작성자

TaeyoungKim

기초 개념을 구현과 검증, 실제 운영 판단까지 연결해 기록합니다.

#JavaScript#setTimeout#clearTimeout#Pointer Events#길게 누르기

함께 읽으면 좋은 글