> ## 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 Prompts

> laravel/prompts 패키지를 사용해 Artisan 명령에 아름다운 대화형 UI를 추가하는 방법을 설명합니다. 텍스트 입력·선택·검색·autocomplete·태스크 로그·스트리밍 출력 등 다양한 함수를 소개합니다.

## 시작하기

[Laravel Prompts](https://github.com/laravel/prompts)는 커맨드라인 애플리케이션에 아름답고 사용하기 쉬운 대화형 폼을 추가하기 위한 PHP 패키지입니다.
플레이스홀더 텍스트나 검증 등 브라우저의 폼에 가까운 경험을 제공합니다.

Artisan 명령 코드 내에서 직접 호출할 수 있으므로, 사용자에 대한 문의를 단순하고 직관적으로 기술할 수 있습니다.

<Info>
  Laravel Prompts는 macOS, Linux, Windows(WSL)를 지원합니다.
  미대응 환경에서는 자동으로 폴백 동작으로 전환됩니다.
</Info>

## 설치

Laravel Prompts는 Laravel 본체에 포함되어 있으므로 추가 설치는 불필요합니다.

다른 PHP 프로젝트에서 사용하고 싶은 경우 Composer로 설치합니다.

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

## 기본적인 프롬프트 함수

### text — 텍스트 입력

`text()`로 사용자에게 문자열 입력을 요구합니다.

```php theme={null}
use function Laravel\Prompts\text;

$name = text('What is your name?');
```

플레이스홀더·기본값·힌트를 설정할 수 있습니다.

```php theme={null}
$name = text(
    label: 'What is your name?',
    placeholder: 'E.g. Taylor Otwell',
    default: $user?->name,
    hint: 'This will be displayed on your profile.'
);
```

`required`를 지정하면 입력을 필수로 만들 수 있습니다. 검증 메시지도 변경 가능합니다.

```php theme={null}
$name = text(
    label: 'What is your name?',
    required: 'Your name is required.'
);
```

`validate` 클로저로 추가 검증을 수행할 수 있습니다. 에러 메시지를 반환하거나, 합격 시에 `null`을 반환합니다.

```php theme={null}
$name = text(
    label: 'What is your name?',
    validate: fn (string $value) => match (true) {
        strlen($value) < 3 => 'The name must be at least 3 characters.',
        strlen($value) > 255 => 'The name must not exceed 255 characters.',
        default => null
    }
);
```

Laravel의 검증 규칙을 배열로 지정할 수도 있습니다.

```php theme={null}
$name = text(
    label: 'What is your name?',
    validate: ['name' => 'required|max:255|unique:users']
);
```

### textarea — 여러 줄 텍스트 입력

`textarea()`로 여러 줄 입력을 받습니다.

```php theme={null}
use function Laravel\Prompts\textarea;

$story = textarea('Tell me a story.');
```

### number — 숫자 입력

`number()`로 숫자를 받습니다. 위아래 화살표 키로 값을 증감시킬 수 있습니다.

```php theme={null}
use function Laravel\Prompts\number;

$copies = number(
    label: 'How many copies would you like?',
    default: 1,
    validate: ['copies' => 'required|integer|min:1|max:100']
);
```

### password — 비밀번호 입력

`password()`는 텍스트 입력과 마찬가지지만, 입력 내용이 화면에 표시되지 않습니다.

```php theme={null}
use function Laravel\Prompts\password;

$password = password('What is your password?');
```

```php theme={null}
$password = password(
    label: 'What is your password?',
    placeholder: 'password',
    hint: 'Minimum 8 characters.',
    validate: fn (string $value) => strlen($value) < 8
        ? 'The password must be at least 8 characters.'
        : null
);
```

### confirm — Yes/No 확인

`confirm()`으로 사용자에게 양자택일 확인을 요구합니다. `true` 또는 `false`를 반환합니다.

```php theme={null}
use function Laravel\Prompts\confirm;

$confirmed = confirm('Do you accept the terms?');
```

기본값이나 라벨 텍스트를 커스터마이즈할 수 있습니다.

```php theme={null}
$confirmed = confirm(
    label: 'Do you accept the terms?',
    default: false,
    yes: 'I accept',
    no: 'I decline',
    hint: 'The terms must be accepted to continue.'
);
```

### select — 선택 리스트

`select()`로 사용자에게 목록에서 하나를 고르게 합니다.

```php theme={null}
use function Laravel\Prompts\select;

$role = select(
    label: 'What role should the user have?',
    options: ['Member', 'Contributor', 'Owner'],
    default: 'Owner'
);
```

연관 배열을 사용하면 표시 라벨이 아닌 키를 반환값으로 만들 수 있습니다.

```php theme={null}
$role = select(
    label: 'What role should the user have?',
    options: [
        'member'      => 'Member',
        'contributor' => 'Contributor',
        'owner'       => 'Owner',
    ],
    default: 'owner'
);
```

`scroll`로 스크롤 전에 표시할 선택지 수를 변경할 수 있습니다(기본값 5개).

```php theme={null}
$role = select(
    label: 'Which category would you like to assign?',
    options: Category::pluck('name', 'id'),
    scroll: 10
);
```

### multiselect — 다중 선택

`multiselect()`로 여러 선택지를 동시에 고르게 합니다.

```php theme={null}
use function Laravel\Prompts\multiselect;

$permissions = multiselect(
    label: 'What permissions should be assigned?',
    options: ['Read', 'Create', 'Update', 'Delete']
);
```

`required`를 지정하면 최소 하나의 선택을 필수로 만들 수 있습니다.

```php theme={null}
$permissions = multiselect(
    label: 'What permissions should be assigned?',
    options: ['Read', 'Create', 'Update', 'Delete'],
    required: 'At least one permission must be selected.'
);
```

### suggest — 자동완성 지원 입력

`suggest()`는 후보를 제시하면서 자유 입력도 받습니다.

```php theme={null}
use function Laravel\Prompts\suggest;

$name = suggest(
    label: 'What is your name?',
    options: ['Taylor', 'Dayle']
);
```

클로저를 전달하면 입력 내용에 따라 동적으로 후보를 좁혀 갈 수 있습니다.

```php theme={null}
$name = suggest(
    label: 'What is your name?',
    options: fn (string $value) => collect(['Taylor', 'Tobi', 'Dries'])
        ->filter(fn ($name) => str_starts_with($name, $value))
        ->values()
        ->all()
);
```

### search — 동적 검색

`search()`는 입력할 때마다 후보 리스트를 갱신합니다. 클로저가 반환하는 배열이 후보가 됩니다.

```php theme={null}
use function Laravel\Prompts\search;

$userId = search(
    label: 'Search for the user that should receive the mail',
    options: fn (string $value) => strlen($value) > 0
        ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
        : []
);
```

### multisearch — 동적 다중 선택

`multisearch()`는 동적 검색으로 다중 선택이 가능합니다.

```php theme={null}
use function Laravel\Prompts\multisearch;

$userIds = multisearch(
    label: 'Search for the users that should receive the mail',
    options: fn (string $value) => strlen($value) > 0
        ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
        : []
);
```

### pause — 일시 정지

`pause()`로 사용자에게 Enter 키의 누름을 재촉해 처리를 일시 정지시킬 수 있습니다.

```php theme={null}
use function Laravel\Prompts\pause;

pause('Press ENTER to continue.');
```

### autocomplete — 인라인 보완

`autocomplete()`는 고스트 텍스트로 후보를 표시하는 인라인 보완 함수입니다. `suggest()`와 달리, 사용자가 입력할 때마다 일치하는 후보가 고스트 텍스트로 표시되고, `Tab` 키 또는 오른쪽 화살표 키로 보완을 확정할 수 있습니다.

```php theme={null}
use function Laravel\Prompts\autocomplete;

$name = autocomplete(
    label: 'What is your name?',
    options: ['Taylor', 'Dayle', 'Jess', 'Nuno', 'Tim']
);
```

플레이스홀더·기본값·힌트를 설정할 수 있습니다.

```php theme={null}
$name = autocomplete(
    label: 'What is your name?',
    options: ['Taylor', 'Dayle', 'Jess', 'Nuno', 'Tim'],
    placeholder: 'E.g. Taylor',
    default: $user?->name,
    hint: 'Use Tab to accept, up/down to cycle.'
);
```

클로저를 전달하면 입력 내용에 따라 동적으로 후보를 생성할 수 있습니다.

```php theme={null}
$file = autocomplete(
    label: 'Which file?',
    options: fn (string $value) => collect($files)
        ->filter(fn ($file) => str_starts_with(strtolower($file), strtolower($value)))
        ->values()
        ->all(),
);
```

## 검증

모든 프롬프트 함수는 `validate` 인수로 검증을 설정할 수 있습니다.

```php theme={null}
$name = text(
    label: 'What is your name?',
    validate: fn (string $value) => match (true) {
        strlen($value) < 3  => 'The name must be at least 3 characters.',
        strlen($value) > 255 => 'The name must not exceed 255 characters.',
        default => null
    }
);
```

클로저가 문자열을 반환하면 에러로 표시하고 재입력을 재촉합니다. `null`을 반환하면 검증 성공입니다.

Laravel의 검증 규칙을 배열 형식으로 사용할 수도 있습니다.

```php theme={null}
$name = text(
    label: 'What is your name?',
    validate: ['name' => 'required|max:255|unique:users']
);
```

입력을 검증 전에 변환하려면 `transform` 인수를 사용합니다.

```php theme={null}
$name = text(
    label: 'What is your name?',
    transform: fn (string $value) => trim($value),
    validate: fn (string $value) => match (true) {
        strlen($value) === 0 => 'The name must not be empty.',
        default => null
    }
);
```

## 폼

`form()`을 사용하면 여러 프롬프트를 하나로 묶어, 완료 전에 통째로 취소할 수 있습니다.

```php theme={null}
use function Laravel\Prompts\form;

$responses = form()
    ->text('What is your name?', required: true, name: 'name')
    ->password('What is your password?', validate: ['password' => 'min:8'], name: 'password')
    ->confirm('Do you accept the terms?')
    ->submit();

$name     = $responses['name'];
$password = $responses['password'];
$confirmed = $responses[2];
```

## 정보 출력

텍스트 메시지를 스타일 첨부로 출력하는 함수가 준비되어 있습니다.

```php theme={null}
use function Laravel\Prompts\info;
use function Laravel\Prompts\warning;
use function Laravel\Prompts\error;
use function Laravel\Prompts\alert;
use function Laravel\Prompts\note;

note('Prepare for launch.');
info('User created successfully.');
warning('This action cannot be undone.');
error('Something went wrong.');
alert('Critical failure detected!');
```

## 콜아웃

`callout()`은 라벨과 콘텐츠를 테두리로 감싸서 표시합니다. 배포 요약, 에러 상세, 상태 갱신 등, 중요한 정보를 두드러지게 하는 데 적합합니다.

```php theme={null}
use function Laravel\Prompts\callout;

callout(
    label: 'Environment Configured',
    content: 'Your application is running in production mode with 4 workers.',
);
```

`type` 인수에 `'warning'` 또는 `'error'`를 지정하면 비주얼 스타일을 변경할 수 있습니다.

```php theme={null}
callout(
    label: 'Deprecation Notice',
    content: 'The `--prefer-stable` flag will be removed in v4.0.',
    type: 'warning',
);

callout(
    label: 'Database Connection Failed',
    content: 'Could not connect to MySQL on 127.0.0.1:3306.',
    type: 'error',
);
```

`info` 인수로 푸터 행을 추가할 수 있습니다. ID나 타임스탬프 등의 메타데이터 표시에 편리합니다.

```php theme={null}
callout(
    label: 'Deployment Summary',
    content: 'Your application was deployed to production.',
    info: 'deploy-id: d4f8a2c',
);
```

### 리치 콘텐츠

문자열 대신 배열을 전달하면 구조화된 리치 콜아웃을 만들 수 있습니다. `Element` 클래스에는 헤딩·불릿 리스트·번호 리스트·키-값 리스트·링크를 만드는 팩토리 메서드가 있습니다.

```php theme={null}
use Laravel\Prompts\Elements\Element;
use function Laravel\Prompts\callout;

callout('Deployment Summary', [
    'Your application was deployed to production at 2024-03-15 14:32 UTC.',
    Element::heading('What Changed'),
    Element::bulletedList([
        'Migrated 3 pending database migrations',
        'Cleared and rebuilt route cache',
        'Restarted 4 queue workers',
    ]),
    Element::heading('Next Steps'),
    Element::numberedList([
        'Verify the health check endpoint at /up',
        'Monitor error rates for the next 15 minutes',
        'Confirm background jobs are processing',
    ]),
]);
```

`Element::keyValueList`로 라벨 첨부 데이터를 표시할 수 있습니다.

```php theme={null}
callout('Database Connection Failed', [
    'Could not connect to the database server.',
    Element::keyValueList([
        'Host'     => '127.0.0.1',
        'Port'     => '3306',
        'Database' => 'forge',
        'Status'   => 'Connection refused',
    ]),
], type: 'error');
```

`Element::link`는 [OSC 8](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda)에 대응한 터미널에서 클릭 가능한 하이퍼링크를 생성합니다. URL만, 또는 URL과 커스텀 라벨을 전달할 수 있습니다.

```php theme={null}
callout('Server Health Check', [
    'Multiple services are reporting degraded performance.',
    Element::heading('Affected Services'),
    'Look here: '.Element::link('https://example.com/health', 'Health Dashboard'),
    Element::link('https://example.com/health'),
]);
```

라벨을 생략한 경우 URL이 링크 텍스트로 표시됩니다.

## 테이블 표시

`table()`로 데이터를 테이블 형식으로 표시할 수 있습니다.

```php theme={null}
use function Laravel\Prompts\table;

table(
    headers: ['Name', 'Email'],
    rows: User::all(['name', 'email'])->toArray()
);
```

## 스핀(로딩 표시)

`spin()`은 클로저의 실행 중에 로딩 인디케이터를 표시합니다.

```php theme={null}
use function Laravel\Prompts\spin;

$response = spin(
    message: 'Fetching response...',
    callback: fn () => Http::get('http://example.com')
);
```

<Warning>
  `spin()`을 사용하려면 `pcntl` PHP 확장이 필요합니다. 사용할 수 없는 환경에서는 스피너가 표시되지 않습니다.
</Warning>

## 진행 바

`progress()`로 반복 처리의 진행을 시각적으로 표시할 수 있습니다.

```php theme={null}
use function Laravel\Prompts\progress;

$users = progress(
    label: 'Updating users',
    steps: User::all(),
    callback: fn ($user) => $this->performTask($user),
    hint: 'This may take some time.'
);
```

수동으로 진행 바를 제어할 수도 있습니다.

```php theme={null}
$progress = progress(label: 'Uploading files', steps: count($files));

$progress->start();

foreach ($files as $file) {
    $this->uploadFile($file);
    $progress->advance();
}

$progress->finish();
```

## 태스크

`task()`는 콜백 실행 중에 스피너와 스크롤 가능한 라이브 출력 영역을 표시합니다. 의존 관계 설치나 배포 스크립트 등 오랜 시간 실행되는 프로세스를 감싸는 데 최적이며, 무엇이 일어나고 있는지 실시간으로 확인할 수 있습니다.

```php theme={null}
use function Laravel\Prompts\task;

task(
    label: 'Installing dependencies',
    callback: function ($logger) {
        // 오랜 시간 실행되는 처리...
    }
);
```

콜백은 `Logger` 인스턴스를 받아서, 로그 행이나 상태 메시지를 실시간으로 표시할 수 있습니다.

<Warning>
  `task()`를 사용하려면 `pcntl` PHP 확장이 필요합니다. 사용할 수 없는 환경에서는 정적 표시로 폴백합니다.
</Warning>

### 로그 행 출력

`line` 메서드로 스크롤 출력 영역에 한 행씩 로그를 씁니다.

```php theme={null}
task(
    label: 'Installing dependencies',
    callback: function ($logger) {
        $logger->line('Resolving packages...');
        $logger->line('Downloading laravel/framework');
    }
);
```

### 상태 메시지

`success`·`warning`·`error`를 사용하면, 스크롤 로그 영역의 상부에 고정된 하이라이트 첨부 메시지를 표시할 수 있습니다.

```php theme={null}
task(
    label: 'Deploying application',
    callback: function ($logger) {
        $logger->line('Pulling latest changes...');
        $logger->success('Changes pulled!');

        $logger->line('Running migrations...');
        $logger->warning('No new migrations to run.');

        $logger->line('Clearing cache...');
        $logger->success('Cache cleared!');
    }
);
```

### 라벨 업데이트

`label` 메서드로 실행 중에 태스크의 라벨을 업데이트할 수 있습니다. `subLabel` 메서드는 라벨 아래에 옅게 표시되는 서브 라벨을 설정합니다. 빈 문자열을 전달하면 서브 라벨을 지울 수 있습니다. `subLabel` 인수로 초기 서브 라벨을 지정할 수도 있습니다.

```php theme={null}
task(
    label: 'Deploying',
    callback: function ($logger) {
        $logger->subLabel('Building assets...');
        // ...
        $logger->subLabel('Running migrations...');
        // ...
        $logger->subLabel('');
    },
    subLabel: 'Preparing...'
);
```

### 텍스트 스트리밍

AI가 생성하는 응답처럼 단계적으로 출력이 생성되는 처리에서는, `partial` 메서드로 텍스트를 하나씩 스트리밍할 수 있습니다. 스트림이 완료되면 `commitPartial`을 호출해 확정합니다.

```php theme={null}
task(
    label: 'Generating response...',
    callback: function ($logger) {
        foreach ($words as $word) {
            $logger->partial($word . ' ');
        }

        $logger->commitPartial();
    }
);
```

### 출력 상한과 서머리 유지

기본적으로 최대 10행의 스크롤 출력을 표시합니다. `limit` 인수로 커스터마이즈할 수 있습니다. 태스크 완료 후에도 상태 메시지를 화면에 남기고 싶은 경우에는 `keepSummary: true`를 전달합니다.

```php theme={null}
task(
    label: 'Deploying',
    callback: function ($logger) {
        $logger->success('Assets built');
        $logger->success('Migrations complete');
    },
    limit: 20,
    keepSummary: true,
);
```

## 스트림

`stream()`은 텍스트를 단계적으로 터미널에 표시합니다. AI가 생성하는 콘텐츠나 청크로 도착하는 데이터의 표시에 최적입니다.

```php theme={null}
use function Laravel\Prompts\stream;

$stream = stream();

foreach ($words as $word) {
    $stream->append($word . ' ');
    usleep(25_000); // 청크 간 지연을 시뮬레이트...
}

$stream->close();
```

`append` 메서드는 페이드 인 이펙트로 텍스트를 스트림에 추가합니다. 모든 콘텐츠를 스트리밍하고 나면 `close`를 호출해 출력을 확정하고 커서를 복원합니다.

## 터미널 조작

### 터미널 타이틀 설정

```php theme={null}
use function Laravel\Prompts\title;

title('My Application');
```

빈 문자열을 전달하면 기본 타이틀로 리셋할 수 있습니다.

```php theme={null}
title('');
```

### 터미널 클리어

```php theme={null}
use function Laravel\Prompts\clear;

clear();
```

## 터미널의 고려 사항

**터미널 폭**: 라벨·선택지·검증 메시지가 터미널의 열수를 넘는 경우 자동으로 잘립니다. 80열의 터미널을 상정하는 경우 최대 74문자를 기준으로 해 주세요.

**터미널의 높이**: `scroll` 인수를 받는 프롬프트에서는, 검증 메시지용 스페이스를 포함해 터미널의 높이에 들어가도록 자동으로 값이 조정됩니다.

## 폴백

미대응 환경(Windows non-WSL 등)에서는 자동으로 폴백합니다.
기본적으로 Laravel의 `$this->ask()`나 `$this->choice()` 등의 내장 메서드가 대신 사용됩니다.

## 테스트

Laravel Prompts는 Pest나 PHPUnit의 테스트와 연계할 수 있습니다.

```php theme={null}
use Laravel\Prompts\Prompt;

Prompt::fake(['Taylor', true]);

$name      = text('What is your name?');
$confirmed = confirm('Do you accept the terms?');

Prompt::assertOutputContains('What is your name?');
```

Laravel의 Artisan 테스트 헬퍼를 사용하면 정보 출력 함수에 대해서도 어서션을 기술할 수 있습니다.

```php theme={null}
// Pest
test('report generation', function () {
    $this->artisan('report:generate')
        ->expectsPromptsInfo('Welcome to the application!')
        ->expectsPromptsWarning('This action cannot be undone')
        ->expectsPromptsError('Something went wrong')
        ->expectsPromptsAlert('Important notice!')
        ->expectsPromptsTable(
            headers: ['Name', 'Email'],
            rows: [
                ['Taylor Otwell', 'taylor@example.com'],
            ]
        )
        ->assertExitCode(0);
});
```

```php theme={null}
// PHPUnit
public function test_report_generation(): void
{
    $this->artisan('report:generate')
        ->expectsPromptsInfo('Welcome to the application!')
        ->expectsPromptsWarning('This action cannot be undone')
        ->expectsPromptsTable(
            headers: ['Name', 'Email'],
            rows: [['Taylor Otwell', 'taylor@example.com']]
        )
        ->assertExitCode(0);
}
```

## 관련 페이지

<Columns cols={2}>
  <Card title="Artisan 콘솔" icon="terminal" href="/ko/artisan">
    Artisan 명령 내에서 Prompts를 활용
  </Card>
</Columns>


## Related topics

- [GitHub Copilot SDK for Laravel](/ko/packages/laravel-copilot-sdk/index.md)
- [스트리밍](/ko/packages/laravel-copilot-sdk/streaming.md)
- [콘솔 테스트](/ko/console-tests.md)
- [Laravel Chisel — 스타터 킷의 포스트 인스톨 스크립트 라이브러리](/ko/blog/chisel-introduction.md)
- [권한 요청](/ko/packages/laravel-copilot-sdk/permission-request.md)
