jQuery / Method / .delay() - 효과 대기열의 다음 작업을 정해진 시간만큼 지연하는 메서드

jQuery의 .delay()는 효과 대기열에서 뒤에 오는 작업의 실행을 늦춥니다. 실행 중인 함수 자체를 멈추거나 JavaScript 전체를 잠시 중지하는 기능은 아닙니다. 큐를 사용하지 않는 일반 메서드는 .delay() 뒤에 이어 써도 기다리지 않을 수 있습니다.

어느 작업이 기다리는지 구분하기

.delay() 공식 문서의 형식은 .delay(duration, queueName)입니다. duration은 밀리초이며 queueName을 생략하면 기본 효과 큐 fx에 대기 작업을 넣습니다. 큐는 해당 요소에서 순서대로 실행할 작업의 대기열입니다. 앞 작업이 끝나 지연 작업 차례가 되어야 기다리기 시작합니다.

뒤에 연결한 작업 기본 효과 큐 사용 .delay() 뒤에서의 의미
.fadeIn()·.fadeOut() 기본적으로 사용 앞선 대기 뒤 효과 시작
.show(0) 시간을 지정한 효과로 사용 기다린 뒤 즉시 표시
.show()·.hide() 인수가 없는 즉시 형식은 사용하지 않음 체인에 있어도 바로 실행 가능

.delay(800)은 기본 큐에 800밀리초의 대기를 추가합니다. "fast"와 "slow"도 각각 200·600밀리초로 사용할 수 있지만, 명확한 대기 비교에는 숫자가 이해하기 쉽습니다. 지연은 앞 작업의 실행 시간과 별도입니다. 효과 200밀리초 뒤에 delay 800을 넣으면 그 효과가 끝난 다음 800밀리초를 더 기다립니다.

show(0)과 show()를 비교하는 전체 예제

전체 코드를 UTF-8의 delay-demo.html로 저장하고 브라우저에서 엽니다. 공식 jQuery 전체 파일을 CDN(Content Delivery Network, 콘텐츠 전송 네트워크)에서 읽을 인터넷 연결이 필요하며 별도 설치는 없습니다. effects가 빠진 slim 파일은 사용하지 않습니다.

코드는 4.0.0을 사용합니다. 큐에서의 대기, 즉시 표시, JavaScript의 계속 실행, 대기 중 초기화와 일반 타이머 취소를 3.7.1과 4.0.0에서 실행해 확인했습니다. 두 상자는 처음 숨겨져 있고 각 버튼이 서로 다른 상자를 제어합니다.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Delay a queued effect, not JavaScript</title>
  <style>
    body { font: 16px/1.6 sans-serif; margin: 24px; }
    .box { display: none; padding: 16px; margin: 12px 0; background: #e4f2ef; }
    button, select { padding: 8px; margin: 4px; }
  </style>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
  <h1>Delay a queued effect, not JavaScript</h1>
  <label for="wait">Wait:</label>
  <select id="wait"><option value="800">800 ms</option><option value="200">200 ms</option></select>
  <button type="button" id="run">Queued show(0)</button>
  <button type="button" id="trap">Immediate show()</button>
  <button type="button" id="reset">Reset</button>
  <div class="box" id="queued">A queued display operation</div>
  <div class="box" id="plain">An immediate display operation</div>
  <p>Queue phase: <span id="phase">ready</span></p>
  <p id="continued"></p>
  <p id="result" aria-live="polite"></p>
  <script>
    $(function () {
      const $queued = $("#queued");
      const $plain = $("#plain");
      let busy = false;
      function report() {
        const queued = $queued.is(":visible") ? "visible" : "hidden";
        const plain = $plain.is(":visible") ? "visible" : "hidden";
        $("#result").text(`queued=${queued} | plain=${plain}`);
      }
      $("#run").on("click", function () {
        if (busy) return;
        busy = true;
        $("#phase").text("waiting");
        $queued.stop(true, false).hide()
          .delay(Number($("#wait").val()))
          .show(0, function () {
            busy = false;
            $("#phase").text("done");
            report();
          });
        $("#continued").text("Script continues immediately");
        report();
      });
      $("#trap").on("click", function () {
        $plain.stop(true, false).hide()
          .delay(Number($("#wait").val())).show();
        report();
      });
      $("#reset").on("click", function () {
        $queued.add($plain).stop(true, false).hide();
        busy = false;
        $("#phase").text("ready");
        $("#continued").text("");
        report();
      });
      report();
    });
  </script>
</body>
</html>

초기 결과는 다음과 같습니다.

queued=hidden | plain=hidden
  1. Wait을 800 ms로 두고 Queued show(0)를 누릅니다. Queue phase는 waiting, 첫 상자는 숨김 상태입니다.
  2. Script continues immediately 문구는 곧바로 나타납니다. .delay()가 다른 JavaScript 실행을 막지 않는다는 뜻입니다.
  3. 대기 뒤 첫 상자가 표시되고 phase는 done, 결과는 queued=visible | plain=hidden입니다.
  4. Reset 후 Immediate show()를 누르면 둘째 상자는 기다리지 않고 나타나 queued=hidden | plain=visible입니다. 인수 없는 .show()가 큐 밖에서 실행되기 때문입니다.
  5. Reset 후 Wait을 200 ms로 바꾸고 Queued show(0)를 누르면 더 짧게 기다립니다.
  6. 800 ms 대기 중 Reset을 누르면 두 상자는 계속 숨겨지고 phase는 ready입니다. 원래 대기 시간이 지난 뒤에도 첫 상자가 다시 나타나지 않습니다.

.show(0)의 0은 ‘앞의 대기를 취소’하는 값이 아니라, 그 작업이 큐에서 실행될 차례가 된 후 표시 효과에 걸리는 시간입니다. 바로 표시하는 .show()와 대기열에 넣는 .show(0)을 같은 방식으로 취급하지 않습니다.

대기열과 초기화 범위를 관리하기

.queue()는 요소의 작업 대기열을 다룹니다. 기본 fx 외에 이름 있는 큐를 사용하면 같은 이름으로 지연과 후속 작업을 넣어야 합니다. 사용자 정의 큐는 자동 시작을 가정하지 말고 .dequeue("work")처럼 해당 이름으로 시작합니다.

Reset의 .stop(true, false)는 이 예제의 효과 큐를 정리하고 현재 진행을 중단합니다. 테스트한 두 버전에서 대기 중 초기화 후 예정된 표시가 실행되지 않는 것을 확인했습니다. .delay() 자체는 일반 타이머 ID나 독립적인 취소 핸들을 반환하지 않으므로, 이를 모든 JavaScript 작업의 예약·취소 수단으로 사용하지 않습니다.

.clearQueue()는 아직 실행되지 않은 큐 항목을 제거합니다. 현재 진행 중인 효과를 멈추는 것과 남은 작업을 제거하는 것은 구분해야 합니다. 이 실습은 두 상자만 정리하고, 실행 중 Queued show(0) 추가 요청은 busy로 무시해 대기가 계속 쌓이지 않게 합니다.

일반 함수 예약과 취소에는 타이머 사용하기

애니메이션 대기열과 관계없는 작업을 나중에 실행하려면 setTimeout()으로 함수를 예약합니다. 취소가 필요하면 반환된 ID를 clearTimeout()에 전달합니다. 개발자 도구의 Console에 다음 부분 코드를 실행하면 800밀리초 뒤의 later 출력은 취소되고 cancelled만 출력됩니다.

const timer = setTimeout(() => console.log("later"), 800);
clearTimeout(timer);
console.log("cancelled");
cancelled

타이머나 효과 큐의 시간은 정밀한 실행 시각 보장이 아닙니다. 브라우저의 다른 작업과 탭 상태에 따라 실행이 더 늦어질 수 있으므로, 중요한 후속 처리는 고정된 시간을 추측해 기다리기보다 실제 완료 시점에 연결합니다.

기다리지 않는 것처럼 보이면 후속 메서드가 큐를 쓰는지, 같은 요소와 같은 큐 이름을 다루는지 확인합니다. 상자가 나타나지 않으면 실제 선택 결과와 대상의 존재, 사용자 정의 큐 시작 여부, Network의 전체 jQuery 로딩과 Console 오류를 점검합니다.