Laravel Fortify
번역일: 2026년 7월 2일
Laravel Fortify
소개
Laravel Fortify는 Laravel의 프론트엔드에 독립적인 인증 백엔드 구현체입니다. Fortify는 로그인, 회원가입, 비밀번호 재설정, 이메일 인증 등 Laravel의 인증 기능을 동작시키는 데 필요한 모든 라우트와 컨트롤러를 등록해 줍니다. Fortify를 설치한 후에는 route:list Artisan 명령어를 실행해서 등록된 라우트 목록을 확인할 수 있습니다.
Fortify는 자체적인 UI를 제공하지 않습니다. 여러분이 직접 제공하는 UI와 함께 동작하는 인증 백엔드 역할만 담당합니다. 각 요청에 대한 응답 방식은 다음 섹션에서 자세히 설명합니다.
Fortify란 무엇인가?
앞서 언급했듯이 Fortify는 프론트엔드에 독립적인 Laravel 인증 백엔드 구현체입니다. Laravel의 인증 기능을 동작시키는 데 필요한 라우트, 컨트롤러, 그리고 관련 로직을 모두 등록해 줍니다.
Fortify를 반드시 사용해야 할 필요는 없습니다. Laravel의 인증 기능을 직접 구현하는 것도 언제든 가능합니다. Laravel은 인증, 비밀번호 재설정, 이메일 인증 등의 문서를 통해 이러한 기능들을 직접 구현하는 방법을 안내하고 있습니다.
Laravel을 처음 접하는 분이라면, Fortify를 사용하기 전에 Laravel Breeze 스타터 킷을 먼저 살펴보는 것을 권장합니다. Breeze는 Tailwind CSS로 만들어진 UI를 포함한 완전한 인증 스캐폴딩을 제공합니다. Fortify와 달리, Breeze는 라우트와 컨트롤러 코드를 여러분의 프로젝트에 직접 퍼블리시해 줍니다. 덕분에 Laravel의 인증 기능을 직접 살펴보고 학습하는 데 도움이 됩니다.
Fortify는 기본적으로 Laravel Breeze의 라우트와 컨트롤러를 UI 없이 패키지 형태로 제공한다고 이해하면 됩니다. 특정 프론트엔드에 종속되지 않으면서도 인증 레이어의 백엔드 구현을 빠르게 갖추고 싶을 때 유용합니다.
Fortify를 언제 사용해야 할까?
Laravel Fortify를 사용하는 것이 적합한 상황이 궁금할 수 있습니다. 다음 두 가지 상황 중 하나에 해당한다면 Fortify 사용을 고려해 보세요.
첫 번째 상황: SPA(Single Page Application)를 개발하는 경우입니다. 예를 들어 Vue나 React로 프론트엔드를 구성하고, 별도의 Laravel API 서버로 인증을 처리하고 싶다면 Fortify가 적합합니다. Fortify는 인증에 필요한 백엔드 라우트와 로직을 모두 제공하며, Laravel Sanctum과 함께 사용하면 세션 기반 인증도 손쉽게 구성할 수 있습니다.
두 번째 상황: 자체 제작한 UI로 인증을 구현하고 싶은 경우입니다. 기본 스타터 킷(Breeze, Jetstream)의 UI 대신 직접 디자인한 화면을 사용해야 한다면, Fortify를 통해 인증 백엔드만 구성하고 UI는 원하는 대로 자유롭게 만들 수 있습니다.
반대로, 다음과 같은 상황이라면 Fortify 대신 다른 선택지를 고려해 보세요.
Laravel Breeze 사용 권장: 빠르게 인증 기능을 갖춘 애플리케이션을 시작하고 싶다면 Laravel Breeze를 사용하세요. Breeze는 Fortify와 달리 라우트, 컨트롤러, 뷰가 모두 프로젝트에 직접 포함되므로 커스터마이징이 훨씬 직관적입니다.
NOTE
Fortify는 인증 기능의 작동을 돕는 라우트와 컨트롤러를 등록합니다. 하지만 UI(뷰)는 제공하지 않습니다. 따라서 Fortify를 단독으로 사용할 때는 반드시 이에 맞는 UI를 직접 구현해야 합니다.
설치
Fortify를 설치하려면 Composer를 사용합니다:
composer require laravel/fortify이후 fortify:install Artisan 명령어를 실행합니다:
php artisan fortify:install이 명령어는 Fortify의 액션(Action) 클래스들을 app/Actions 디렉토리에 퍼블리시합니다. 해당 디렉토리가 없으면 자동으로 생성됩니다. 또한 FortifyServiceProvider, 설정 파일, 필요한 데이터베이스 마이그레이션 파일도 함께 퍼블리시됩니다.
이제 데이터베이스 마이그레이션을 실행합니다:
php artisan migrateFortify 기능
config/fortify.php 설정 파일에는 features 배열이 있습니다. 이 배열에서 Fortify가 제공할 백엔드 라우트와 기능을 지정합니다. Laravel Jetstream과 함께 사용하지 않는 경우에는 대부분의 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는 인증 시 두 가지 방식으로 동작합니다.
브라우저 요청의 경우: 로그인 성공 시 설정 파일의 home 설정값에 지정된 URL로 리다이렉트됩니다. 로그인 실패 시에는 사용자가 로그인 화면으로 다시 돌아갑니다. XHR 요청의 경우에는 성공 여부에 따라 적절한 JSON 응답이 반환됩니다.
XHR(비동기) 요청의 경우: 인증 결과가 JSON 형식으로 반환됩니다. HTTP 200 응답은 성공을 의미하며, 인증 실패 시에는 422 응답과 함께 유효성 검사 오류 메시지가 반환됩니다.
따라서 Fortify를 사용할 때 별도의 인증 라우트를 직접 구현할 필요가 없습니다. 대신 Fortify가 처리할 인증 관련 뷰만 제공하면 됩니다.
뷰 등록
Fortify는 모든 인증 관련 뷰를 어디서 가져올지 알아야 합니다. 보통 이 설정은 app/Providers/FortifyServiceProvider.php에 정의합니다. Fortify는 Laravel\Fortify\Fortify 클래스의 뷰 메서드들을 사용해 뷰를 등록합니다.
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::loginView(function () {
return view('auth.login');
});
// ...
}Fortify는 이 뷰를 반환하는 라우트를 자동으로 등록합니다. auth.login 뷰에는 /login으로 POST 요청을 보내는 폼이 있어야 합니다.
사용자 인증 커스터마이징
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는 로그인 요청을 처리할 때 일련의 클래스를 파이프라인으로 거쳐 인증을 수행합니다. 필요하다면 로그인 요청이 통과할 커스텀 파이프라인 클래스를 직접 정의할 수 있습니다. 각 클래스는 들어오는 Illuminate\Http\Request 인스턴스를 받는 __invoke 메서드를 구현해야 하며, 미들웨어처럼 $next 변수를 통해 다음 클래스로 요청을 전달합니다.
커스텀 파이프라인을 정의하려면 Fortify::authenticateThrough 메서드를 사용합니다. 이 메서드는 로그인 요청을 처리할 클래스 배열을 반환하는 클로저를 인자로 받습니다. 보통 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는 config/fortify.php 설정 파일의 home 값에 지정된 URI로 사용자를 리다이렉트합니다. 요청이 XHR 방식이라면 HTTP 200 응답이 반환됩니다.
로그아웃 후에는 / URI로 리다이렉트됩니다.
이 동작을 더 세밀하게 제어하고 싶다면, LoginResponse와 LogoutResponse 인터페이스의 구현체를 Laravel 서비스 컨테이너에 바인딩하면 됩니다. 보통 FortifyServiceProvider의 register 메서드에서 처리합니다:
use Laravel\Fortify\Contracts\LoginResponse;
/**
* 애플리케이션 서비스를 등록합니다.
*/
public function register(): void
{
$this->app->instance(LoginResponse::class, new class implements LoginResponse {
public function toResponse($request)
{
return redirect('/dashboard');
}
});
}이중 인증(2FA)
Fortify의 이중 인증 기능을 활성화하면, 사용자는 로그인 과정에서 6자리 숫자 토큰을 추가로 입력해야 합니다. 이 토큰은 TOTP(Time-based One-Time Password) 방식으로 생성되며, Google Authenticator와 같은 인증 앱을 통해 확인할 수 있습니다.
시작하기 전에, 애플리케이션의 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;
}다음으로, 사용자가 이중 인증 설정을 관리할 수 있는 화면을 애플리케이션에 추가해야 합니다. 이 화면에서는 이중 인증을 활성화 및 비활성화하고, QR 코드를 재생성할 수 있어야 합니다.
NOTE
기본적으로 config/fortify.php 설정 파일의 features 배열에는 이중 인증 설정 변경 전 비밀번호 확인을 요구하도록 되어 있습니다. 따라서 이 기능을 사용하려면 Fortify의 비밀번호 확인 기능이 먼저 구현되어 있어야 합니다.
이중 인증 활성화
이중 인증을 활성화하려면, 애플리케이션에서 Fortify가 정의한 /user/two-factor-authentication 엔드포인트로 POST 요청을 보내야 합니다.
요청이 성공하면 사용자는 이전 URL로 리다이렉트되며, 세션에 status 변수가 two-factor-authentication-enabled로 설정됩니다. 이 세션 변수를 활용해 뷰에서 성공 메시지를 표시할 수 있습니다. 요청이 XHR 방식이라면 HTTP 200 응답이 반환됩니다.
이중 인증을 활성화한 직후에는 아직 완전히 활성화된 상태가 아닙니다. 사용자가 이중 인증 설정을 완료하려면 유효한 이중 인증 코드를 입력해 "확인"해야 합니다. 확인 방법은 아래의 이중 인증 활성화 확인 섹션을 참조하세요.
QR 코드는 Fortify가 제공하는 내장 Blade 컴포넌트를 통해 표시할 수 있습니다. svg() 메서드를 사용하면 됩니다:
<div class="mt-4">
{!! $user->twoFactorQrCodeSvg() !!}
</div>또한 이중 인증 화면에는 복구 코드(Recovery Codes)도 함께 표시해야 합니다. 복구 코드는 인증 앱을 사용할 수 없는 긴급 상황에서 계정에 접근할 수 있도록 해 줍니다. 복구 코드는 아래와 같이 가져올 수 있습니다:
$recoveryCodes = json_decode(decrypt($request->user()->two_factor_recovery_codes), true);이중 인증 활성화 확인
이중 인증 설정을 완전히 활성화하려면, 사용자가 인증 앱에서 생성한 유효한 코드를 /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 text-green-600">
이중 인증이 성공적으로 설정되었습니다.
</div>
@endif요청이 XHR 방식이라면 HTTP 200 응답이 반환됩니다.
이중 인증으로 로그인하기
인증 과정에서 Fortify는 이중 인증이 활성화된 사용자를 자동으로 애플리케이션의 이중 인증 확인 화면으로 리다이렉트합니다. 요청이 XHR 방식이라면, 인증 성공 후 JSON 응답에 two_factor 불리언 속성이 포함됩니다.
이중 인증 확인 화면을 구현하려면, Fortify에 이중 인증 뷰를 어디서 가져올지 알려줘야 합니다. 인증 관련 뷰 등록 로직은 모두 Laravel\Fortify\Fortify 클래스에서 제공합니다. 보통 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는 config/fortify.php의 home 설정값에 지정된 URI로 사용자를 리다이렉트합니다. 요청이 XHR 방식이라면 HTTP 204 응답이 반환됩니다.
실패한 경우에는 이중 인증 화면으로 돌아가며, 유효성 검사 오류는 공유 $errors Blade 변수를 통해 확인할 수 있습니다. XHR 요청의 경우에는 422 HTTP 응답으로 오류가 반환됩니다.
이중 인증 비활성화
이중 인증을 비활성화하려면, /user/two-factor-authentication 엔드포인트로 DELETE 요청을 보내야 합니다.
Fortify의 이중 인증 관련 엔드포인트는 비밀번호 확인 후에야 호출 가능합니다.
회원가입
회원가입 기능을 구현하려면, Fortify에 회원가입 뷰 반환 방법을 알려줘야 합니다. Fortify는 UI가 없는 인증 라이브러리이므로, UI는 직접 구현해야 합니다.
Fortify의 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스의 적절한 메서드를 통해 커스터마이징할 수 있습니다. 보통 FortifyServiceProvider의 boot 메서드에서 호출합니다:
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::registerView(function () {
return view('auth.register');
});
// ...
}Fortify는 이 뷰를 반환하는 /register 라우트를 자동으로 등록합니다. auth.register 뷰에는 /register 엔드포인트로 POST 요청을 보내는 폼이 있어야 합니다.
/register 엔드포인트는 문자열 타입의 name, 이메일/사용자명 필드, password, password_confirmation 필드를 받습니다. 이메일이나 사용자명 필드의 이름은 config/fortify.php 파일의 username 설정값과 일치해야 합니다.
회원가입에 성공하면 Fortify는 config/fortify.php의 home 설정값에 지정된 URI로 사용자를 리다이렉트합니다. 요청이 XHR 방식이라면 HTTP 201 응답이 반환됩니다.
회원가입 커스터마이징
사용자 유효성 검사 및 생성 로직은 Fortify 설치 시 생성된 app/Actions/Fortify/CreateNewUser.php 액션을 수정해서 커스터마이징할 수 있습니다.
비밀번호 재설정
비밀번호 재설정 링크 요청
비밀번호 재설정 기능을 구현하려면, 먼저 Fortify에 "비밀번호 찾기" 뷰를 어디서 가져올지 알려줘야 합니다. Fortify는 UI를 포함하지 않으므로 뷰는 직접 구현해야 합니다. 보통 FortifyServiceProvider의 boot 메서드에서 등록합니다:
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::requestPasswordResetLinkView(function () {
return view('auth.forgot-password');
});
// ...
}Fortify는 이 뷰를 반환하는 /forgot-password 라우트를 자동으로 등록합니다. auth.forgot-password 뷰에는 /forgot-password 엔드포인트로 POST 요청을 보내는 폼이 있어야 합니다. 이 폼에는 email 필드가 포함되어야 합니다.
요청이 성공하면 Fortify는 /forgot-password 라우트로 다시 리다이렉트하며, 세션에 status 변수를 설정해 비밀번호 재설정 링크 발송 결과를 알려줍니다. 요청이 XHR 방식이라면 HTTP 200 응답이 반환됩니다.
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endif비밀번호 재설정
비밀번호 재설정을 완료하려면, Fortify에 비밀번호 재설정 뷰를 어디서 가져올지 알려줘야 합니다:
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::resetPasswordView(function ($request) {
return view('auth.reset-password', ['request' => $request]);
});
// ...
}Fortify는 이 뷰를 표시하는 라우트를 자동으로 등록합니다. auth.reset-password 뷰에는 /reset-password 엔드포인트로 POST 요청을 보내는 폼이 있어야 합니다. 이 폼에는 email, password, password_confirmation 필드와 숨겨진 token 필드(값은 request()->route('token'))가 포함되어야 합니다.
email 필드의 이름은 config/fortify.php 파일의 email 설정값과 일치해야 합니다.
비밀번호 재설정에 성공하면 Fortify는 /login 라우트로 리다이렉트하여 사용자가 새 비밀번호로 로그인할 수 있도록 합니다. 또한 세션에 status 변수가 설정되어 성공 메시지를 표시할 수 있습니다:
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endif요청이 XHR 방식이라면 HTTP 200 응답이 반환됩니다.
재설정에 실패한 경우 비밀번호 재설정 화면으로 돌아가며, 유효성 검사 오류는 공유 $errors Blade 변수를 통해 확인할 수 있습니다. XHR 요청의 경우에는 422 HTTP 응답으로 오류가 반환됩니다.
비밀번호 재설정 커스터마이징
비밀번호 재설정 로직은 Fortify 설치 시 생성된 app/Actions/ResetUserPassword.php 액션을 수정해서 커스터마이징할 수 있습니다.
이메일 인증
회원가입 후 이메일 인증을 요구하고 싶다면, Fortify에 이메일 인증 안내 뷰를 어디서 가져올지 알려줘야 합니다. 다시 말하지만, Fortify는 UI를 포함하지 않으므로 뷰는 직접 구현해야 합니다.
Fortify의 모든 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스의 적절한 메서드를 통해 커스터마이징할 수 있습니다. 보통 FortifyServiceProvider의 boot 메서드에서 등록합니다:
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::verifyEmailView(function () {
return view('auth.verify-email');
});
// ...
}Fortify는 사용자가 Laravel 내장 verified 미들웨어에 의해 /email/verify 엔드포인트로 리다이렉트될 때 이 뷰를 표시합니다.
auth.verify-email 뷰에는 이메일 인증 링크 발송을 안내하는 메시지가 포함되어야 합니다. 선택적으로, /email/verification-notification 엔드포인트로 POST 요청을 보내는 버튼을 추가해 인증 이메일을 재발송할 수 있습니다.
재발송 요청이 성공하면 Fortify는 /email/verify 라우트로 다시 리다이렉트하며, 세션에 status 변수를 설정해 사용자에게 결과를 알려줍니다. 요청이 XHR 방식이라면 HTTP 202 응답이 반환됩니다:
@if (session('status') == 'verification-link-sent')
<div class="mb-4 font-medium text-sm text-green-600">
새로운 이메일 인증 링크가 발송되었습니다!
</div>
@endif라우트 보호
특정 라우트나 라우트 그룹에 이메일 인증을 요구하려면 Laravel 내장 verified 미들웨어를 적용하면 됩니다. verified 미들웨어 별칭은 Laravel에 의해 자동으로 등록됩니다:
Route::get('/dashboard', function () {
// ...
})->middleware(['verified']);비밀번호 확인
애플리케이션을 개발하다 보면, 특정 작업을 수행하기 전에 사용자에게 비밀번호를 한 번 더 입력하도록 요구해야 할 때가 있습니다. 이런 라우트에는 보통 Laravel 내장 password.confirm 미들웨어를 적용합니다.
비밀번호 확인 기능을 구현하려면, Fortify에 비밀번호 확인 뷰를 어디서 가져올지 알려줘야 합니다. Fortify는 UI를 포함하지 않으므로 뷰는 직접 구현해야 합니다. 보통 FortifyServiceProvider의 boot 메서드에서 등록합니다:
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::confirmPasswordView(function () {
return view('auth.confirm-password');
});
// ...
}Fortify는 이 뷰를 반환하는 /user/confirm-password 라우트를 자동으로 등록합니다. auth.confirm-password 뷰에는 /user/confirm-password 엔드포인트로 POST 요청을 보내는 폼이 있어야 하며, 이 폼에는 password 필드가 포함되어야 합니다.
비밀번호가 일치하면 Fortify는 사용자가 접근하려던 원래 라우트로 리다이렉트합니다. 요청이 XHR 방식이라면 HTTP 201 응답이 반환됩니다.
비밀번호가 틀린 경우 비밀번호 확인 화면으로 돌아가며, 유효성 검사 오류는 공유 $errors Blade 변수를 통해 확인할 수 있습니다. XHR 요청의 경우에는 422 HTTP 응답으로 오류가 반환됩니다.
Laravel Fortify
소개
Laravel Fortify는 프론트엔드에 종속되지 않는 Laravel용 인증 백엔드 구현 패키지입니다. Fortify는 로그인, 회원가입, 비밀번호 재설정, 이메일 인증 등 Laravel의 모든 인증 기능을 구현하는 데 필요한 라우트와 컨트롤러를 자동으로 등록합니다. 설치 후 route:list Artisan 명령어를 실행하면 Fortify가 등록한 라우트 목록을 확인할 수 있습니다.
Fortify는 자체 UI를 제공하지 않으므로, 여러분이 직접 만든 UI에서 Fortify가 등록한 라우트로 요청을 보내는 방식으로 사용합니다. 각 라우트에 어떻게 요청을 보내는지는 이 문서의 뒷부분에서 자세히 설명합니다.
NOTE
Fortify는 Laravel 인증 기능 구현의 출발점을 빠르게 잡아주는 패키지입니다. 반드시 사용해야 하는 것은 아닙니다. 인증, 비밀번호 재설정, 이메일 인증 문서를 참고해 Laravel의 인증 서비스를 직접 다루는 것도 언제든 가능합니다.
Fortify란 무엇인가?
앞서 설명했듯이, Laravel Fortify는 프론트엔드에 종속되지 않는 Laravel용 인증 백엔드 구현 패키지입니다. 로그인, 회원가입, 비밀번호 재설정, 이메일 인증 등에 필요한 라우트와 컨트롤러를 모두 등록해 줍니다.
Laravel의 인증 기능을 사용하기 위해 반드시 Fortify가 필요한 것은 아닙니다. 인증, 비밀번호 재설정, 이메일 인증 문서를 따라 직접 구현하는 방법도 있습니다.
Laravel을 처음 접한다면 애플리케이션 스타터 킷을 먼저 살펴보는 것을 권장합니다. 스타터 킷은 내부적으로 Fortify를 사용하며, Tailwind CSS로 만들어진 UI와 함께 인증 스캐폴딩을 제공합니다. Fortify를 직접 다루기 전에 스타터 킷으로 Laravel 인증의 전체 흐름을 먼저 익혀보는 것이 좋습니다.
Fortify는 스타터 킷의 라우트와 컨트롤러를 UI 없이 패키지 형태로 분리한 것이라고 이해하면 됩니다. 특정 프론트엔드 기술에 얽매이지 않으면서도 인증 백엔드를 빠르게 구성할 수 있습니다.
Fortify를 언제 사용해야 할까?
Fortify 사용 시점이 헷갈릴 수 있습니다. 간단히 정리하면 다음과 같습니다.
-
스타터 킷(Breeze, Jetstream 등)을 사용 중이라면 Fortify를 별도로 설치할 필요가 없습니다. 스타터 킷이 이미 Fortify를 포함해 인증 기능을 완전히 구현하고 있습니다.
-
스타터 킷을 사용하지 않고 인증 기능이 필요하다면 두 가지 선택지가 있습니다.
- 인증 기능을 직접 구현한다.
- Fortify로 인증 백엔드를 구성하고, 여기에 맞는 UI를 직접 만든다.
Fortify를 선택한 경우, 직접 만든 UI에서 이 문서에 설명된 Fortify의 인증 라우트로 요청을 보내 로그인, 회원가입 등의 기능을 처리하면 됩니다.
직접 구현을 선택한 경우에는 인증, 비밀번호 재설정, 이메일 인증 문서를 참고하세요.
Laravel Fortify와 Laravel Sanctum의 차이
Laravel Sanctum과 Fortify를 혼동하는 경우가 많습니다. 두 패키지는 서로 다른 문제를 해결하며, 상호 배타적이거나 경쟁 관계에 있지 않습니다.
- Laravel Sanctum: API 토큰 관리와 세션 쿠키 또는 토큰을 이용한 기존 사용자 인증을 담당합니다. 회원가입, 비밀번호 재설정 같은 라우트는 제공하지 않습니다.
- Laravel Fortify: 회원가입, 비밀번호 재설정, 이메일 인증 등 사용자 인증 플로우의 백엔드 구현을 담당합니다.
따라서 API를 제공하거나 SPA(Single Page Application)의 백엔드를 구축하는 경우, Fortify(회원가입, 비밀번호 재설정 등)와 Sanctum(API 토큰 관리, 세션 인증)을 함께 사용하는 것이 자연스러운 조합입니다.
Laravel Fortify
설치
Composer를 사용해 Fortify를 설치합니다:
composer require laravel/fortify설치 후, fortify:install Artisan 명령어로 Fortify 리소스를 프로젝트에 게시합니다:
php artisan fortify:install이 명령어를 실행하면 다음 작업이 자동으로 이루어집니다:
app/Actions디렉터리가 없으면 생성하고, Fortify의 액션 클래스들을 해당 디렉터리에 게시합니다.FortifyServiceProvider, 설정 파일(config/fortify.php), 그리고 필요한 데이터베이스 마이그레이션 파일이 게시됩니다.
이후 마이그레이션을 실행해 데이터베이스 테이블을 생성합니다:
php artisan migrateFortify 기능 설정
게시된 config/fortify.php 설정 파일에는 features 배열이 있습니다. 이 배열에서 Fortify가 활성화할 백엔드 라우트와 기능을 지정합니다. 대부분의 Laravel 애플리케이션에서 필요로 하는 기본 인증 기능만 활성화하는 것을 권장합니다:
'features' => [
Features::registration(), // 회원가입
Features::resetPasswords(), // 비밀번호 재설정
Features::emailVerification(), // 이메일 인증
],NOTE
필요하지 않은 기능은 이 배열에서 제거하세요. 활성화된 기능만큼 라우트와 처리 로직이 등록되므로, 실제 사용하는 기능만 남겨두면 불필요한 엔드포인트 노출을 줄일 수 있습니다.
뷰 비활성화
Fortify는 기본적으로 로그인 화면, 회원가입 화면 등 뷰를 반환하는 라우트를 등록합니다. 그러나 React, Vue 등의 SPA(싱글 페이지 애플리케이션)를 구축하는 경우, 이러한 서버 사이드 뷰 라우트는 필요하지 않을 수 있습니다. config/fortify.php에서 views 값을 false로 설정하면 해당 라우트를 비활성화할 수 있습니다:
'views' => false,뷰 비활성화 시 비밀번호 재설정 처리 주의사항
뷰를 비활성화하더라도 비밀번호 재설정 기능을 사용하는 경우, password.reset이라는 이름의 라우트는 반드시 직접 정의해야 합니다. Laravel의 Illuminate\Auth\Notifications\ResetPassword 알림이 password.reset 네임드 라우트를 기반으로 비밀번호 재설정 URL을 생성하기 때문입니다. 이 라우트가 없으면 재설정 링크가 정상적으로 생성되지 않습니다.
Laravel Fortify
인증 (Authentication)
Fortify를 사용하려면 먼저 "로그인" 뷰를 어떻게 반환할지 알려줘야 합니다. Fortify는 헤드리스(headless) 인증 라이브러리이므로, 프론트엔드 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 요청을 보내는 폼이 포함되어야 합니다. 이 엔드포인트는 문자열 email / username과 password를 요구합니다. 이메일 / 사용자명 필드의 이름은 config/fortify.php의 username 값과 일치해야 합니다. 또한 불리언 타입의 remember 필드를 함께 전송하면 Laravel의 "로그인 상태 유지(remember me)" 기능을 활성화할 수 있습니다.
로그인에 성공하면 Fortify는 fortify 설정 파일의 home 옵션에 지정된 URI로 리디렉션합니다. XHR 요청인 경우에는 HTTP 200 응답이 반환됩니다.
로그인에 실패하면 사용자는 로그인 화면으로 다시 리디렉션되고, 유효성 검사 오류는 Blade의 공유 변수 $errors를 통해 접근할 수 있습니다. 자세한 내용은 유효성 검사 오류 표시 문서를 참고하세요. XHR 요청인 경우에는 HTTP 422 응답과 함께 유효성 검사 오류가 반환됩니다.
사용자 인증 커스터마이징
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는 로그인 요청을 처리할 때 여러 개의 인보커블(invokable) 클래스로 구성된 파이프라인을 통해 인증을 수행합니다. 필요하다면 이 파이프라인을 직접 정의할 수도 있습니다. 파이프라인의 각 클래스는 __invoke 메서드를 가져야 하며, 이 메서드는 Illuminate\Http\Request 인스턴스와 미들웨어처럼 다음 클래스로 요청을 전달하는 $next 변수를 받습니다.
커스텀 파이프라인을 정의하려면 Fortify::authenticateThrough 메서드를 사용합니다. 이 메서드는 클로저를 받으며, 클로저는 로그인 요청이 통과할 클래스 배열을 반환해야 합니다. 마찬가지로 App\Providers\FortifyServiceProvider의 boot 메서드에서 호출합니다.
아래 예시는 Fortify의 기본 파이프라인 정의이며, 커스터마이징의 시작점으로 활용할 수 있습니다:
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,
]);
});인증 시도 제한 (Throttling)
Fortify는 기본적으로 EnsureLoginIsNotThrottled 미들웨어를 사용해 인증 시도를 제한합니다. 이 미들웨어는 사용자명과 IP 주소의 조합을 기준으로 시도 횟수를 제한합니다.
애플리케이션에 따라 IP 주소만을 기준으로 제한하는 등 다른 방식이 필요할 수 있습니다. 이 경우 config/fortify.php의 fortify.limiters.login 옵션에 직접 정의한 속도 제한기(rate limiter)를 지정할 수 있습니다.
NOTE
시도 횟수 제한(throttling), 2단계 인증, 외부 웹 방화벽(WAF)을 함께 사용하면 정상적인 사용자를 보호하는 가장 견고한 방어 체계를 구성할 수 있습니다.
리디렉션 커스터마이징
로그인 성공 시 Fortify는 fortify 설정 파일의 home 옵션에 지정된 URI로 리디렉션합니다. XHR 요청인 경우에는 HTTP 200 응답이 반환됩니다. 로그아웃 후에는 / URI로 리디렉션됩니다.
이 동작을 더 세밀하게 제어하려면, LoginResponse와 LogoutResponse 컨트랙트(contract)의 구현체를 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('/');
}
});
}이중 인증 (Two-Factor Authentication)
Fortify의 이중 인증 기능을 활성화하면, 사용자는 로그인 과정에서 6자리 숫자 코드를 추가로 입력해야 합니다. 이 코드는 TOTP(Time-based One-Time Password) 방식으로 생성되며, Google Authenticator 등 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;
}다음으로, 사용자가 이중 인증 설정을 관리할 수 있는 화면을 구성해야 합니다. 이 화면에서는 이중 인증 활성화/비활성화, 복구 코드 재생성 등의 기능을 제공해야 합니다.
NOTE
fortify 설정 파일의 features 배열에는 기본적으로 이중 인증 설정 변경 전에 비밀번호 확인을 요구하는 옵션이 포함되어 있습니다. 따라서 이중 인증 기능을 구현하기 전에 Fortify의 비밀번호 확인 기능을 먼저 구현해야 합니다.
이중 인증 활성화
이중 인증을 활성화하려면, 애플리케이션에서 /user/two-factor-authentication 엔드포인트로 POST 요청을 전송해야 합니다. 요청이 성공하면 사용자는 이전 URL로 리디렉션되고, 세션의 status 변수가 two-factor-authentication-enabled로 설정됩니다. 템플릿에서 이 값을 확인하여 적절한 성공 메시지를 표시할 수 있습니다. XHR 요청인 경우에는 200 HTTP 응답이 반환됩니다.
이중 인증 활성화를 선택한 후에도 사용자는 유효한 인증 코드를 입력하여 설정을 확인(confirm) 해야 합니다. 따라서 성공 메시지에는 추가 확인 단계가 필요함을 안내해야 합니다:
@if (session('status') == 'two-factor-authentication-enabled')
<div class="mb-4 font-medium text-sm">
아래에서 이중 인증 설정을 완료해 주세요.
</div>
@endif이어서 사용자가 인증 앱으로 스캔할 수 있는 QR 코드를 표시해야 합니다. Blade를 사용하는 경우, 사용자 인스턴스의 twoFactorQrCodeSvg 메서드로 QR 코드 SVG를 가져올 수 있습니다:
$request->user()->twoFactorQrCodeSvg();JavaScript 기반 프런트엔드를 구축하는 경우, /user/two-factor-qr-code 엔드포인트로 XHR GET 요청을 보내면 됩니다. 이 엔드포인트는 svg 키를 포함한 JSON 객체를 반환합니다.
이중 인증 확인
QR 코드를 표시하는 것과 함께, 사용자가 인증 앱에서 생성된 코드를 직접 입력하여 설정을 확인할 수 있는 텍스트 입력 필드도 제공해야 합니다. 입력된 코드는 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">
이중 인증이 성공적으로 확인되고 활성화되었습니다.
</div>
@endifXHR 요청인 경우에는 200 HTTP 응답이 반환됩니다.
복구 코드 표시
사용자가 모바일 기기를 분실했을 때를 대비해, 이중 인증 복구 코드도 반드시 표시해야 합니다. Blade를 사용하는 경우, 인증된 사용자 인스턴스를 통해 복구 코드에 접근할 수 있습니다:
(array) $request->user()->recoveryCodes()JavaScript 기반 프런트엔드를 구축하는 경우, /user/two-factor-recovery-codes 엔드포인트로 XHR GET 요청을 보내면 됩니다. 이 엔드포인트는 복구 코드 목록을 JSON 배열로 반환합니다.
복구 코드를 재생성하려면 동일한 /user/two-factor-recovery-codes 엔드포인트로 POST 요청을 전송합니다.
이중 인증으로 로그인
로그인 과정에서 이중 인증이 필요한 경우, Fortify는 자동으로 이중 인증 확인 화면으로 리디렉션합니다. XHR 로그인 요청을 사용하는 경우에는 인증 성공 후 반환되는 JSON 응답에 two_factor 불리언 속성이 포함됩니다. 이 값을 확인하여 이중 인증 화면으로 리디렉션할지 판단해야 합니다.
이중 인증 확인 뷰를 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 응답이 반환됩니다.
요청이 실패하면 사용자는 이중 인증 확인 화면으로 되돌아가며, 공유 $errors Blade 템플릿 변수를 통해 유효성 검사 오류를 확인할 수 있습니다. XHR 요청의 경우에는 422 HTTP 응답과 함께 유효성 검사 오류가 반환됩니다.
이중 인증 비활성화
이중 인증을 비활성화하려면, /user/two-factor-authentication 엔드포인트로 DELETE 요청을 전송합니다. Fortify의 이중 인증 관련 엔드포인트는 호출 전에 비밀번호 확인을 요구한다는 점을 기억하세요.
Laravel Fortify
회원가입
애플리케이션의 회원가입 기능을 구현하려면, 먼저 Fortify에게 "register" 뷰를 어떻게 반환할지 알려줘야 합니다. Fortify는 UI가 없는 헤드리스(headless) 인증 라이브러리입니다. 프론트엔드 인증 화면까지 완성된 형태로 제공받고 싶다면, 애플리케이션 스타터 킷을 사용하는 것이 더 적합합니다.
Fortify의 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 메서드로 자유롭게 커스터마이징할 수 있습니다. 보통 아래와 같이 App\Providers\FortifyServiceProvider 클래스의 boot 메서드 안에서 호출합니다.
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::registerView(function () {
return view('auth.register');
});
// ...
}Fortify는 이 뷰를 반환하는 /register 라우트를 자동으로 정의합니다. register 템플릿에는 Fortify가 제공하는 /register 엔드포인트로 POST 요청을 보내는 폼이 포함되어야 합니다.
/register 엔드포인트는 다음 필드를 받습니다.
| 필드 | 설명 |
|---|---|
name | 문자열, 사용자 이름 |
| 이메일 또는 사용자명 | fortify 설정 파일의 username 값과 일치해야 함 |
password | 비밀번호 |
password_confirmation | 비밀번호 확인 |
NOTE
이메일/사용자명 필드의 이름은 config/fortify.php의 username 설정값과 반드시 일치해야 합니다. 기본값은 email이지만, 프로젝트 요구사항에 따라 변경할 수 있습니다.
회원가입에 성공하면, Fortify는 fortify 설정 파일의 home 옵션에 지정된 URI로 사용자를 리다이렉트합니다. XHR 요청인 경우에는 201 HTTP 응답이 반환됩니다.
회원가입에 실패하면, 사용자는 회원가입 화면으로 다시 리다이렉트되며 유효성 검사 오류는 Blade의 공유 변수 $errors를 통해 확인할 수 있습니다. 자세한 내용은 유효성 검사 오류 표시 문서를 참고하세요. XHR 요청인 경우에는 422 HTTP 응답과 함께 유효성 검사 오류가 반환됩니다.
회원가입 커스터마이징
사용자 유효성 검사 및 생성 로직은 Laravel Fortify를 설치할 때 자동으로 생성된 App\Actions\Fortify\CreateNewUser 액션을 수정하여 커스터마이징할 수 있습니다. 예를 들어, 회원가입 시 추가 필드를 저장하거나 특정 역할을 자동으로 부여하는 등의 처리를 이 클래스 안에서 구현하면 됩니다.
비밀번호 재설정
비밀번호 재설정 링크 요청
비밀번호 재설정 기능을 구현하려면, 먼저 Fortify에게 "비밀번호를 잊으셨나요?" 뷰를 어떻게 렌더링할지 알려줘야 합니다. Fortify는 헤드리스(headless) 인증 라이브러리이므로, 뷰 구현은 직접 작성해야 합니다. 프론트엔드까지 미리 완성된 인증 기능이 필요하다면 애플리케이션 스타터 킷을 사용하는 것이 더 적합합니다.
Fortify의 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 메서드로 커스터마이징할 수 있습니다. 아래와 같이 App\Providers\FortifyServiceProvider의 boot 메서드에서 호출하는 것이 일반적입니다.
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::requestPasswordResetLinkView(function () {
return view('auth.forgot-password');
});
// ...
}이 설정을 마치면 Fortify가 /forgot-password 엔드포인트를 자동으로 정의하고, 해당 뷰를 반환합니다. forgot-password 템플릿에는 /forgot-password 엔드포인트로 POST 요청을 보내는 폼이 포함되어야 합니다.
/forgot-password 엔드포인트는 문자열 타입의 email 필드를 요구합니다. 이 필드명(및 데이터베이스 컬럼명)은 fortify 설정 파일의 email 설정값과 일치해야 합니다.
비밀번호 재설정 링크 요청 응답 처리
요청이 성공하면 Fortify는 사용자를 /forgot-password 엔드포인트로 리다이렉트하고, 비밀번호 재설정에 사용할 보안 링크가 담긴 이메일을 발송합니다. XHR 요청인 경우에는 200 HTTP 응답이 반환됩니다.
성공적으로 리다이렉트된 후, 세션의 status 변수를 활용해 처리 결과를 사용자에게 보여줄 수 있습니다.
$status 세션 변수의 값은 애플리케이션의 passwords 언어 파일에 정의된 번역 문자열 중 하나와 매핑됩니다. 이 값을 커스터마이징하고 싶다면, 아직 언어 파일을 퍼블리시하지 않은 경우 lang:publish Artisan 명령을 실행하세요.
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endif요청이 실패하면 사용자는 비밀번호 재설정 링크 요청 화면으로 다시 리다이렉트되며, 유효성 검사 오류는 공유 $errors Blade 템플릿 변수를 통해 접근할 수 있습니다. XHR 요청인 경우에는 422 HTTP 응답과 함께 유효성 검사 오류가 반환됩니다.
비밀번호 재설정
비밀번호 재설정 기능을 완성하려면, Fortify에게 "비밀번호 재설정" 뷰를 어떻게 렌더링할지도 알려줘야 합니다.
마찬가지로 App\Providers\FortifyServiceProvider의 boot 메서드에서 설정합니다.
use Laravel\Fortify\Fortify;
use Illuminate\Http\Request;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::resetPasswordView(function (Request $request) {
return view('auth.reset-password', ['request' => $request]);
});
// ...
}Fortify가 이 뷰를 표시하는 라우트를 자동으로 정의합니다. reset-password 템플릿에는 /reset-password 엔드포인트로 POST 요청을 보내는 폼이 포함되어야 합니다.
/reset-password 엔드포인트는 다음 필드를 요구합니다.
| 필드명 | 설명 |
|---|---|
email | 문자열 타입의 이메일 주소 |
password | 새 비밀번호 |
password_confirmation | 새 비밀번호 확인 |
token | request()->route('token') 값을 담은 히든 필드 |
email 필드명(및 데이터베이스 컬럼명)은 fortify 설정 파일의 email 설정값과 일치해야 합니다.
비밀번호 재설정 응답 처리
비밀번호 재설정 요청이 성공하면, Fortify는 사용자가 새 비밀번호로 로그인할 수 있도록 /login 라우트로 리다이렉트합니다. 이때 status 세션 변수도 함께 설정되므로, 로그인 화면에서 재설정 성공 메시지를 표시할 수 있습니다.
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endifXHR 요청인 경우에는 200 HTTP 응답이 반환됩니다.
요청이 실패하면 사용자는 비밀번호 재설정 화면으로 다시 리다이렉트되며, 유효성 검사 오류는 공유 $errors Blade 템플릿 변수를 통해 접근할 수 있습니다. XHR 요청인 경우에는 422 HTTP 응답과 함께 유효성 검사 오류가 반환됩니다.
비밀번호 재설정 커스터마이징
비밀번호 재설정 프로세스는 Laravel Fortify 설치 시 자동으로 생성된 App\Actions\ResetUserPassword 액션을 수정하여 커스터마이징할 수 있습니다.
이메일 인증
회원가입 후 사용자가 이메일 주소를 인증하도록 요구할 수 있습니다. 이를 위해 먼저 fortify 설정 파일의 features 배열에서 emailVerification 기능이 활성화되어 있는지 확인하세요. 그런 다음 App\Models\User 클래스가 Illuminate\Contracts\Auth\MustVerifyEmail 인터페이스를 구현하고 있는지 확인해야 합니다.
이 두 가지 설정이 완료되면, 새로 가입한 사용자에게 이메일 주소 소유권 확인을 요청하는 인증 메일이 자동으로 발송됩니다. 단, 사용자에게 이메일의 인증 링크를 클릭하라고 안내하는 이메일 인증 화면을 어떻게 표시할지 Fortify에 알려줘야 합니다.
Fortify의 모든 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스의 메서드를 통해 커스터마이징할 수 있습니다. 일반적으로 애플리케이션의 App\Providers\FortifyServiceProvider 클래스의 boot 메서드 안에서 호출합니다.
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 초기화합니다.
*/
public function boot(): void
{
Fortify::verifyEmailView(function () {
return view('auth.verify-email');
});
// ...
}Laravel의 내장 verified 미들웨어가 사용자를 /email/verify 엔드포인트로 리다이렉트할 때, Fortify가 자동으로 해당 뷰를 표시하는 라우트를 등록해 줍니다.
verify-email 템플릿에는 사용자에게 이메일로 전송된 인증 링크를 클릭하라고 안내하는 메시지를 포함해야 합니다.
이메일 인증 링크 재발송
verify-email 템플릿에 버튼을 추가하여 /email/verification-notification 엔드포인트로 POST 요청을 보낼 수 있습니다. 이 엔드포인트가 요청을 받으면 새로운 인증 링크가 담긴 이메일이 사용자에게 재발송됩니다. 이전 링크를 실수로 삭제했거나 이메일을 찾을 수 없는 경우 유용하게 활용할 수 있습니다.
인증 링크 재발송 요청이 성공하면, Fortify는 사용자를 /email/verify 엔드포인트로 다시 리다이렉트하면서 status 세션 변수를 함께 전달합니다. 이 값을 활용해 작업 완료 안내 메시지를 표시할 수 있습니다. XHR 요청인 경우에는 202 HTTP 응답이 반환됩니다.
@if (session('status') == 'verification-link-sent')
<div class="mb-4 font-medium text-sm text-green-600">
새로운 이메일 인증 링크가 발송되었습니다!
</div>
@endif라우트 보호
특정 라우트나 라우트 그룹에 이메일 인증이 완료된 사용자만 접근할 수 있도록 제한하려면, Laravel 내장 verified 미들웨어를 라우트에 적용하면 됩니다. verified 미들웨어 별칭은 Laravel이 자동으로 등록하며, 내부적으로 Illuminate\Auth\Middleware\EnsureEmailIsVerified 미들웨어의 별칭으로 동작합니다.
Route::get('/dashboard', function () {
// ...
})->middleware(['verified']);Laravel Fortify
비밀번호 확인
애플리케이션을 개발하다 보면, 특정 작업을 수행하기 전에 사용자에게 비밀번호를 다시 한번 입력하도록 요구해야 할 때가 있습니다. 예를 들어 결제 수단 변경이나 계정 삭제처럼 민감한 작업이 이에 해당합니다. 일반적으로 이런 라우트는 Laravel 내장 password.confirm 미들웨어로 보호합니다.
비밀번호 확인 기능을 구현하려면 먼저 Fortify에 "비밀번호 확인" 뷰를 어떻게 반환할지 알려주어야 합니다. Fortify는 헤드리스(headless) 인증 라이브러리이므로, 프론트엔드 UI가 미리 완성된 구현체가 필요하다면 애플리케이션 스타터 킷을 사용하는 것을 권장합니다.
Fortify의 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 메서드로 커스터마이징할 수 있습니다. 아래 코드처럼 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출하는 것이 일반적입니다.
use Laravel\Fortify\Fortify;
/**
* 애플리케이션 서비스를 부트스트랩합니다.
*/
public function boot(): void
{
Fortify::confirmPasswordView(function () {
return view('auth.confirm-password');
});
// ...
}이렇게 설정하면 Fortify가 /user/confirm-password 엔드포인트를 자동으로 정의하고, 위에서 지정한 뷰를 반환합니다.
confirm-password 템플릿에는 /user/confirm-password 엔드포인트로 POST 요청을 보내는 폼이 포함되어야 합니다. 이 엔드포인트는 사용자의 현재 비밀번호가 담긴 password 필드를 요구합니다.
요청 성공 시 동작:
- 입력한 비밀번호가 일치하면, Fortify는 사용자가 원래 접근하려 했던 라우트로 리다이렉트합니다.
- XHR 요청인 경우에는
201HTTP 응답을 반환합니다.
요청 실패 시 동작:
- 비밀번호가 일치하지 않으면 비밀번호 확인 화면으로 다시 리다이렉트되며, 유효성 검사 오류는 Blade 템플릿의 공유 변수인
$errors를 통해 확인할 수 있습니다. - XHR 요청인 경우에는 유효성 검사 오류와 함께
422HTTP 응답이 반환됩니다.