메인 콘텐츠로 건너뛰기

시작하기

Laravel Prompts는 커맨드라인 애플리케이션에 아름답고 사용하기 쉬운 대화형 폼을 추가하기 위한 PHP 패키지입니다. 플레이스홀더 텍스트나 검증 등 브라우저의 폼에 가까운 경험을 제공합니다. Artisan 명령 코드 내에서 직접 호출할 수 있으므로, 사용자에 대한 문의를 단순하고 직관적으로 기술할 수 있습니다.
Laravel Prompts는 macOS, Linux, Windows(WSL)를 지원합니다. 미대응 환경에서는 자동으로 폴백 동작으로 전환됩니다.

설치

Laravel Prompts는 Laravel 본체에 포함되어 있으므로 추가 설치는 불필요합니다. 다른 PHP 프로젝트에서 사용하고 싶은 경우 Composer로 설치합니다.
composer require laravel/prompts

기본적인 프롬프트 함수

text — 텍스트 입력

text()로 사용자에게 문자열 입력을 요구합니다.
use function Laravel\Prompts\text;

$name = text('What is your name?');
플레이스홀더·기본값·힌트를 설정할 수 있습니다.
$name = text(
    label: 'What is your name?',
    placeholder: 'E.g. Taylor Otwell',
    default: $user?->name,
    hint: 'This will be displayed on your profile.'
);
required를 지정하면 입력을 필수로 만들 수 있습니다. 검증 메시지도 변경 가능합니다.
$name = text(
    label: 'What is your name?',
    required: 'Your name is required.'
);
validate 클로저로 추가 검증을 수행할 수 있습니다. 에러 메시지를 반환하거나, 합격 시에 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의 검증 규칙을 배열로 지정할 수도 있습니다.
$name = text(
    label: 'What is your name?',
    validate: ['name' => 'required|max:255|unique:users']
);

textarea — 여러 줄 텍스트 입력

textarea()로 여러 줄 입력을 받습니다.
use function Laravel\Prompts\textarea;

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

number — 숫자 입력

number()로 숫자를 받습니다. 위아래 화살표 키로 값을 증감시킬 수 있습니다.
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()는 텍스트 입력과 마찬가지지만, 입력 내용이 화면에 표시되지 않습니다.
use function Laravel\Prompts\password;

$password = password('What is your password?');
$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를 반환합니다.
use function Laravel\Prompts\confirm;

$confirmed = confirm('Do you accept the terms?');
기본값이나 라벨 텍스트를 커스터마이즈할 수 있습니다.
$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()로 사용자에게 목록에서 하나를 고르게 합니다.
use function Laravel\Prompts\select;

$role = select(
    label: 'What role should the user have?',
    options: ['Member', 'Contributor', 'Owner'],
    default: 'Owner'
);
연관 배열을 사용하면 표시 라벨이 아닌 키를 반환값으로 만들 수 있습니다.
$role = select(
    label: 'What role should the user have?',
    options: [
        'member'      => 'Member',
        'contributor' => 'Contributor',
        'owner'       => 'Owner',
    ],
    default: 'owner'
);
scroll로 스크롤 전에 표시할 선택지 수를 변경할 수 있습니다(기본값 5개).
$role = select(
    label: 'Which category would you like to assign?',
    options: Category::pluck('name', 'id'),
    scroll: 10
);

multiselect — 다중 선택

multiselect()로 여러 선택지를 동시에 고르게 합니다.
use function Laravel\Prompts\multiselect;

$permissions = multiselect(
    label: 'What permissions should be assigned?',
    options: ['Read', 'Create', 'Update', 'Delete']
);
required를 지정하면 최소 하나의 선택을 필수로 만들 수 있습니다.
$permissions = multiselect(
    label: 'What permissions should be assigned?',
    options: ['Read', 'Create', 'Update', 'Delete'],
    required: 'At least one permission must be selected.'
);

suggest — 자동완성 지원 입력

suggest()는 후보를 제시하면서 자유 입력도 받습니다.
use function Laravel\Prompts\suggest;

$name = suggest(
    label: 'What is your name?',
    options: ['Taylor', 'Dayle']
);
클로저를 전달하면 입력 내용에 따라 동적으로 후보를 좁혀 갈 수 있습니다.
$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()는 입력할 때마다 후보 리스트를 갱신합니다. 클로저가 반환하는 배열이 후보가 됩니다.
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()는 동적 검색으로 다중 선택이 가능합니다.
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 키의 누름을 재촉해 처리를 일시 정지시킬 수 있습니다.
use function Laravel\Prompts\pause;

pause('Press ENTER to continue.');

autocomplete — 인라인 보완

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

$name = autocomplete(
    label: 'What is your name?',
    options: ['Taylor', 'Dayle', 'Jess', 'Nuno', 'Tim']
);
플레이스홀더·기본값·힌트를 설정할 수 있습니다.
$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.'
);
클로저를 전달하면 입력 내용에 따라 동적으로 후보를 생성할 수 있습니다.
$file = autocomplete(
    label: 'Which file?',
    options: fn (string $value) => collect($files)
        ->filter(fn ($file) => str_starts_with(strtolower($file), strtolower($value)))
        ->values()
        ->all(),
);

검증

모든 프롬프트 함수는 validate 인수로 검증을 설정할 수 있습니다.
$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의 검증 규칙을 배열 형식으로 사용할 수도 있습니다.
$name = text(
    label: 'What is your name?',
    validate: ['name' => 'required|max:255|unique:users']
);
입력을 검증 전에 변환하려면 transform 인수를 사용합니다.
$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()을 사용하면 여러 프롬프트를 하나로 묶어, 완료 전에 통째로 취소할 수 있습니다.
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];

정보 출력

텍스트 메시지를 스타일 첨부로 출력하는 함수가 준비되어 있습니다.
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()은 라벨과 콘텐츠를 테두리로 감싸서 표시합니다. 배포 요약, 에러 상세, 상태 갱신 등, 중요한 정보를 두드러지게 하는 데 적합합니다.
use function Laravel\Prompts\callout;

callout(
    label: 'Environment Configured',
    content: 'Your application is running in production mode with 4 workers.',
);
type 인수에 'warning' 또는 'error'를 지정하면 비주얼 스타일을 변경할 수 있습니다.
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나 타임스탬프 등의 메타데이터 표시에 편리합니다.
callout(
    label: 'Deployment Summary',
    content: 'Your application was deployed to production.',
    info: 'deploy-id: d4f8a2c',
);

리치 콘텐츠

문자열 대신 배열을 전달하면 구조화된 리치 콜아웃을 만들 수 있습니다. Element 클래스에는 헤딩·불릿 리스트·번호 리스트·키-값 리스트·링크를 만드는 팩토리 메서드가 있습니다.
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로 라벨 첨부 데이터를 표시할 수 있습니다.
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::linkOSC 8에 대응한 터미널에서 클릭 가능한 하이퍼링크를 생성합니다. URL만, 또는 URL과 커스텀 라벨을 전달할 수 있습니다.
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()로 데이터를 테이블 형식으로 표시할 수 있습니다.
use function Laravel\Prompts\table;

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

스핀(로딩 표시)

spin()은 클로저의 실행 중에 로딩 인디케이터를 표시합니다.
use function Laravel\Prompts\spin;

$response = spin(
    message: 'Fetching response...',
    callback: fn () => Http::get('http://example.com')
);
spin()을 사용하려면 pcntl PHP 확장이 필요합니다. 사용할 수 없는 환경에서는 스피너가 표시되지 않습니다.

진행 바

progress()로 반복 처리의 진행을 시각적으로 표시할 수 있습니다.
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.'
);
수동으로 진행 바를 제어할 수도 있습니다.
$progress = progress(label: 'Uploading files', steps: count($files));

$progress->start();

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

$progress->finish();

태스크

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

task(
    label: 'Installing dependencies',
    callback: function ($logger) {
        // 오랜 시간 실행되는 처리...
    }
);
콜백은 Logger 인스턴스를 받아서, 로그 행이나 상태 메시지를 실시간으로 표시할 수 있습니다.
task()를 사용하려면 pcntl PHP 확장이 필요합니다. 사용할 수 없는 환경에서는 정적 표시로 폴백합니다.

로그 행 출력

line 메서드로 스크롤 출력 영역에 한 행씩 로그를 씁니다.
task(
    label: 'Installing dependencies',
    callback: function ($logger) {
        $logger->line('Resolving packages...');
        $logger->line('Downloading laravel/framework');
    }
);

상태 메시지

success·warning·error를 사용하면, 스크롤 로그 영역의 상부에 고정된 하이라이트 첨부 메시지를 표시할 수 있습니다.
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 인수로 초기 서브 라벨을 지정할 수도 있습니다.
task(
    label: 'Deploying',
    callback: function ($logger) {
        $logger->subLabel('Building assets...');
        // ...
        $logger->subLabel('Running migrations...');
        // ...
        $logger->subLabel('');
    },
    subLabel: 'Preparing...'
);

텍스트 스트리밍

AI가 생성하는 응답처럼 단계적으로 출력이 생성되는 처리에서는, partial 메서드로 텍스트를 하나씩 스트리밍할 수 있습니다. 스트림이 완료되면 commitPartial을 호출해 확정합니다.
task(
    label: 'Generating response...',
    callback: function ($logger) {
        foreach ($words as $word) {
            $logger->partial($word . ' ');
        }

        $logger->commitPartial();
    }
);

출력 상한과 서머리 유지

기본적으로 최대 10행의 스크롤 출력을 표시합니다. limit 인수로 커스터마이즈할 수 있습니다. 태스크 완료 후에도 상태 메시지를 화면에 남기고 싶은 경우에는 keepSummary: true를 전달합니다.
task(
    label: 'Deploying',
    callback: function ($logger) {
        $logger->success('Assets built');
        $logger->success('Migrations complete');
    },
    limit: 20,
    keepSummary: true,
);

스트림

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

$stream = stream();

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

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

터미널 조작

터미널 타이틀 설정

use function Laravel\Prompts\title;

title('My Application');
빈 문자열을 전달하면 기본 타이틀로 리셋할 수 있습니다.
title('');

터미널 클리어

use function Laravel\Prompts\clear;

clear();

터미널의 고려 사항

터미널 폭: 라벨·선택지·검증 메시지가 터미널의 열수를 넘는 경우 자동으로 잘립니다. 80열의 터미널을 상정하는 경우 최대 74문자를 기준으로 해 주세요. 터미널의 높이: scroll 인수를 받는 프롬프트에서는, 검증 메시지용 스페이스를 포함해 터미널의 높이에 들어가도록 자동으로 값이 조정됩니다.

폴백

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

테스트

Laravel Prompts는 Pest나 PHPUnit의 테스트와 연계할 수 있습니다.
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 테스트 헬퍼를 사용하면 정보 출력 함수에 대해서도 어서션을 기술할 수 있습니다.
// 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', '[email protected]'],
            ]
        )
        ->assertExitCode(0);
});
// 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', '[email protected]']]
        )
        ->assertExitCode(0);
}

관련 페이지

Artisan 콘솔

Artisan 명령 내에서 Prompts를 활용
마지막 수정일 2026년 7월 13일