Artisan 콘솔

번역일: 2026년 6월 25일

Artisan 콘솔

소개

Artisan은 Laravel에 기본 포함된 CLI(명령줄 인터페이스)입니다. 애플리케이션 루트에 artisan 스크립트로 존재하며, 개발 과정에서 유용하게 쓸 수 있는 다양한 커맨드를 제공합니다. 사용 가능한 모든 Artisan 커맨드 목록은 list 커맨드로 확인할 수 있습니다.

php artisan list

각 커맨드에는 해당 커맨드의 인수와 옵션을 보여주는 도움말 화면이 있습니다. help 키워드를 커맨드 이름 앞에 붙이면 확인할 수 있습니다.

php artisan help migrate

Laravel Sail

로컬 개발 환경으로 Laravel Sail을 사용하고 있다면, Artisan 커맨드를 실행할 때 sail 명령을 사용해야 합니다. Sail은 Docker 컨테이너 내부에서 Artisan 커맨드를 실행합니다.

./vendor/bin/sail artisan list

Tinker (REPL)

Laravel Tinker는 PsySH 패키지를 기반으로 한 강력한 REPL 환경입니다. Tinker를 사용하면 터미널에서 직접 Eloquent 모델, Job, 이벤트 등 애플리케이션의 모든 요소를 대화형으로 조작할 수 있습니다.

설치

모든 Laravel 애플리케이션에는 기본적으로 Tinker가 포함되어 있습니다. 만약 이전에 제거했다면 Composer로 다시 설치할 수 있습니다.

composer require laravel/tinker

NOTE

Laravel 애플리케이션을 다루면서 핫 리로딩, 멀티라인 코드 편집, 자동완성 기능이 필요하다면 Tinkerwell을 살펴보세요!

사용법

tinker Artisan 커맨드를 실행하면 Tinker 환경으로 진입합니다.

php artisan tinker

vendor:publish 커맨드로 Tinker의 설정 파일을 애플리케이션에 배포할 수 있습니다.

php artisan vendor:publish --provider="Laravel\Tinker\TinkerServiceProvider"

WARNING

dispatch 헬퍼 함수와 Dispatchable 클래스의 dispatch 메서드는 가비지 컬렉션에 의존하여 Job을 큐에 등록합니다. 따라서 Tinker 환경에서 Job을 디스패치할 때는 Bus::dispatch 또는 Queue::push를 사용하세요.

커맨드 허용 목록

Tinker는 셸 내에서 실행을 허용할 Artisan 커맨드를 "허용 목록(allow list)"으로 관리합니다. 기본적으로 clear-compiled, down, env, inspire, migrate, optimize, up 커맨드를 실행할 수 있습니다. 추가로 허용하고 싶은 커맨드가 있다면 tinker.php 설정 파일의 commands 배열에 추가하세요.

'commands' => [
    // App\Console\Commands\ExampleCommand::class,
],

자동 별칭 제외 클래스

Tinker는 사용하는 클래스를 자동으로 별칭 처리합니다. 특정 클래스는 자동 별칭에서 제외하고 싶다면 tinker.php 설정 파일의 dont_alias 배열에 추가하세요.

'dont_alias' => [
    App\Models\User::class,
],

커맨드 작성하기

Artisan이 기본 제공하는 커맨드 외에도 직접 커맨드를 만들 수 있습니다. 커맨드 파일은 일반적으로 app/Console/Commands 디렉터리에 저장하지만, Composer가 로드할 수 있는 위치라면 어디든 자유롭게 선택해도 됩니다.

커맨드 생성

새 커맨드를 만들려면 make:command Artisan 커맨드를 사용하세요. app/Console/Commands 디렉터리가 없어도 처음 실행할 때 자동으로 생성됩니다.

php artisan make:command SendEmails

커맨드 구조

커맨드를 생성한 후에는 클래스의 signaturedescription 프로퍼티를 적절히 설정해야 합니다. 이 두 값은 php artisan list 화면에 표시되며, signature커맨드 입력 정의에도 사용됩니다. 커맨드가 실행되면 handle 메서드가 호출되므로, 실제 로직은 이 메서드 안에 작성합니다.

아래는 커맨드 예시입니다. handle 메서드에서 필요한 의존성을 타입힌트로 선언하면 Laravel 서비스 컨테이너가 자동으로 주입해 줍니다.

<?php namespace App\Console\Commands; use App\Models\User; use App\Support\DripEmailer; use Illuminate\Console\Command; class SendEmails extends Command { /** * 콘솔 커맨드의 이름 및 시그니처 * * @var string */ protected $signature = 'mail:send {user}'; /** * 콘솔 커맨드 설명 * * @var string */ protected $description = '특정 사용자에게 마케팅 이메일 발송'; /** * 콘솔 커맨드 실행 */ public function handle(DripEmailer $drip): void { $drip->send(User::find($this->argument('user'))); } }

NOTE

커맨드 클래스는 가볍게 유지하고 실제 무거운 작업은 서비스 클래스에 위임하는 것이 좋습니다. 위 예시에서도 이메일 발송의 실제 로직은 DripEmailer 서비스 클래스가 담당합니다.

클로저 커맨드

클로저 기반 커맨드는 커맨드를 별도의 클래스로 만들지 않고 클로저로 간결하게 정의하는 방식입니다. 라우트를 컨트롤러 대신 클로저로 정의하는 것과 비슷한 개념입니다.

app/Console/Kernel.phpcommands 메서드에서 routes/console.php 파일을 로드합니다.

/** * 애플리케이션의 클로저 기반 커맨드 등록 */ protected function commands(): void { require base_path('routes/console.php'); }

routes/console.php는 HTTP 라우트가 아닌 콘솔 진입점을 정의하는 파일입니다. Artisan::command 메서드를 사용하여 클로저 기반 커맨드를 정의할 수 있습니다. command 메서드는 커맨드 시그니처와 인수·옵션을 받는 클로저 두 가지를 인수로 받습니다.

Artisan::command('mail:send {user}', function (string $user) { $this->info("이메일 발송 대상: {$user}!"); });

클로저는 내부적으로 커맨드 인스턴스에 바인딩되므로, 커맨드 클래스에서 사용할 수 있는 모든 헬퍼 메서드를 그대로 사용할 수 있습니다.

의존성 타입힌트

클로저 커맨드에서도 인수·옵션 외에 서비스 컨테이너에서 해결할 의존성을 타입힌트로 선언할 수 있습니다.

use App\Models\User; use App\Support\DripEmailer; Artisan::command('mail:send {user}', function (DripEmailer $drip, string $user) { $drip->send(User::find($user)); });

클로저 커맨드 설명 추가

클로저 커맨드에 설명을 추가하려면 purpose 메서드를 체이닝하세요. 이 설명은 php artisan list 또는 php artisan help 실행 시 표시됩니다.

Artisan::command('mail:send {user}', function (string $user) { // ... })->purpose('특정 사용자에게 마케팅 이메일 발송');

격리 실행 가능한 커맨드

WARNING

이 기능을 사용하려면 애플리케이션의 기본 캐시 드라이버로 memcached, redis, dynamodb, database, file, array 중 하나를 사용해야 합니다. 또한 모든 서버가 동일한 중앙 캐시 서버와 통신해야 합니다.

동시에 하나의 인스턴스만 실행되도록 보장해야 하는 커맨드가 있다면, 커맨드 클래스에 Illuminate\Contracts\Console\Isolatable 인터페이스를 구현하세요.

<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Contracts\Console\Isolatable; class SendEmails extends Command implements Isolatable { // ... }

Isolatable로 표시된 커맨드는 자동으로 --isolated 옵션이 추가됩니다. 이 옵션을 붙여 실행하면, Laravel은 애플리케이션의 기본 캐시 드라이버를 이용해 원자적 락(atomic lock)을 획득하여 다른 인스턴스가 실행 중이지 않은지 확인합니다. 이미 실행 중인 인스턴스가 있으면 커맨드는 실행되지 않지만, 종료 코드는 성공(0)으로 반환됩니다.

php artisan mail:send 1 --isolated

실행되지 않을 때 반환할 종료 코드를 직접 지정하려면 --isolated 옵션에 값을 전달하세요.

php artisan mail:send 1 --isolated=12

락 ID

기본적으로 Laravel은 커맨드 이름을 기반으로 캐시 락 키를 생성합니다. 커맨드의 인수나 옵션을 락 키에 포함시키는 등 키를 커스터마이징하려면 isolatableId 메서드를 정의하세요.

/** * 커맨드의 격리 ID 반환 */ public function isolatableId(): string { return $this->argument('user'); }

락 만료 시간

기본적으로 격리 락은 커맨드가 완료되면 해제됩니다. 커맨드가 중단되어 완료되지 못한 경우에는 1시간 후 자동으로 만료됩니다. 만료 시간을 변경하려면 isolationLockExpiresAt 메서드를 정의하세요.

use DateTimeInterface; use DateInterval; /** * 커맨드 격리 락의 만료 시점 결정 */ public function isolationLockExpiresAt(): DateTimeInterface|DateInterval { return now()->addMinutes(5); }

입력 정의하기

콘솔 커맨드를 작성할 때는 인수(argument)나 옵션(option)을 통해 사용자 입력을 받는 경우가 많습니다. Laravel은 signature 프로퍼티를 사용해 커맨드 이름, 인수, 옵션을 라우트 정의와 유사한 표현식으로 한 번에 정의할 수 있습니다.

인수

인수와 옵션은 모두 중괄호 {}로 감쌉니다. 아래 예시는 user라는 필수 인수를 하나 정의합니다.

/**
 * 콘솔 커맨드의 이름 및 시그니처
 *
 * @var string
 */
protected $signature = 'mail:send {user}';

인수를 선택적으로 만들거나 기본값을 지정할 수도 있습니다.

// 선택적 인수
'mail:send {user?}'

// 기본값이 있는 선택적 인수
'mail:send {user=foo}'

옵션

옵션은 커맨드 실행 시 -- 접두사를 붙여 전달합니다. 옵션에는 두 가지 종류가 있습니다. 값을 받지 않는 옵션(불리언 스위치)과 값을 받는 옵션입니다.

/**
 * 콘솔 커맨드의 이름 및 시그니처
 *
 * @var string
 */
protected $signature = 'mail:send {user} {--queue}';

위 예시에서 --queue 스위치는 커맨드 실행 시 지정하면 true, 지정하지 않으면 false가 됩니다.

php artisan mail:send 1 --queue

값을 받는 옵션

옵션 이름 뒤에 =를 붙이면 해당 옵션이 값을 받도록 정의됩니다.

/**
 * 콘솔 커맨드의 이름 및 시그니처
 *
 * @var string
 */
protected $signature = 'mail:send {user} {--queue=}';

값을 지정하지 않으면 옵션 값은 null이 됩니다.

php artisan mail:send 1 --queue=default

기본값을 설정하려면 옵션 이름 뒤에 기본값을 명시합니다.

'mail:send {user} {--queue=default}'

옵션 단축키

옵션에 단축키를 지정하려면 |를 구분자로 단축키와 전체 옵션 이름을 함께 작성합니다.

'mail:send {user} {--Q|queue}'

터미널에서 단축키를 사용할 때는 단일 하이픈(-)을 접두사로 붙이며, 값 지정 시 =를 붙이지 않습니다.

php artisan mail:send 1 -Qdefault

배열 입력

여러 값을 받는 인수나 옵션을 정의할 때는 * 문자를 사용합니다.

'mail:send {user*}'

아래와 같이 실행하면 user 값이 [1, 2]인 배열이 됩니다.

php artisan mail:send 1 2

*를 선택적 인수와 조합하면 0개 이상의 값을 허용할 수 있습니다.

'mail:send {user?*}'

배열 옵션

여러 값을 받는 옵션은 각 값마다 옵션 이름을 반복하여 전달합니다.

'mail:send {--id=*}'
php artisan mail:send --id=1 --id=2

입력 설명

인수나 옵션에 콜론(:)으로 구분하여 설명을 추가할 수 있습니다. 시그니처가 길다면 여러 줄로 나눠 작성해도 됩니다.

/**
 * 콘솔 커맨드의 이름 및 시그니처
 *
 * @var string
 */
protected $signature = 'mail:send
                        {user : 이메일을 받을 사용자 ID}
                        {--queue : 작업을 큐로 처리할지 여부}';

누락된 입력 프롬프트

필수 인수가 누락된 경우 기본적으로 오류 메시지가 출력됩니다. PromptsForMissingInput 인터페이스를 구현하면, 누락된 인수를 사용자에게 자동으로 입력받도록 변경할 수 있습니다.

<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Contracts\Console\PromptsForMissingInput; class SendEmails extends Command implements PromptsForMissingInput { /** * 콘솔 커맨드의 이름 및 시그니처 * * @var string */ protected $signature = 'mail:send {user}'; // ... }

Laravel은 인수 이름이나 설명을 기반으로 질문을 자동 구성합니다. 질문을 직접 커스터마이징하려면 promptForMissingArgumentsUsing 메서드를 구현하여 인수 이름을 키로 하는 배열을 반환하세요.

/** * 누락된 인수를 묻기 위한 질문 반환 * * @return array */ protected function promptForMissingArgumentsUsing() { return [ 'user' => '이메일을 받을 사용자 ID를 입력하세요.', ]; }

질문과 플레이스홀더를 함께 지정하려면 튜플 형태로 반환하세요.

return [
    'user' => ['이메일을 받을 사용자 ID를 입력하세요.', '예: 123'],
];

프롬프트를 완전히 제어하고 싶다면 클로저를 반환할 수 있습니다.

use App\Models\User; use function Laravel\Prompts\search; // ... return [ 'user' => fn () => search( label: '사용자를 검색하세요:', placeholder: '예: 홍길동', options: fn ($value) => strlen($value) > 0 ? User::where('name', 'like', "%{$value}%")->pluck('name', 'id')->all() : [] ), ];

NOTE

사용 가능한 프롬프트 종류와 자세한 사용법은 Laravel Prompts 문서를 참고하세요.

옵션에 대한 프롬프트도 포함하고 싶다면, handle 메서드에 직접 추가할 수 있습니다. 단, 누락된 인수 프롬프트 이후에만 실행되도록 제한하고 싶다면 afterPromptingForMissingArguments 메서드를 구현하세요.

use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use function Laravel\Prompts\confirm; // ... /** * 누락된 인수 프롬프트 이후 실행할 작업 * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output) { $input->setOption('queue', confirm( label: '메일을 큐로 처리하시겠습니까?', default: $this->option('queue') )); }

커맨드 I/O

입력 가져오기

커맨드 실행 중에 인수나 옵션의 값을 가져오려면 argumentoption 메서드를 사용합니다. 존재하지 않는 인수나 옵션을 요청하면 null을 반환합니다.

/** * 콘솔 커맨드 실행 */ public function handle(): void { $userId = $this->argument('user'); }

모든 인수를 배열로 가져오려면 arguments 메서드를 사용합니다.

$arguments = $this->arguments();

옵션도 동일한 방식으로 가져올 수 있습니다.

// 특정 옵션 가져오기
$queueName = $this->option('queue');

// 모든 옵션을 배열로 가져오기
$options = $this->options();

입력 프롬프트

NOTE

Laravel Prompts는 플레이스홀더, 유효성 검사 등 브라우저와 유사한 UX를 제공하는 CLI 폼 패키지입니다.

커맨드 실행 중에 사용자에게 입력을 요청할 수 있습니다. ask 메서드는 질문을 출력하고 사용자의 입력을 반환합니다.

/** * 콘솔 커맨드 실행 */ public function handle(): void { $name = $this->ask('이름이 무엇인가요?'); // ... }

ask 메서드의 두 번째 인수로 기본값을 지정할 수 있습니다.

$name = $this->ask('이름이 무엇인가요?', '홍길동');

secret 메서드는 ask와 동일하지만 입력 내용이 화면에 표시되지 않습니다. 비밀번호 등 민감한 정보를 입력받을 때 사용합니다.

$password = $this->secret('비밀번호를 입력하세요.');

확인 요청

사용자에게 예/아니오 확인을 요청할 때는 confirm 메서드를 사용합니다. 기본적으로 false를 반환하며, 사용자가 y 또는 yes를 입력하면 true를 반환합니다.

if ($this->confirm('계속 진행하시겠습니까?')) {
    // ...
}

기본값을 true로 설정하려면 두 번째 인수로 true를 전달하세요.

if ($this->confirm('계속 진행하시겠습니까?', true)) {
    // ...
}

자동완성

anticipate 메서드는 자동완성 힌트를 제공합니다. 사용자가 힌트와 다른 값을 입력하는 것도 허용됩니다.

$name = $this->anticipate('이름이 무엇인가요?', ['길동', '철수']);

클로저를 전달하면 사용자가 타이핑할 때마다 동적으로 자동완성 목록을 생성할 수 있습니다.

$name = $this->anticipate('주소를 입력하세요.', function (string $input) { // 자동완성 옵션 반환 });

선택형 질문

미리 정의된 선택지를 제시하려면 choice 메서드를 사용합니다. 세 번째 인수로 기본 선택 항목의 배열 인덱스를 지정할 수 있습니다.

$name = $this->choice(
    '이름이 무엇인가요?',
    ['길동', '철수'],
    $defaultIndex
);

네 번째와 다섯 번째 인수로 최대 시도 횟수와 다중 선택 허용 여부를 설정할 수 있습니다.

$name = $this->choice(
    '이름이 무엇인가요?',
    ['길동', '철수'],
    $defaultIndex,
    $maxAttempts = null,
    $

이 문서는 Laravel 공식 문서(MIT)를 한국 개발자를 위해 번역·재구성한 것입니다.

번역일: 2026년 6월 25일