
# 소개

Queuety은 빠른 작업 큐, 내구성 있는 워크플로우 엔진 및 내구성 있는 상태 머신 런타임을 제공하는 WordPress 플러그인입니다. 워커는 MySQL에서 직접 작업을 가져와 장시간 실행되는 WP-CLI 프로세스 안에서 처리합니다. WordPress 및 WP-CLI을 로드하는 PHP 런타임에는 `mysqli` 또는 `pdo_mysql`이 필요합니다.

## Queuety을 사용하는 이유는 무엇인가요?

WordPress에는 실제 백그라운드 작업 시스템이 없습니다. `wp_cron`은 페이지 방문 시에만 실행됩니다. Action Scheduler의 기본 실행기는 WP-Cron 및 루프백 HTTP 요청을 이용하며, 각 요청은 최대 30초 동안 배치를 처리합니다. 60초가 걸리는 LLM API 호출은 PHP의 30초 시간 초과로 종료됩니다. 충돌 후에도 살아남아 중단 지점에서 재개하는 다단계 프로세스를 실행할 방법이 없습니다.

Queuety은 세 가지 기본 요소로 이 문제를 해결합니다:

1. **작업**은 실행 후 잊어도 되는 백그라운드 작업에 사용합니다.
2. **워크플로우**는 상태를 유지하는 내구성 있는 다단계 프로세스에 사용합니다.
3. **상태 머신**은 오래 지속되는 이벤트 기반 수명 주기 상태를 모델링합니다.

## 빠른 예제

최신 API을 사용해 작업을 디스패치하세요:

```php
use Queuety\Contracts\Job;
use Queuety\Dispatchable;

readonly class SendEmailJob implements Job {
    use Dispatchable;

    public function __construct(
        public string $to,
        public string $subject,
        public string $body,
    ) {}

    public function handle(): void {
        wp_mail( $this->to, $this->subject, $this->body );
    }
}

SendEmailJob::dispatch( 'user@example.com', 'Welcome', 'Hello from Queuety!' );
```

또는 기존 핸들러 이름 방식을 사용하세요:

```php
use Queuety\Queuety;

Queuety::dispatch( 'send_email', [ 'to' => 'user@example.com' ] );
```

내구성 있는 워크플로우를 실행하세요:

```php
Queuety::workflow( 'generate_report' )
    ->then( FetchDataHandler::class )
    ->then( CallLLMHandler::class )
    ->then( FormatOutputHandler::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

상태 머신으로 오래 지속되는 세션을 모델링하세요:

```php
use Queuety\Enums\StateMachineStatus;

Queuety::machine( 'agent_session' )
    ->state( 'awaiting_user' )
    ->on( 'user_message', 'planning' )
    ->state( 'planning' )
    ->action( PlanSessionAction::class )
    ->on( 'planned', 'completed' )
    ->state( 'completed', StateMachineStatus::Completed )
    ->dispatch( [ 'thread_id' => 42 ] );
```

워커를 시작하세요:

```bash
wp queuety work
```

에이전트 스타일 시스템을 구축한다면 [에이전트 오케스트레이션](https://queuety.inline0.dev/ko/docs/workflows/agent-orchestration)부터 시작하세요. 플래너/실행기 흐름, 사람의 검토 단계, 워크플로우 간 대기가 어떻게 함께 작동하는지 설명합니다.

시스템이 이벤트 기반이고 오래 지속된다면 워크플로우와 함께 [상태 머신](https://queuety.inline0.dev/ko/docs/state-machines)부터 살펴보세요.

엔드투엔드 통합 예제가 필요하면 [예제](https://queuety.inline0.dev/ko/docs/examples)를 확인하세요. 여기에는 제공자 전환, 스트리밍, 메모리 기반 검토 반복 및 종속 워크플로우를 위한 Neuron 기반 패턴이 포함되어 있습니다.

WordPress 같은 `save_post` 도메인 이벤트에서 워크플로우를 시작하려면 [액션 트리거](https://queuety.inline0.dev/ko/docs/features/action-triggers)를 확인하세요.

DB 기반 런타임을 WordPress 외부에서 사용하려면 [독립 실행형 사용](https://queuety.inline0.dev/ko/docs/features/standalone-use)을 확인하세요.

## 주요 차별점

- **빠른 실행.** 워커는 직접 MySQL 큐에 액세스하므로 WordPress의 백그라운드 작업을 느리게 만드는 요청별 cron 패턴을 피합니다.
- **내구성 있는 워크플로우.** 지속 상태를 사용하는 다단계 프로세스는 PHP 시간 초과, 충돌 및 재시도에도 유지됩니다. 각 단계 경계는 원자적 MySQL 트랜잭션입니다.
- **명시적 상태 머신.** 이름이 지정된 상태, 가드가 있는 전환, 큐에 등록되는 상태 진입 작업, 내구성 있는 이벤트 타임라인으로 채팅 세션, 승인 및 기타 장기 수명 주기를 모델링합니다.
- **최신 디스패치 API.** `Dispatchable` 트레이트, 페이로드 역할을 하는 타입 지정 생성자 속성, 클래스에 선언된 `$tries`/`$timeout`/`$backoff`을 사용하는 독립형 작업 클래스입니다. `readonly` 클래스에서는 이러한 속성에 기본값을 지정할 수 없으므로 readonly 승격 생성자 속성을 사용하는 일반 클래스에 선언하세요.
- **미들웨어 파이프라인.** 속도 제한, 예외 스로틀링, 고유 작업 및 사용자 지정 로직을 위한 양파형 미들웨어입니다. 작업별 `middleware()` 메서드로 선언합니다.
- **스트리밍 단계.** `StreamingStep` 인터페이스는 청크를 생성해 데이터베이스에 즉시 저장합니다. 재시도 시 이전에 저장된 청크가 전달되므로 스트림을 중단된 지점부터 재개할 수 있습니다. LLM 응답 및 대용량 다운로드에 적합합니다.
- **플러그형 캐시 계층.** `CacheFactory`은 APCu를 자동 감지하고, 사용할 수 없으면 메모리 내 캐시로 대체합니다. 사용자 지정 백엔드는 `Contracts\Cache`를 구현합니다. 속도 제한 조회 및 큐 상태에 내부적으로 사용됩니다.
- **배칭 및 체이닝.** `then`/`catch`/`finally` 콜백과 진행률 추적을 사용해 작업 그룹을 디스패치하거나, 앞 작업이 완료되어야 다음 작업이 진행되는 순차 작업 체인을 구성합니다.
- **내구성 있는 지연 및 대기.** `delay()`은 프로세스가 재시작되어도 유지되는 지연을 추가합니다. `wait_for_signal()`, `wait_for_signals()`, `wait_for_approval()`, `wait_for_input()` 및 `wait_for_workflow()`을 사용하면 PHP을 계속 실행하지 않고도 외부 이벤트나 다른 워크플로우를 기다리도록 워크플로우를 일시 중지할 수 있습니다.
- **동적 for-each.** `for_each()`는 워크플로우 상태에서 런타임에 검색된 분기 작업을 확장하고 전체 성공, 첫 성공 및 정족수 완료 모드를 지원합니다.
- **비동기 워크플로우 핸드오프.** `start_workflows()`은 런타임에 검색된 항목을 나중에 기다릴 수 있는 독립적인 최상위 워크플로우로 전환합니다.
- **WordPress 액션 트리거.** `on_action()`은 코어 또는 플러그인 액션 훅을 게이팅 및 멱등성을 갖춘 내구성 있는 워크플로우 디스패치에 연결합니다.
- **내구성 있는 아티팩트.** 이름이 지정된 워크플로우 출력을 기본 상태 저장소 외부에 저장하고 상태, CLI 검사, 내보내기 및 재생 과정에서 유지합니다.
- **워크플로우 가드레일.** `version()`, 결정적 정의 해시, 멱등성 디스패치 키 및 워크플로우 예산을 통해 에이전트 스타일 실행을 더 쉽게 검사하고 중복 실행이나 제어되지 않는 실행을 방지합니다.
- **리소스 관리.** 동시성 그룹, 비용 단위, 워크플로우 예산 및 워커 승인으로 비용이 큰 에이전트 스타일 작업을 정해진 한도 안에서 실행하도록 합니다.
- **단계 보상.** `compensate_with()` 및 `compensate_on_failure()`는 워크플로우가 취소되거나 실패할 때 완료된 단계를 롤백하는 훅을 제공합니다.
- **하트비트.** 장시간 실행되는 단계는 하트비트를 전송해 오래된 작업 복구 시스템이 활성 작업을 회수하지 못하게 합니다.
- **워크플로우 추적.** 모든 단계 전환은 입력, 출력, 전후 상태, 컨텍스트, 아티팩트, 청크, 오류와 함께 기록되며 `workflow_state_at()`을 사용한 시간 여행 디버깅도 지원합니다.
- **병렬 단계.** 여러 단계를 동시에 실행하고 모두 완료될 때까지 기다린 후 다음 단계로 진행합니다.
- **조건부 분기.** `_next_step`을 사용해 이전 상태에 따라 이름이 지정된 단계로 건너뜁니다.
- **워크플로우 실행.** 결과를 부모에게 반환하는 자식 워크플로우를 시작합니다.
- **우선순위 큐.** 타입 안전 PHP 열거형을 통해 낮음, 보통, 높음, 긴급의 네 가지 우선순위를 지원합니다.
- **다중 큐 워커.** 하나의 워커에서 엄격한 우선순위 순서로 여러 큐를 처리합니다.
- **속도 제한.** 슬라이딩 윈도우 방식으로 핸들러별 실행 횟수를 제한합니다.
- **반복 작업.** 간격 기반 및 cron 기반 예약과 구성 가능한 중복 실행 정책(허용, 건너뛰기, 버퍼링)을 지원합니다.
- **워크플로우 취소.** 실행 중인 워크플로우를 취소하고 등록된 정리 핸들러를 실행합니다.
- **상태 정리.** 오래된 단계 출력을 자동으로 제거해 대형 워크플로우 상태를 관리하기 쉽게 유지합니다.
- **워커 동시성.** `--workers=N`는 여러 프로세스를 분기하고 충돌 시 자동으로 재시작합니다.
- **완전한 관측성.** 데이터베이스 로깅, 핸들러별 메트릭 및 이벤트 웹훅을 제공합니다.
- **테스트 유틸리티.** `QueueFake`는 단위 테스트에서 단언할 수 있도록 디스패치된 작업과 배치를 기록합니다.
- **PHP 속성.** `#[QueuetyHandler('name')]`을 사용해 설정 없이 핸들러를 등록합니다.

## 작동 방식

워커는 오래 실행되는 WP-CLI 프로세스 안에서 실행되며 MySQL에서 직접 작업을 가져옵니다. 큐 행, 워크플로우 상태, 로그, 배치, 신호 및 스트리밍 청크는 모두 MySQL에 저장되므로 워커가 재시작되어도 오케스트레이션 상태가 사라지지 않습니다.

워크플로우는 장시간 실행되는 작업을 단계로 나눕니다. 각 단계는 출력을 데이터베이스의 공유 상태 저장소에 유지합니다. PHP이 단계 실행 중 종료되면 워커는 이전 상태를 모두 보존한 채 해당 단계를 재시도합니다. 단계 경계는 하나의 MySQL 트랜잭션입니다. 상태 업데이트, 작업 완료 및 다음 단계 큐 등록이 모두 원자적으로 수행됩니다.

```
Workflow: generate_report (3 steps)

Step 0: fetch_data     -> state: {user_data: {...}}
Step 1: call_llm       -> PHP dies -> retry -> state: {user_data: {...}, llm_response: "..."}
Step 2: format_output  -> state: {user_data: {...}, llm_response: "...", report_url: "/reports/42.pdf"}

Workflow: completed
```

## 요구 사항

- PHP 8.2 이상
- WordPress 6.4 이상
- MySQL 8.0+ 또는 MariaDB 10.6+ (워커가 `SELECT ... FOR UPDATE SKIP LOCKED`를 사용해 작업을 가져오기 때문)
- WordPress 및 WP-CLI을 로드하는 PHP 런타임의 `mysqli` 또는 `pdo_mysql`
- `wp queuety work`로 전용 워커를 실행하기 위한 WP-CLI
- 워커 풀을 위한 `pcntl` 및 `posix` PHP 확장(`--workers`, `--min-workers`, `--max-workers`)

설치는 [시작하기](https://queuety.inline0.dev/ko/docs/getting-started)를 참고하세요.
