Laravel Fortify
업데이트됨번역일: 2026년 6월 25일
이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.
- 원문 수정
- 2026년 6월 20일
- 번역 갱신
- 2026년 6월 25일
Laravel Fortify
소개
Laravel Fortify는 프론트엔드에 종속되지 않는 Laravel용 인증 백엔드 구현체입니다. Fortify는 로그인, 회원가입, 비밀번호 재설정, 이메일 인증 등 Laravel의 모든 인증 기능을 구현하는 데 필요한 라우트와 컨트롤러를 등록합니다. Fortify를 설치한 후 route:list Artisan 명령어를 실행하면 Fortify가 등록한 라우트 목록을 확인할 수 있습니다.
Fortify는 자체 UI를 제공하지 않으므로, 여러분이 직접 만든 UI에서 Fortify가 등록한 라우트로 요청을 보내는 방식으로 함께 사용합니다. 각 라우트에 어떻게 요청을 보내는지는 이 문서의 나머지 부분에서 자세히 설명합니다.
NOTE
Fortify는 Laravel 인증 기능 구현을 빠르게 시작하기 위한 패키지입니다. 반드시 사용해야 하는 것은 아닙니다. 인증, 비밀번호 재설정, 이메일 인증 문서를 참고하여 Laravel의 인증 서비스를 직접 구현할 수도 있습니다.
Fortify란?
앞서 언급했듯이, Laravel Fortify는 프론트엔드에 종속되지 않는 Laravel용 인증 백엔드 구현체입니다. 로그인, 회원가입, 비밀번호 재설정, 이메일 인증 등 Laravel의 모든 인증 기능에 필요한 라우트와 컨트롤러를 등록합니다.
Laravel의 인증 기능을 사용하기 위해 반드시 Fortify가 필요한 것은 아닙니다. 인증, 비밀번호 재설정, 이메일 인증 문서를 따라 직접 구현할 수도 있습니다.
Laravel을 처음 접한다면 애플리케이션 스타터 키트를 먼저 살펴보는 것을 권장합니다. 스타터 키트는 내부적으로 Fortify를 사용하며, Tailwind CSS로 만들어진 UI와 함께 인증 스캐폴딩을 제공합니다. 이를 통해 Laravel 인증 기능을 실제 코드와 함께 익힐 수 있습니다.
Laravel Fortify는 본질적으로 스타터 키트의 라우트와 컨트롤러를 UI 없이 패키지 형태로 분리해 놓은 것입니다. 특정 프론트엔드에 종속되지 않으면서도 인증 백엔드를 빠르게 구축할 수 있습니다.
Fortify를 사용해야 할 때
Laravel의 애플리케이션 스타터 키트를 사용한다면 Fortify를 별도로 설치할 필요가 없습니다. 스타터 키트는 이미 Fortify를 포함한 완전한 인증 구현을 제공합니다.
스타터 키트를 사용하지 않고 인증 기능이 필요하다면 두 가지 선택지가 있습니다.
- Laravel의 인증 서비스를 직접 구현
- Laravel Fortify로 인증 백엔드를 구성하고, 직접 만든 UI를 연결
Fortify를 설치했다면, 여러분의 UI는 이 문서에서 설명하는 Fortify의 인증 라우트로 요청을 보내 사용자를 인증하고 등록합니다.
Laravel Fortify와 Laravel Sanctum
Laravel Sanctum과 Fortify를 혼동하는 경우가 있는데, 두 패키지는 서로 다른 문제를 해결하며 경쟁 관계가 아닙니다.
- Sanctum: API 토큰 관리, 세션 쿠키 또는 토큰을 이용한 기존 사용자 인증만을 담당합니다. 회원가입, 비밀번호 재설정 등의 라우트는 제공하지 않습니다.
- Fortify: 회원가입, 비밀번호 재설정 등 인증 흐름 전반의 백엔드를 담당합니다.
API를 제공하거나 SPA(Single Page Application)의 백엔드를 구축한다면, Fortify(회원가입, 비밀번호 재설정 등)와 Sanctum(API 토큰 관리, 세션 인증)을 함께 사용하는 것이 일반적인 패턴입니다.
설치
Composer로 Fortify를 설치합니다.
composer require laravel/fortify다음으로 fortify:install Artisan 명령어로 Fortify의 리소스를 게시합니다.
php artisan fortify:install이 명령어는 Fortify의 액션 클래스들을 app/Actions 디렉터리에 게시하고, FortifyServiceProvider, 설정 파일, 데이터베이스 마이그레이션 파일도 함께 게시합니다.
이후 마이그레이션을 실행합니다.
php artisan migrateFortify 기능
fortify 설정 파일에는 features 배열이 있으며, 여기서 Fortify가 활성화할 백엔드 라우트와 기능을 지정합니다. 대부분의 Laravel 애플리케이션에서 필요한 기본 인증 기능만 활성화하는 것을 권장합니다.
'features' => [
Features::registration(),
Features::resetPasswords(),
Features::emailVerification(),
],뷰 비활성화
기본적으로 Fortify는 로그인 화면, 회원가입 화면 등 뷰를 반환하는 라우트를 정의합니다. 그러나 JavaScript 기반의 SPA를 개발한다면 이러한 라우트가 필요 없을 수 있습니다. config/fortify.php의 views 값을 false로 설정하면 해당 라우트를 비활성화할 수 있습니다.
'views' => false,뷰 비활성화와 비밀번호 재설정
뷰를 비활성화하면서 비밀번호 재설정 기능을 구현할 경우, "비밀번호 재설정" 화면을 표시하는 password.reset이라는 이름의 라우트는 반드시 직접 정의해야 합니다. Laravel의 Illuminate\Auth\Notifications\ResetPassword 알림이 password.reset 네임드 라우트를 통해 비밀번호 재설정 URL을 생성하기 때문입니다.
인증
인증을 시작하려면 Fortify에게 "로그인" 뷰를 어떻게 반환할지 알려주어야 합니다. Fortify는 UI가 없는 인증 라이브러리임을 기억하세요. 완성된 UI가 포함된 인증 구현이 필요하다면 애플리케이션 스타터 키트를 사용하세요.
뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스의 메서드를 통해 커스터마이징할 수 있습니다. 일반적으로 App\Providers\FortifyServiceProvider의 boot 메서드에서 호출합니다. Fortify는 이 뷰를 반환하는 /login 라우트를 자동으로 정의합니다.
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::loginView(function () {
return view('auth.login');
});
// ...
}로그인 템플릿에는 /login으로 POST 요청을 보내는 폼이 포함되어야 합니다. /login 엔드포인트는 문자열 email / username과 password를 필요로 합니다. 이메일/사용자명 필드의 이름은 config/fortify.php의 username 값과 일치해야 합니다. "로그인 상태 유지" 기능을 사용하려면 불리언 타입의 remember 필드를 함께 전송할 수 있습니다.
로그인에 성공하면 Fortify는 fortify 설정 파일의 home 옵션에 지정된 URI로 리디렉션합니다. XHR 요청인 경우 200 HTTP 응답이 반환됩니다.
로그인에 실패하면 사용자는 로그인 화면으로 돌아가고, 공유된 $errors Blade 템플릿 변수를 통해 유효성 검사 오류를 확인할 수 있습니다. XHR 요청인 경우 422 HTTP 응답과 함께 유효성 검사 오류가 반환됩니다.
사용자 인증 커스터마이징
Fortify는 기본적으로 제공된 인증 정보와 설정된 인증 가드를 바탕으로 사용자를 조회하고 인증합니다. 하지만 로그인 인증 방식을 완전히 직접 제어하고 싶다면 Fortify::authenticateUsing 메서드를 사용할 수 있습니다.
이 메서드는 클로저를 인수로 받으며, 클로저는 HTTP 요청을 받아 인증 정보를 검증한 후 해당 사용자 인스턴스를 반환합니다. 인증 정보가 유효하지 않거나 사용자를 찾을 수 없으면 null 또는 false를 반환해야 합니다. 이 설정은 FortifyServiceProvider의 boot 메서드에서 호출하세요.
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::authenticateUsing(function (Request $request) {
$user = User::where('email', $request->email)->first();
if ($user &&
Hash::check($request->password, $user->password)) {
return $user;
}
});
// ...
}인증 가드
fortify 설정 파일에서 Fortify가 사용할 인증 가드를 지정할 수 있습니다. 단, 설정된 가드는 반드시 Illuminate\Contracts\Auth\StatefulGuard를 구현해야 합니다. SPA에서 Fortify를 사용한다면 Laravel의 기본 web 가드와 Laravel Sanctum을 함께 사용하세요.
인증 파이프라인 커스터마이징
Laravel Fortify는 호출 가능한 클래스들로 구성된 파이프라인을 통해 로그인 요청을 처리합니다. 필요하다면 로그인 요청이 통과할 클래스들의 파이프라인을 직접 정의할 수 있습니다. 각 클래스는 __invoke 메서드를 가져야 하며, 미들웨어와 유사하게 Illuminate\Http\Request 인스턴스와 $next 변수를 받아 요청을 다음 클래스로 전달합니다.
Fortify::authenticateThrough 메서드로 커스텀 파이프라인을 정의하세요. 이 메서드는 클래스 배열을 반환하는 클로저를 인수로 받습니다. 일반적으로 App\Providers\FortifyServiceProvider의 boot 메서드에서 호출합니다.
아래는 수정 시 참고할 수 있는 기본 파이프라인 정의입니다.
use Laravel\Fortify\Actions\AttemptToAuthenticate;
use Laravel\Fortify\Actions\CanonicalizeUsername;
use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
use Laravel\Fortify\Features;
use Laravel\Fortify\Fortify;
use Illuminate\Http\Request;
Fortify::authenticateThrough(function (Request $request) {
return array_filter([
config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
config('fortify.lowercase_usernames') ? CanonicalizeUsername::class : null,
Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null,
AttemptToAuthenticate::class,
PrepareAuthenticatedSession::class,
]);
});인증 요청 제한
기본적으로 Fortify는 EnsureLoginIsNotThrottled 미들웨어를 통해 인증 시도를 제한합니다. 이 미들웨어는 사용자명과 IP 주소의 조합을 기준으로 요청을 제한합니다.
IP 주소만으로 제한하는 등 다른 방식이 필요하다면, fortify.limiters.login 설정 옵션을 통해 직접 정의한 속도 제한기를 지정할 수 있습니다. 이 옵션은 config/fortify.php 파일에 있습니다.
NOTE
요청 제한, 2단계 인증, 외부 WAF(Web Application Firewall)를 함께 사용하면 정상 사용자를 보호하는 가장 강력한 방어 체계를 구성할 수 있습니다.
리디렉션 커스터마이징
로그인에 성공하면 Fortify는 fortify 설정 파일의 home 옵션에 지정된 URI로 리디렉션합니다. XHR 요청인 경우 200 HTTP 응답이 반환됩니다. 사용자가 로그아웃하면 / URI로 리디렉션됩니다.
이 동작을 더 세밀하게 커스터마이징하려면 LoginResponse와 LogoutResponse 컨트랙트의 구현체를 Laravel 서비스 컨테이너에 바인딩하세요. 일반적으로 App\Providers\FortifyServiceProvider의 register 메서드에서 처리합니다.
use Laravel\Fortify\Contracts\LogoutResponse;
/**
* 애플리케이션 서비스를 등록합니다.
*/
public function register(): void
{
$this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
public function toResponse($request)
{
return redirect('/');
}
});
}2단계 인증
Fortify의 2단계 인증 기능을 활성화하면, 로그인 과정에서 6자리 숫자 토큰을 추가로 입력해야 합니다. 이 토큰은 Google Authenticator와 같은 TOTP 호환 모바일 인증 앱에서 생성되는 시간 기반 일회용 비밀번호(TOTP)입니다.
시작하기 전에 App\Models\User 모델에 Laravel\Fortify\TwoFactorAuthenticatable 트레잇이 추가되어 있는지 확인하세요.
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
class User extends Authenticatable
{
use Notifiable, TwoFactorAuthenticatable;
}다음으로 사용자가 2단계 인증을 설정하고 관리할 수 있는 화면을 구현해야 합니다. 이 화면에서 사용자는 2단계 인증을 활성화/비활성화하거나 복구 코드를 재생성할 수 있어야 합니다.
기본적으로
fortify설정 파일의features배열은 2단계 인증 설정을 변경하기 전에 비밀번호 확인을 요구합니다. 따라서 계속 진행하기 전에 Fortify의 비밀번호 확인 기능을 먼저 구현해야 합니다.
2단계 인증 활성화
2단계 인증을 활성화하려면 Fortify가 정의한 /user/two-factor-authentication 엔드포인트로 POST 요청을 보내야 합니다. 요청이 성공하면 사용자는 이전 URL로 리디렉션되고 세션에 status 변수가 two-factor-authentication-enabled로 설정됩니다. 이 세션 변수를 템플릿에서 감지하여 성공 메시지를 표시할 수 있습니다. XHR 요청인 경우 200 HTTP 응답이 반환됩니다.
2단계 인증 활성화를 선택한 후에도 사용자는 유효한 인증 코드를 입력해 설정을 "확인"해야 합니다. 따라서 성공 메시지에서 설정 확인이 아직 필요함을 사용자에게 안내해야 합니다.
@if (session('status') == 'two-factor-authentication-enabled')
<div class="mb-4 font-medium text-sm">
아래에서 2단계 인증 설정을 완료해 주세요.
</div>
@endif다음으로 사용자가 인증 앱에서 스캔할 수 있도록 QR 코드를 표시해야 합니다. Blade로 프론트엔드를 렌더링한다면 사용자 인스턴스의 twoFactorQrCodeSvg 메서드로 QR 코드 SVG를 가져올 수 있습니다.
$request->user()->twoFactorQrCodeSvg();JavaScript 기반 프론트엔드를 사용한다면 /user/two-factor-qr-code 엔드포인트로 XHR GET 요청을 보내세요. 이 엔드포인트는 svg 키를 포함한 JSON 객체를 반환합니다.
2단계 인증 확인
QR 코드를 표시하는 것과 함께, 사용자가 유효한 인증 코드를 입력하여 2단계 인증 설정을 "확인"할 수 있는 텍스트 입력 필드도 제공해야 합니다. 이 코드는 Fortify가 정의한 /user/confirmed-two-factor-authentication 엔드포인트로 POST 요청을 통해 전송해야 합니다.
요청이 성공하면 사용자는 이전 URL로 리디렉션되고 세션의 status 변수가 two-factor-authentication-confirmed로 설정됩니다.
@if (session('status') == 'two-factor-authentication-confirmed')
<div class="mb-4 font-medium text-sm">
2단계 인증이 성공적으로 확인 및 활성화되었습니다.
</div>
@endifXHR 요청을 통해 2단계 인증 확인 엔드포인트에 요청한 경우 200 HTTP 응답이 반환됩니다.
복구 코드 표시
사용자의 2단계 인증 복구 코드도 표시해야 합니다. 복구 코드는 모바일 기기에 접근할 수 없을 때 인증하는 데 사용됩니다. Blade를 사용한다면 인증된 사용자 인스턴스를 통해 복구 코드에 접근할 수 있습니다.
(array) $request->user()->recoveryCodes()JavaScript 기반 프론트엔드를 사용한다면 /user/two-factor-recovery-codes 엔드포인트로 XHR GET 요청을 보내세요. 이 엔드포인트는 복구 코드가 담긴 JSON 배열을 반환합니다.
복구 코드를 재생성하려면 /user/two-factor-recovery-codes 엔드포인트로 POST 요청을 보내세요.
2단계 인증으로 로그인
인증 과정에서 Fortify는 자동으로 사용자를 2단계 인증 챌린지 화면으로 리디렉션합니다. XHR 로그인 요청인 경우에는 인증 성공 후 반환되는 JSON 응답에 two_factor 불리언 속성이 포함됩니다. 이 값을 확인하여 2단계 인증 챌린지 화면으로 리디렉션할지 결정하세요.
2단계 인증 기능을 구현하려면 Fortify에게 챌린지 뷰를 어떻게 반환할지 알려주어야 합니다. App\Providers\FortifyServiceProvider의 boot 메서드에서 다음과 같이 설정합니다.
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::twoFactorChallengeView(function () {
return view('auth.two-factor-challenge');
});
// ...
}Fortify는 이 뷰를 반환하는 /two-factor-challenge 라우트를 자동으로 정의합니다. two-factor-challenge 템플릿에는 /two-factor-challenge 엔드포인트로 POST 요청을 보내는 폼이 포함되어야 합니다. 이 폼은 유효한 TOTP 토큰을 담는 code 필드 또는 복구 코드를 담는 recovery_code 필드를 포함해야 합니다.
로그인에 성공하면 Fortify는 fortify 설정 파일의 home 옵션에 지정된 URI로 리디렉션합니다. XHR 요청인 경우 204 HTTP 응답이 반환됩니다.
실패한 경우 사용자는 2단계 인증 챌린지 화면으로 돌아가고, 공유된 $errors Blade 템플릿 변수를