> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Horizon

> Laravel Horizon을 사용해 Redis 큐를 시각적으로 관리·감시하는 방법을 설명합니다. 대시보드, 밸런스 전략, Supervisor 설정, 통지까지 아우릅니다.

## Horizon 이란

[Laravel Horizon](https://github.com/laravel/horizon)은 Laravel의 **Redis 큐 전용** 감시 대시보드입니다. 잡의 스루풋·실행 시간·실패 상황을 실시간으로 가시화하고, 워커 설정을 코드로 관리할 수 있습니다.

<Info>
  Horizon은 큐의 기초 기능을 확장하는 패키지입니다. 먼저 [큐와 잡](/ko/queues)의 기본을 이해하고 나서 진행해 주십시오. 또한 백엔드에는 반드시 [Redis](/ko/redis)가 필요합니다.
</Info>

```mermaid theme={null}
flowchart LR
    Browser["브라우저"] -->|"/horizon"| Dashboard["Horizon<br>대시보드"]
    Dashboard -->|"감시·제어"| Horizon["Horizon<br>프로세스"]
    Horizon -->|"잡 관리"| Redis["Redis<br>Queue"]
    Redis -->|"잡 취득"| Worker1["워커 1"]
    Redis -->|"잡 취득"| Worker2["워커 2"]
    Redis -->|"잡 취득"| Worker3["워커 3"]
```

## 설치

<Warning>
  Horizon은 Redis를 큐 백엔드로 사용합니다. `config/queue.php`의 `QUEUE_CONNECTION`이 `redis`로 설정되어 있는지 확인해 주십시오. 현시점에서 Redis Cluster에는 대응하고 있지 않습니다.
</Warning>

Composer로 설치합니다.

```shell theme={null}
composer require laravel/horizon
```

설치 후 Horizon의 애셋과 설정 파일을 공개합니다.

```shell theme={null}
php artisan horizon:install
```

이 명령어로 `config/horizon.php`와 `app/Providers/HorizonServiceProvider.php`가 생성됩니다.

## 설정

### config/horizon.php 의 구성

`config/horizon.php`는 워커의 설정을 모두 관리하는 파일입니다. 중심이 되는 설정이 `environments` 옵션입니다.

```php theme={null}
'environments' => [
    'production' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['default', 'notifications'],
            'balance' => 'auto',
            'autoScalingStrategy' => 'time',
            'minProcesses' => 1,
            'maxProcesses' => 10,
            'balanceMaxShift' => 1,
            'balanceCooldown' => 3,
            'tries' => 3,
            'timeout' => 60,
        ],
    ],

    'local' => [
        'supervisor-1' => [
            // 그 외의 값은 defaults 섹션에서 상속됩니다
            'maxProcesses' => 3,
        ],
    ],
],
```

<Info>
  Horizon은 내부에서 `horizon`이라는 이름의 Redis 접속을 사용합니다. `config/database.php`에서 이 이름을 다른 접속에 사용하지 마십시오.
</Info>

### 슈퍼바이저(Supervisor)

각 환경은 하나 이상의 "슈퍼바이저"를 가질 수 있습니다. 슈퍼바이저는 워커 그룹의 관리 단위이며, 서로 다른 큐·밸런스 전략·프로세스 수를 갖는 여러 슈퍼바이저를 동일 환경에서 움직일 수 있습니다.

### 기본값

`defaults` 옵션으로 모든 슈퍼바이저에 적용되는 기본값을 설정할 수 있습니다.

```php theme={null}
'defaults' => [
    'supervisor-1' => [
        'connection' => 'redis',
        'queue' => ['default'],
        'balance' => 'auto',
        'tries' => 1,
        'timeout' => 60,
        'maxProcesses' => 1,
    ],
],
```

### 유지보수 모드

애플리케이션이 유지보수 모드일 때, Horizon은 기본적으로 잡을 처리하지 않습니다. 강제로 처리시키려면 `force` 옵션을 사용합니다.

```php theme={null}
'environments' => [
    'production' => [
        'supervisor-1' => [
            'force' => true,
        ],
    ],
],
```

### 잡의 최대 시도 횟수

```php theme={null}
'environments' => [
    'production' => [
        'supervisor-1' => [
            'tries' => 10,
        ],
    ],
],
```

`tries`를 `0`으로 하면 무제한 재시도를 허가합니다.

### 잡의 타임아웃

```php theme={null}
'environments' => [
    'production' => [
        'supervisor-1' => [
            'timeout' => 60,
        ],
    ],
],
```

<Warning>
  `timeout`은 `config/queue.php`의 `retry_after`보다 수 초 짧은 값을 설정해 주십시오. 또한 `auto` 밸런스 전략에서는 이 값보다 긴 잡을 강제 종료시키는 경우가 있습니다.
</Warning>

### 백오프(재시도의 대기 시간)

예외 발생 후 재시도까지의 대기 초 수를 지정합니다.

```php theme={null}
// 고정값
'backoff' => 10,

// 단계적(지수 백오프)
'backoff' => [1, 5, 10],
```

## 밸런스 전략

Horizon에는 3종류의 워커 밸런스 전략이 있습니다.

<AccordionGroup>
  <Accordion title="auto(기본값)">
    큐의 부하에 따라 워커 수를 자동 조정합니다. `minProcesses`와 `maxProcesses`로 범위를 지정합니다.

    ```php theme={null}
    'supervisor-1' => [
        'balance' => 'auto',
        'autoScalingStrategy' => 'time', // 또는 'size'
        'minProcesses' => 1,
        'maxProcesses' => 10,
        'balanceMaxShift' => 1,
        'balanceCooldown' => 3,
    ],
    ```

    * `time` — 큐를 비울 때까지의 추정 시간으로 스케일링
    * `size` — 큐 내의 잡 수로 스케일링

    <Info>
      `auto` 전략에서는 큐의 순서가 우선도를 의미하지 않습니다. 우선도를 강제하고 싶은 경우 여러 슈퍼바이저를 사용해 주십시오.
    </Info>
  </Accordion>

  <Accordion title="simple">
    워커 수를 고정하고, 지정한 큐에 균등하게 분배합니다.

    ```php theme={null}
    'supervisor-1' => [
        'balance' => 'simple',
        'processes' => 10,
        'queue' => ['default', 'notifications'],
    ],
    ```

    위에서는 `default`와 `notifications`에 각각 5프로세스씩 할당됩니다.
  </Accordion>

  <Accordion title="false(밸런스 없음)">
    큐를 열거한 순서대로 엄격히 우선합니다. Laravel 기본의 큐 시스템과 같은 동작이지만, 적체에 따라 워커 수를 스케일링합니다.

    ```php theme={null}
    'supervisor-1' => [
        'balance' => false,
        'queue' => ['default', 'notifications'],
        'minProcesses' => 1,
        'maxProcesses' => 10,
    ],
    ```

    `default` 큐의 잡이 항상 `notifications` 큐보다 먼저 처리됩니다.
  </Accordion>
</AccordionGroup>

## 대시보드의 인가

Horizon의 대시보드는 `/horizon` 라우트에서 접근할 수 있습니다. 로컬 환경에서는 기본적으로 누구나 접근할 수 있지만, **운영 환경**에서는 게이트 정의로 접근을 제한합니다.

`app/Providers/HorizonServiceProvider.php`의 `gate()` 메서드를 편집합니다.

```php theme={null}
use App\Models\User;
use Illuminate\Support\Facades\Gate;

protected function gate(): void
{
    Gate::define('viewHorizon', function (User $user) {
        return in_array($user->email, [
            'admin@example.com',
        ]);
    });
}
```

인증을 필요로 하지 않는 경우(IP 제한 등으로 보호하고 있는 경우), 인수를 옵셔널로 합니다.

```php theme={null}
Gate::define('viewHorizon', function (User $user = null) {
    // IP 주소 등으로 제한하고 있는 경우
    return true;
});
```

## Horizon 의 기동

### 기본 명령어

```shell theme={null}
# 기동
php artisan horizon

# 일시 정지 / 재개
php artisan horizon:pause
php artisan horizon:continue

# 특정 슈퍼바이저의 일시 정지 / 재개
php artisan horizon:pause-supervisor supervisor-1
php artisan horizon:continue-supervisor supervisor-1

# 스테이터스 확인
php artisan horizon:status
php artisan horizon:supervisor-status supervisor-1

# 그레이스풀 셧다운
php artisan horizon:terminate
```

### 로컬 개발: 자동 재기동

파일 변경을 감지해 Horizon을 자동 재기동하려면 `horizon:listen` 명령어를 사용합니다.

```shell theme={null}
npm install --save-dev chokidar
php artisan horizon:listen

# Docker / Vagrant 환경에서는
php artisan horizon:listen --poll
```

### Supervisor 에 의한 상시 기동

운영 환경에서는 Supervisor를 사용해 Horizon을 상시 가동시킵니다.

#### Supervisor 의 설치

```shell theme={null}
sudo apt-get install supervisor
```

#### 설정 파일의 작성

`/etc/supervisor/conf.d/horizon.conf`를 작성합니다.

```ini theme={null}
[program:horizon]
process_name=%(program_name)s
command=php /home/forge/example.com/artisan horizon
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/example.com/horizon.log
stopwaitsecs=3600
```

<Warning>
  `stopwaitsecs`는 가장 긴 잡의 실행 시간보다 큰 값을 설정해 주십시오. 너무 작으면 Supervisor가 잡을 도중에 강제 종료시켜 버립니다.
</Warning>

#### Supervisor 의 기동

```shell theme={null}
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon
```

#### 배포 시

코드를 배포할 때마다 Horizon을 재기동해 변경을 반영합니다.

```shell theme={null}
php artisan horizon:terminate
```

Supervisor가 `autostart=true` / `autorestart=true`로 되어 있으면, 종료 후에 자동으로 재기동됩니다.

## 잡의 관리

### 태그

Horizon은 잡에 관련된 Eloquent 모델을 자동 검출해 태그를 붙입니다.

```php theme={null}
// Video 모델(id=1)을 받는 잡 → 자동으로 "App\Models\Video:1" 태그가 붙음
RenderVideo::dispatch(Video::find(1));
```

수동으로 태그를 정의하려면 `tags()` 메서드를 구현합니다.

```php theme={null}
class RenderVideo implements ShouldQueue
{
    /**
     * @return array<int, string>
     */
    public function tags(): array
    {
        return ['render', 'video:'.$this->video->id];
    }
}
```

이벤트 리스너에서는 이벤트 인스턴스가 `tags()` 메서드에 전달됩니다.

```php theme={null}
class SendRenderNotifications implements ShouldQueue
{
    public function tags(VideoRendered $event): array
    {
        return ['video:'.$event->video->id];
    }
}
```

### 사일런트화

대시보드의 "완료된 잡" 리스트에 표시하고 싶지 않은 잡은 `config/horizon.php`에서 사일런트화할 수 있습니다.

```php theme={null}
'silenced' => [
    App\Jobs\ProcessPodcast::class,
],

// 태그 단위로 사일런트화
'silenced_tags' => [
    'notifications',
],
```

`Silenced` 인터페이스를 구현하는 방법도 있습니다.

```php theme={null}
use Laravel\Horizon\Contracts\Silenced;

class ProcessPodcast implements ShouldQueue, Silenced
{
    use Queueable;
    // ...
}
```

## 메트릭과 모니터링

Horizon의 메트릭 대시보드에는 잡·큐의 스루풋과 실행 시간이 표시됩니다. 정기적으로 스냅숏을 취득하기 위한 스케줄을 설정합니다.

```php theme={null}
// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('horizon:snapshot')->everyFiveMinutes();
```

메트릭 데이터를 모두 삭제하려면 다음을 실행합니다.

```shell theme={null}
php artisan horizon:clear-metrics
```

## 잡 실패의 통지

큐의 대기 시간이 길어졌을 때 통지를 받을 수 있습니다. `app/Providers/HorizonServiceProvider.php`의 `boot()` 메서드에서 설정합니다.

```php theme={null}
use Laravel\Horizon\Horizon;

public function boot(): void
{
    parent::boot();

    Horizon::routeMailNotificationsTo('admin@example.com');
    Horizon::routeSlackNotificationsTo('slack-webhook-url', '#ops');
    Horizon::routeSmsNotificationsTo('15556667777');
}
```

### 대기 시간의 임계값

`config/horizon.php`의 `waits` 옵션으로 통지 트리거가 되는 대기 초 수를 설정합니다.

```php theme={null}
'waits' => [
    'redis:critical' => 30,  // 30초 이상 대기로 통지
    'redis:default' => 60,
    'redis:batch' => 120,
],
```

`0`을 설정하면 그 큐의 통지는 무효화됩니다.

## 실패 잡의 관리

실패한 잡은 ID 또는 UUID로 삭제할 수 있습니다.

```shell theme={null}
# 특정 실패 잡을 삭제
php artisan horizon:forget 5

# 모든 실패 잡을 삭제
php artisan horizon:forget --all
```

큐의 잡을 모두 소거하려면 다음을 사용합니다.

```shell theme={null}
# 기본 큐 소거
php artisan horizon:clear

# 특정 큐 소거
php artisan horizon:clear --queue=emails
```

## 업그레이드

Horizon의 메이저 버전 업데이트 시에는 [업그레이드 가이드](https://github.com/laravel/horizon/blob/master/UPGRADE.md)를 반드시 확인해 주십시오.

## 관련 페이지

<CardGroup cols={2}>
  <Card title="큐와 잡" href="/ko/queues">
    Laravel 큐의 기본. 잡의 작성·디스패치·배치 처리·실패 처리를 설명.
  </Card>

  <Card title="Redis" href="/ko/redis">
    Horizon의 백엔드로서 필요한 Redis의 설정과 사용법.
  </Card>
</CardGroup>


## Related topics

- [캐시](/ko/cache.md)
- [패키지의 버전 호환성 관리](/ko/advanced/package-versioning.md)
- [큐와 잡](/ko/queues.md)
- [Laravel Sentinel — 라우트 보호 미들웨어 조사](/ko/blog/sentinel-introduction.md)
- [2026년 4월 Laravel 업데이트](/ko/blog/changelog/202604.md)
