Skip to main content

개요

Laravel의 큐 기능에는 잡의 중복 제거(Unique)디바운스(Debounce) 라는 두 가지 실행 제어 방식이 준비되어 있습니다. 둘 다 “같은 잡을 여러 번 디스패치했을 때 불필요한 실행을 줄이기 위한” 메커니즘이지만 동작 방식이 다릅니다.
Unique Jobs와 Debounced Jobs는 상호 배타적입니다. DebounceFor 어트리뷰트를 사용하는 잡에 ShouldBeUnique를 구현하지 마세요.

Unique Jobs — ShouldBeUnique

동일한 잡이 큐에 존재하는 동안에는 추가 디스패치를 무시합니다.
UpdateSearchIndex가 큐에 쌓여 있는(또는 처리 중인) 동안, 동일한 잡을 디스패치하려고 해도 무시됩니다.

키로 유니크 제약 좁히기 — UniqueFor + uniqueId()

동일한 잡 클래스라도 “상품 A 업데이트”와 “상품 B 업데이트”를 별개의 잡으로 취급하고 싶다면, uniqueId() 메서드로 키를 정의합니다.
  • uniqueId()가 반환하는 값이 캐시 락의 키가 됩니다.
  • #[UniqueFor(초)]를 지정하면 해당 시간이 경과한 후 락이 자동으로 해제됩니다(잡이 처리되지 않았을 경우의 페일세이프).

캐시 드라이버 지정 — uniqueVia()

기본 캐시 드라이버 외의 것을 사용하고 싶다면 uniqueVia()를 구현합니다.
Unique Jobs는 원자적 락을 지원하는 캐시 드라이버(redis, database, memcached, dynamodb, file, array)가 필요합니다.

ShouldBeUnique vs ShouldBeUniqueUntilProcessing

ShouldBeUnique의 락은 잡이 완료되거나 재시도 상한에 도달할 때까지 유지됩니다. 이것이 문제가 되는 경우가 있습니다. 예: 큐에 UpdateSearchIndex(product_id: 42)가 1건 있고, 워커가 처리를 시작한 직후 동일한 잡을 다시 디스패치하고 싶은 경우. ShouldBeUnique에서는 처리 완료까지 2건째가 큐에 들어가지 않습니다. 이럴 때는 ShouldBeUniqueUntilProcessing을 사용합니다. 락이 처리 시작 직전에 해제되므로, 워커가 잡을 꺼내는 순간 다음 디스패치가 가능해집니다.

비교 정리


Debounced Jobs — #[DebounceFor]

DebounceFor 어트리뷰트는 Laravel 13에서 추가된 기능입니다.
짧은 시간에 같은 잡이 대량으로 디스패치될 경우, 마지막에 디스패치된 1건만 실행합니다. 웹 프런트엔드의 디바운스와 같은 개념입니다.
  • debounceId()가 반환하는 값으로 잡을 식별합니다(상품 ID별로 독립적인 디바운스가 적용됨).
  • 30초 동안 같은 productId로 10번 디스패치되어도 마지막 1건만 실행됩니다.

maxWait — 최대 대기 시간 상한

자주 갱신되는 데이터에서는 디바운스가 계속 이어져 잡이 영원히 실행되지 않을 가능성이 있습니다. maxWait로 최대 지연 시간을 설정할 수 있습니다.
이 예에서는 최초 디스패치로부터 최대 120초 후에는 반드시 실행됩니다(30초 디바운스가 이어져도 120초에 타임아웃).

캐시 드라이버 지정 — debounceVia()

JobDebounced 이벤트

후속 디스패치에 의해 덮어쓰인 잡은 Illuminate\Queue\Events\JobDebounced 이벤트를 발생시키고 큐에서 제거됩니다. 이 이벤트를 리스닝함으로써 디바운스된 잡의 추적과 모니터링이 가능합니다.

어느 것을 사용해야 할까


내부 구현

Unique Jobs의 락 메커니즘

ShouldBeUnique 잡이 디스패치되면, Laravel은 내부적으로 캐시의 원자적 락을 획득합니다. 락 키는 다음 형식입니다:
락을 획득할 수 없는 경우(이미 다른 잡이 보유 중), 잡은 큐에 추가되지 않습니다.

Debounced Jobs의 구현

DebounceFor는 내부적으로 “디바운스 윈도”를 관리하는 캐시 엔트리를 사용합니다. 새로운 디스패치가 올 때마다:
  1. 기존 잡을 큐에서 삭제(JobDebounced 이벤트 발생)
  2. 새로운 잡을 큐에 추가(디바운스 초 지연 포함)
  3. 캐시 타이머 리셋
maxWait가 지정된 경우, 최초 디스패치의 타임스탬프도 기록하여 그 시각으로부터 maxWait초를 초과하는 디바운스를 방지합니다.

참고 링크

마지막 수정일 2026년 8월 2일