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

# Envoy

> Laravel Envoy를 사용하여 원격 서버상의 배포 작업이나 Artisan 명령을 Blade 문법으로 정의·실행하는 방법을 설명합니다.

## 시작하기

[Laravel Envoy](https://github.com/laravel/envoy)는 원격 서버에서 자주 사용하는 작업을 실행하기 위한 도구입니다. [Blade](/ko/blade)와 같은 문법을 사용하여 배포나 Artisan 명령 실행 등의 작업을 간단히 정의할 수 있습니다.

<Info>
  Envoy는 현재 macOS와 Linux만 지원합니다. Windows에서 사용할 경우 [WSL2](https://docs.microsoft.com/ko-kr/windows/wsl/install-win10) 경유의 이용이 필요합니다.
</Info>

## 설치

Composer 패키지 매니저를 사용하여 프로젝트에 Envoy를 설치합니다.

```shell theme={null}
composer require laravel/envoy --dev
```

설치 후, `vendor/bin` 디렉터리에 Envoy 실행 파일이 이용 가능해집니다.

```shell theme={null}
php vendor/bin/envoy
```

## 작업 만들기

### 작업 정의

작업은 Envoy의 기본 구성 요소입니다. 작업은 작업 실행 시 원격 서버상에서 실행해야 할 셸 명령을 정의합니다. 예를 들어 모든 큐 워커 서버에서 `php artisan queue:restart` 명령을 실행하는 작업을 정의할 수 있습니다.

Envoy 작업은 모두 애플리케이션 루트에 있는 `Envoy.blade.php` 파일에 정의합니다.

```blade theme={null}
@servers(['web' => ['user@192.168.1.1'], 'workers' => ['user@192.168.1.2']])

@task('restart-queues', ['on' => 'workers'])
    cd /home/user/example.com
    php artisan queue:restart
@endtask
```

위와 같이 파일 맨 앞에서 `@servers` 배열을 정의하고, 각 작업 선언의 `on` 옵션에서 이 서버들을 참조합니다. `@servers` 선언은 반드시 한 줄로 작성하세요. `@task` 선언 안에는 작업 실행 시 서버에서 실행할 셸 명령을 작성합니다.

#### 로컬 작업

서버의 IP 주소를 `127.0.0.1`로 지정함으로써 스크립트를 로컬 컴퓨터에서 강제로 실행할 수 있습니다.

```blade theme={null}
@servers(['localhost' => '127.0.0.1'])
```

#### Envoy 작업 임포트

`@import` 디렉티브를 사용하면 다른 Envoy 파일을 임포트하여 해당 스토리나 작업을 자신의 파일에 추가할 수 있습니다. 임포트 후에는 자신의 Envoy 파일에서 정의한 것처럼 작업을 실행할 수 있습니다.

```blade theme={null}
@import('vendor/package/Envoy.blade.php')
```

### 여러 서버

Envoy에서는 하나의 작업을 여러 서버에서 간단히 실행할 수 있습니다. 먼저 `@servers` 선언에 추가 서버를 등록하고 각 서버에 고유 이름을 할당합니다. 서버를 추가한 후, 작업의 `on` 배열에 각 서버를 나열합니다.

```blade theme={null}
@servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])

@task('deploy', ['on' => ['web-1', 'web-2']])
    cd /home/user/example.com
    git pull origin {{ $branch }}
    php artisan migrate --force
@endtask
```

#### 병렬 실행

기본적으로 작업은 각 서버에서 순차적으로 실행됩니다. 즉 어떤 작업이 첫 번째 서버에서 완료되고 나서 두 번째 서버에서의 실행으로 진행됩니다. 여러 서버에서 작업을 병렬 실행하고 싶다면, 작업 선언에 `parallel` 옵션을 추가합니다.

```blade theme={null}
@servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])

@task('deploy', ['on' => ['web-1', 'web-2'], 'parallel' => true])
    cd /home/user/example.com
    git pull origin {{ $branch }}
    php artisan migrate --force
@endtask
```

### 셋업

Envoy 작업을 실행하기 전에 임의의 PHP 코드를 실행해야 할 경우 `@setup` 디렉티브를 사용합니다.

```php theme={null}
@setup
    $now = new DateTime;
@endsetup
```

작업 실행 전에 다른 PHP 파일을 로드해야 할 경우, `Envoy.blade.php` 파일 맨 앞에서 `@include` 디렉티브를 사용합니다.

```blade theme={null}
@include('vendor/autoload.php')

@task('restart-queues')
    # ...
@endtask
```

### 변수

Envoy 작업을 호출할 때 커맨드 라인에서 인수를 지정하여 작업에 전달할 수 있습니다.

```shell theme={null}
php vendor/bin/envoy run deploy --branch=master
```

작업 내에서는 Blade의 "echo" 문법으로 옵션에 접근할 수 있습니다. Blade의 `if` 문이나 반복문도 정의할 수 있습니다. 예를 들어 `git pull` 명령을 실행하기 전에 `$branch` 변수의 존재를 확인하는 경우 다음과 같이 합니다.

```blade theme={null}
@servers(['web' => ['user@192.168.1.1']])

@task('deploy', ['on' => 'web'])
    cd /home/user/example.com

    @if ($branch)
        git pull origin {{ $branch }}
    @endif

    php artisan migrate --force
@endtask
```

### 스토리

스토리는 일련의 작업을 하나의 편리한 이름으로 그룹화합니다. 예를 들어 `deploy` 스토리에서 `update-code` 작업과 `install-dependencies` 작업을 함께 실행할 수 있습니다.

```blade theme={null}
@servers(['web' => ['user@192.168.1.1']])

@story('deploy')
    update-code
    install-dependencies
@endstory

@task('update-code')
    cd /home/user/example.com
    git pull origin master
@endtask

@task('install-dependencies')
    cd /home/user/example.com
    composer install
@endtask
```

스토리를 작성했다면, 작업과 동일한 방법으로 호출할 수 있습니다.

```shell theme={null}
php vendor/bin/envoy run deploy
```

### 완료 훅

작업이나 스토리를 실행할 때 여러 훅이 실행됩니다. Envoy가 지원하는 훅의 종류는 `@before`, `@after`, `@error`, `@success`, `@finished`입니다. 이 훅 내의 코드는 모두 PHP로 해석되어, 작업이 조작하는 원격 서버가 아니라 **로컬에서** 실행됩니다.

각 훅은 얼마든지 정의할 수 있으며, Envoy 스크립트에 작성된 순서대로 실행됩니다.

```blade theme={null}
@before
    if ($task === 'deploy') {
        // ...
    }
@endbefore

@after
    if ($task === 'deploy') {
        // ...
    }
@endafter

@error
    if ($task === 'deploy') {
        // ...
    }
@enderror

@success
    // ...
@endsuccess

@finished
    if ($exitCode > 0) {
        // 어느 작업에서 오류가 발생함...
    }
@endfinished
```

`@finished` 훅은 실행이 완료된 작업의 상태 코드를 받습니다. 상태 코드는 `null` 또는 `0` 이상의 정수입니다.

## 작업 실행

애플리케이션의 `Envoy.blade.php` 파일에 정의한 작업이나 스토리를 실행하려면, Envoy의 `run` 명령을 실행하고 실행할 작업 또는 스토리의 이름을 전달합니다. Envoy는 작업을 실행하고 실행 중에 원격 서버로부터의 출력을 표시합니다.

```shell theme={null}
php vendor/bin/envoy run deploy
```

### 작업 실행 확인

서버에서 특정 작업을 실행하기 전에 확인을 요구하고 싶다면 작업 선언에 `confirm` 디렉티브를 추가합니다. 이 기능은 파괴적인 작업을 실행할 때 특히 편리합니다.

```blade theme={null}
@task('deploy', ['on' => 'web', 'confirm' => true])
    cd /home/user/example.com
    git pull origin {{ $branch }}
    php artisan migrate
@endtask
```

## 알림

### Slack

Envoy는 각 작업 실행 후 [Slack](https://slack.com)에 알림을 보낼 수 있습니다. `@slack` 디렉티브는 Slack의 Webhook URL과 채널명(또는 사용자명)을 받습니다. Webhook URL은 Slack 컨트롤 패널에서 "Incoming WebHooks" 인테그레이션을 만들면 얻을 수 있습니다.

`@slack` 디렉티브의 첫 번째 인수에는 Webhook URL 전체를 전달합니다. 두 번째 인수에는 채널명(`#channel`) 또는 사용자명(`@user`)을 지정합니다.

```blade theme={null}
@finished
    @slack('webhook-url', '#bots')
@endfinished
```

기본적으로는 실행된 작업을 설명하는 메시지가 알림 채널에 전송됩니다. `@slack` 디렉티브에 세 번째 인수를 전달하여 자체 메시지로 덮어쓸 수 있습니다.

```blade theme={null}
@finished
    @slack('webhook-url', '#bots', 'Hello, Slack.')
@endfinished
```

### Discord

Envoy는 각 작업 실행 후 [Discord](https://discord.com)에 알림을 보내는 것도 지원합니다. `@discord` 디렉티브는 Discord의 Webhook URL과 메시지를 받습니다. Webhook URL은 서버 설정 내에서 "Webhook"을 만들고 게시할 채널을 선택함으로써 얻을 수 있습니다.

```blade theme={null}
@finished
    @discord('discord-webhook-url')
@endfinished
```

### Telegram

Envoy는 각 작업 실행 후 [Telegram](https://telegram.org)에 알림을 보내는 것도 지원합니다. `@telegram` 디렉티브는 Telegram Bot ID와 Chat ID를 받습니다. Bot ID는 [BotFather](https://t.me/botfather)에서 새로운 봇을 만들면 얻을 수 있습니다. Chat ID는 [@username\_to\_id\_bot](https://t.me/username_to_id_bot)을 사용하여 얻을 수 있습니다.

```blade theme={null}
@finished
    @telegram('bot-id','chat-id')
@endfinished
```

### Microsoft Teams

Envoy는 각 작업 실행 후 [Microsoft Teams](https://www.microsoft.com/microsoft-teams)에 알림을 보내는 것도 지원합니다. `@teams` 디렉티브는 Teams의 webhook(필수), 메시지, 테마 색상(success, info, warning, error), 그리고 옵셔널 설정 배열을 받습니다. Teams의 webhook은 [Incoming Webhook](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook)을 만들어 얻을 수 있습니다. Teams API에는 그 외에도 많은 설정 항목이 있어 자체 메시지 카드를 자유롭게 만들 수 있습니다. 자세한 내용은 [Microsoft Teams 문서](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using)를 참조하세요.

```blade theme={null}
@finished
    @teams('webhook-url')
@endfinished
```

<Warning>
  Envoy는 원격 서버로의 [SSH](https://ko.wikipedia.org/wiki/시큐어_셸) 연결을 전제로 합니다. 실행 환경에 따라 키 인증 설정이나 서버에 대한 접근 제어를 사전에 마쳐 두어야 합니다. 보다 고도의 배포 자동화가 필요한 경우, [디플로이먼트](/ko/deployment) 가이드나 [GitHub Actions](/ko/advanced/github-actions-pinning)와의 조합도 검토하세요.
</Warning>
