인증

업데이트됨

번역일: 2026년 7월 28일

이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.

원문 수정
2026년 7월 28일
번역 갱신
2026년 7월 28일

인증

소개

많은 웹 애플리케이션에서 사용자가 로그인하고 인증받을 수 있는 기능이 필요합니다. Laravel은 이러한 인증 기능을 직접 구현하는 부담을 줄여주기 위해, 인증 구현을 쉽고 빠르게 할 수 있는 도구를 기본으로 제공합니다.

Laravel의 인증 시스템은 크게 두 가지 개념으로 이루어져 있습니다. 바로 **가드(guard)**와 **프로바이더(provider)**입니다.

  • 가드: 각 요청마다 사용자를 어떻게 인증할지 정의합니다. 예를 들어 session 가드는 세션 저장소와 쿠키를 이용해 상태를 유지합니다.
  • 프로바이더: 영구 저장소(데이터베이스 등)에서 사용자를 어떻게 조회할지 정의합니다. Laravel은 기본적으로 Eloquent와 데이터베이스 쿼리 빌더를 지원합니다.

애플리케이션의 인증 설정은 config/auth.php에서 관리합니다. 이 파일에는 가드와 프로바이더를 조정할 수 있는 다양한 옵션이 잘 문서화되어 있으니 참고하세요.

NOTE

가드와 프로바이더를 권한(authorization) 또는 "역할(role)"과 혼동하지 마세요. 권한 관련 기능은 authorization 문서를 참고하세요.

스타터 키트

빠르게 시작하고 싶다면 Laravel 애플리케이션 스타터 키트를 사용하는 것을 권장합니다. 스타터 키트는 로그인, 회원가입, 비밀번호 재설정, 이메일 인증 등 전체 인증 흐름의 스캐폴딩을 자동으로 구성해 줍니다.

스타터 키트를 사용하면 인증 시스템을 직접 설계하고 구현하는 데 시간을 쏟지 않아도 됩니다. 이 문서는 스타터 키트 없이도 Laravel 인증 시스템을 직접 다루고 싶은 분들을 위한 내용을 담고 있습니다.

데이터베이스 고려사항

Laravel은 기본적으로 app/Models 디렉터리에 App\Models\User Eloquent 모델을 포함하고 있습니다. 이 모델은 기본 Eloquent 인증 드라이버와 함께 사용됩니다. 애플리케이션에서 Eloquent를 사용하지 않는다면, Laravel 쿼리 빌더를 사용하는 database 인증 프로바이더를 선택할 수 있습니다.

App\Models\User 모델의 데이터베이스 스키마를 구성할 때, password 컬럼은 최소 60자 이상이어야 합니다. 기본값인 VARCHAR(255)를 사용하면 충분합니다.

또한, users 테이블에 nullable한 문자열 타입의 remember_token 컬럼(100자)이 있어야 합니다. 이 컬럼은 로그인 시 "로그인 상태 유지" 옵션을 선택한 사용자의 토큰을 저장하는 데 사용됩니다. 기본 마이그레이션 파일에는 이미 이 컬럼이 포함되어 있습니다.

에코시스템 개요

Laravel은 인증과 관련하여 여러 패키지를 제공합니다. 본격적으로 시작하기 전에 Laravel의 인증 에코시스템 전체를 간략히 살펴보고, 각 패키지의 용도를 파악해 두면 도움이 됩니다.

먼저 인증 흐름을 이해해 봅시다. 브라우저를 통해 사용하는 일반적인 웹 애플리케이션은 로그인 폼을 통해 사용자 자격증명을 받고, 인증이 성공하면 세션에 사용자 정보를 저장합니다. 이후 브라우저는 세션 쿠키를 함께 전송하고, Laravel은 이 쿠키로 사용자를 식별합니다. API 요청의 경우에는 보통 각 요청마다 토큰을 함께 전달해 인증합니다.

Laravel이 제공하는 주요 인증 관련 패키지는 다음과 같습니다.

스타터 키트

인증 UI와 로직을 포함한 스캐폴딩을 빠르게 생성해 줍니다. 새 프로젝트에서 인증을 빠르게 구성하고 싶다면 가장 먼저 고려하세요.

Laravel Sanctum

API 토큰 인증과 SPA(싱글 페이지 애플리케이션) 인증을 모두 지원하는 경량 패키지입니다. Sanctum은 세션 기반 인증과 토큰 기반 인증을 모두 처리할 수 있으며, 사용자별로 여러 개의 API 토큰을 발급하고 각 토큰에 권한(ability)을 부여할 수 있습니다. Vue, React 등의 프론트엔드와 Laravel API를 연동하는 프로젝트에 적합합니다.

Laravel Passport

완전한 OAuth2 서버 구현체입니다. 외부 서드파티 애플리케이션에 API 접근 권한을 부여해야 하는 복잡한 시나리오에 적합합니다. 단순한 SPA나 모바일 앱 연동이라면 Sanctum으로 충분한 경우가 많습니다.

Laravel Socialite

Google, Kakao, Naver 등 OAuth 기반 소셜 로그인을 간편하게 구현할 수 있는 패키지입니다.

NOTE

어떤 패키지를 선택할지 고민된다면 다음 기준을 참고하세요.

  • 일반 웹앱: 스타터 키트 + 기본 세션 인증
  • SPA 또는 모바일 앱: Laravel Sanctum
  • 외부 서드파티 OAuth 서버 구축: Laravel Passport
  • 소셜 로그인 연동: Laravel Socialite

인증 빠른 시작

스타터 키트 설치

인증을 가장 빠르게 구성하는 방법은 Laravel 애플리케이션 스타터 키트를 사용하는 것입니다. 스타터 키트는 로그인, 회원가입, 비밀번호 재설정, 이메일 인증, 비밀번호 확인 등 전체 인증 흐름을 자동으로 스캐폴딩해 줍니다.

스타터 키트를 사용하면 인증 로직뿐 아니라 UI까지 즉시 사용할 수 있는 상태로 제공됩니다. 이후 필요에 따라 자유롭게 수정하면 됩니다.

인증된 사용자 가져오기

스타터 키트를 통해 인증 시스템을 구성한 후에는, 현재 로그인한 사용자 정보를 가져오는 방법을 알아야 합니다. 요청을 처리하는 도중 Auth 파사드를 통해 인증된 사용자에 접근할 수 있습니다.

use Illuminate\Support\Facades\Auth; // 현재 인증된 사용자 가져오기 $user = Auth::user(); // 현재 인증된 사용자의 ID 가져오기 $id = Auth::id();

또는 Illuminate\Http\Request 인스턴스를 통해서도 현재 사용자에 접근할 수 있습니다. 컨트롤러 메서드에서 타입힌트로 Request를 주입받으면, 어디서든 $request->user()를 호출할 수 있습니다.

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class FlightController extends Controller { /** * 기존 항공편 정보를 업데이트합니다. */ public function update(Request $request): RedirectResponse { $user = $request->user(); // ... } }

사용자 인증 여부 확인

현재 요청을 보낸 사용자가 로그인한 상태인지 확인하려면 Auth 파사드의 check 메서드를 사용합니다. 인증된 사용자라면 true를 반환합니다.

use Illuminate\Support\Facades\Auth; if (Auth::check()) { // 사용자가 로그인한 상태입니다. }

NOTE

check 메서드로도 인증 여부를 확인할 수 있지만, 실제로는 미들웨어를 사용해 특정 라우트나 컨트롤러에 접근하기 전에 인증 여부를 확인하는 것이 일반적입니다. 자세한 내용은 라우트 보호 문서를 참고하세요.

라우트 보호

라우트 미들웨어를 사용하면 인증된 사용자만 특정 라우트에 접근할 수 있도록 제한할 수 있습니다. Laravel은 Illuminate\Auth\Middleware\Authenticate 클래스를 참조하는 auth 미들웨어를 기본으로 제공합니다. 라우트 정의에 이 미들웨어를 적용하기만 하면 됩니다.

Route::get('/flights', function () { // 인증된 사용자만 이 라우트에 접근할 수 있습니다. })->middleware('auth');

인증되지 않은 사용자가 이 라우트에 접근하면, Laravel은 자동으로 login 이름의 라우트로 리다이렉트합니다.

리다이렉트 경로 변경

인증되지 않은 사용자를 다른 경로로 리다이렉트하고 싶다면, bootstrap/app.php 파일에서 redirectGuestsTo 메서드를 사용해 경로를 지정할 수 있습니다.

use Illuminate\Http\Request; ->withMiddleware(function (Middleware $middleware) { $middleware->redirectGuestsTo('/login'); // 클로저를 사용할 수도 있습니다. $middleware->redirectGuestsTo(fn (Request $request) => route('login')); })

가드 지정

auth 미들웨어를 적용할 때, 어떤 가드를 사용할지 지정할 수 있습니다. 지정하는 가드 이름은 config/auth.phpguards 배열에 정의된 키 중 하나여야 합니다.

Route::get('/flights', function () { // 인증된 사용자만 접근 가능합니다. })->middleware('auth:admin');

로그인 횟수 제한

Laravel Breeze 또는 Laravel Jetstream 스타터 키트를 사용하는 경우, 로그인 시도에 자동으로 횟수 제한(rate limiting)이 적용됩니다. 일정 횟수 이상 로그인에 실패하면 사용자는 일정 시간 동안 로그인을 시도할 수 없게 됩니다. 제한은 사용자의 사용자명/이메일과 IP 주소의 조합을 기준으로 적용됩니다.

NOTE

애플리케이션의 다른 라우트에도 횟수 제한을 적용하고 싶다면 rate limiting 문서를 참고하세요.

사용자 직접 인증

스타터 키트를 반드시 사용해야 하는 것은 아닙니다. 스타터 키트 없이 Laravel의 인증 클래스를 직접 다루는 방법을 알아보겠습니다.

Auth 파사드의 attempt 메서드를 사용합니다. 보통 이 메서드는 로그인 폼을 처리하는 컨트롤러에서 호출합니다. attempt 메서드는 첫 번째 인수로 자격증명 배열을 받습니다. 전달된 값을 기반으로 데이터베이스에서 사용자를 조회하고, 저장된 해시 비밀번호와 비교합니다. 비밀번호는 직접 해싱하지 않아도 됩니다 — 프레임워크가 자동으로 처리합니다. 인증이 성공하면 세션이 시작됩니다.

attempt 메서드는 인증 성공 시 true를, 실패 시 false를 반환합니다.

intended 메서드는 인증 미들웨어에 의해 차단되기 전 사용자가 접근하려 했던 URL로 리다이렉트해 줍니다. 해당 URL이 없을 경우를 대비해 대체 경로를 인수로 전달할 수 있습니다.

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Auth; class LoginController extends Controller { /** * 인증 시도를 처리합니다. */ public function authenticate(Request $request): RedirectResponse { $credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required'], ]); if (Auth::attempt($credentials)) { $request->session()->regenerate(); return redirect()->intended('dashboard'); } return back()->withErrors([ 'email' => '입력하신 정보와 일치하는 계정을 찾을 수 없습니다.', ])->onlyInput('email'); } }

NOTE

로그인 성공 후 $request->session()->regenerate()를 호출하는 것은 세션 고정 공격(session fixation)을 방지하기 위한 중요한 보안 조치입니다. 반드시 포함하세요.

특정 조건으로 사용자 조회

attempt 메서드에 추가적인 쿼리 조건을 전달할 수도 있습니다. 예를 들어, 사용자가 "활성화된" 상태인지 함께 확인할 수 있습니다.

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) { // 인증 성공 }

복잡한 쿼리 조건이 필요한 경우, 자격증명 배열에 클로저를 포함할 수 있습니다. 클로저는 쿼리 인스턴스를 받아 애플리케이션의 필요에 맞게 쿼리를 수정할 수 있습니다.

use Illuminate\Database\Eloquent\Builder; if (Auth::attempt([ 'email' => $email, 'password' => $password, fn (Builder $query) => $query->has('activeSubscription'), ])) { // 인증 성공 }

WARNING

위 예시에서 password는 쿼리 조건으로 사용되지 않습니다. 비밀번호 필드는 항상 Auth 시스템이 별도로 처리합니다. 마찬가지로 password라는 키를 갖는 값은 쿼리 조건에서 제외됩니다.

가드를 지정한 인증

특정 가드를 사용해 인증하려면 Auth::guard() 메서드에 가드 이름을 전달합니다. 이를 통해 같은 애플리케이션 내에서 서로 다른 사용자 모델이나 테이블로 독립적인 인증을 구성할 수 있습니다.

if (Auth::guard('admin')->attempt($credentials)) { // ... }

사용자 기억하기

많은 웹 애플리케이션에서 로그인 폼에 "로그인 상태 유지" 체크박스를 제공합니다. 이 기능을 구현하려면 attempt 메서드의 두 번째 인수로 true를 전달합니다.

이 기능이 활성화되면 Laravel은 사용자가 수동으로 로그아웃할 때까지 인증 상태를 무기한 유지합니다. users 테이블에 remember_token 컬럼이 필요하며(문자열 타입), 기본 마이그레이션에는 이미 포함되어 있습니다.

use Illuminate\Support\Facades\Auth; if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) { // 사용자의 인증 상태를 유지합니다. }

현재 사용자가 "로그인 상태 유지" 쿠키로 인증된 상태인지 확인하려면 viaRemember 메서드를 사용합니다.

use Illuminate\Support\Facades\Auth; if (Auth::viaRemember()) { // ... }

기타 인증 방법

사용자 인스턴스로 직접 인증

이미 조회한 사용자 인스턴스를 기반으로 인증 상태를 설정하려면 Auth::login 메서드에 해당 인스턴스를 전달합니다. 전달하는 객체는 Illuminate\Contracts\Auth\Authenticatable 컨트랙트를 구현해야 합니다. Laravel의 App\Models\User 모델은 이미 이 컨트랙트를 구현하고 있습니다. 이 방법은 회원가입 직후 자동 로그인 처리에 유용합니다.

use Illuminate\Support\Facades\Auth; Auth::login($user);

"로그인 상태 유지"를 함께 설정하려면 두 번째 인수에 true를 전달합니다.

Auth::login($user, $remember = true);

특정 가드를 사용해 인증하려면 guard 메서드를 먼저 호출합니다.

Auth::guard('admin')->login($user);

사용자 ID로 직접 인증

데이터베이스의 기본 키(primary key)를 사용해 사용자를 인증하려면 loginUsingId 메서드를 사용합니다.

Auth::loginUsingId(1);

"로그인 상태 유지"를 함께 설정하려면 두 번째 인수에 true를 전달합니다.

Auth::loginUsingId(1, remember: true);

일회성 인증

once 메서드를 사용하면 세션이나 쿠키 없이 단일 요청에 대해서만 인증 상태를 설정할 수 있습니다. 세션이 필요 없는 stateless API 요청 처리에 유용합니다.

if (Auth::once($credentials)) { // ... }

HTTP Basic 인증

HTTP Basic 인증은 별도의 로그인 페이지 없이도 간단하게 사용자를 인증할 수 있는 방법입니다. auth.basic 미들웨어를 라우트에 적용하기만 하면 됩니다. auth.basic 미들웨어는 Laravel에 기본 포함되어 있으므로 별도 등록 없이 바로 사용할 수 있습니다.

Route::get('/profile', function () { // 인증된 사용자만 접근 가능합니다. })->middleware('auth.basic');

미들웨어가 적용된 라우트에 접근하면 브라우저가 자동으로 자격증명 입력창을 표시합니다. 기본적으로 auth.basic 미들웨어는 users 테이블의 email 컬럼을 "사용자명"으로 사용합니다.

FastCGI 환경 주의사항

PHP FastCGI와 Apache를 함께 사용하는 경우 HTTP Basic 인증이 정상적으로 동작하지 않을 수 있습니다. 이 경우 .htaccess 파일에 다음 설정을 추가하세요.

RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Stateless HTTP Basic 인증

세션에 사용자 식별 쿠키를 저장하지 않는 Stateless HTTP Basic 인증도 사용할 수 있습니다. API 인증처럼 각 요청마다 자격증명을 함께 전달하는 경우에 유용합니다. 이를 위해 onceBasic 메서드를 호출하는 미들웨어를 직접 정의합니다.

<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Symfony\Component\HttpFoundation\Response; class AuthenticateOnceWithBasicAuth { /** * 들어오는 요청을 처리합니다. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { return Auth::onceBasic() ?: $next($request); } }

그리고 이 미들웨어를 라우트에 적용합니다.

Route::get('/api/user', function () { // 인증된 사용자만 접근 가능합니다. })->middleware(AuthenticateOnceWithBasicAuth::class);

로그아웃

사용자를 로그아웃 처리하려면 Auth 파사드의 logout 메서드를 호출합니다. 이 메서드는 세션에서 인증 정보를 제거합니다. 이후 세션을 무효화하고 CSRF 토큰을 재생성해야 보안을 유지할 수 있습니다.

use Illuminate\Http\Request; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Auth; /** * 사용자를 로그아웃 처리합니다. */ public function logout(Request $request): RedirectResponse { Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/'); }

다른 기기의 세션 무효화

Laravel은 현재 기기의 세션은 유지하면서 다른 기기에서 활성화된 세션만 무효화하는 기능도 제공합니다. 비밀번호 변경 시 다른 기기의 로그인을 일괄 해제하는 용도로 활용할 수 있습니다.

이 기능을 사용하려면 먼저 bootstrap/app.php에서 Illuminate\Session\Middleware\AuthenticateSession 미들웨어가 해당 라우트에 적용되어 있어야 합니다.

use Illuminate\Session\Middleware\AuthenticateSession; ->withMiddleware(function (Middleware $middleware) { $middleware->authenticateSessions(); })

그런 다음 Auth 파사드의 logoutOtherDevices 메서드를 호출합니다. 이 메서드는 현재 비밀번호 확인이 필요합니다.

use Illuminate\Support\Facades\Auth; Auth::logoutOtherDevices($currentPassword);

logoutOtherDevices 메서드가 호출되면, 해당 사용자의 다른 모든 세션이 완전히 무효화되어 기존에 인증된 모든 가드에서 로그아웃 처리됩니다.

비밀번호 확인

애플리케이션을 개발하다 보면 특정 민감한 작업(결제 수단 변경, 중요 설정 수정 등)을 수행하기 전에 사용자에게 비밀번호 재입력을 요구하는 경우가 있습니다. Laravel은 이를 위한 미들웨어를 기본으로 제공합니다.

이 기능을 구현하려면 비밀번호 확인 뷰를 표시하는 라우트와 확인 처리 라우트, 두 가지가 필요합니다.

NOTE

이하 내용은 Laravel의 비밀번호 확인 기능을 직접 구성하는 방법을 설명합니다. 스타터 키트를 사용하면 이 기능이 자동으로 포함됩니다.

설정

비밀번호 확인 후에는 기본적으로 3시간 동안 다시 비밀번호를 요구하지 않습니다. config/auth.phppassword_timeout 값을 수정하여 이 시간을 변경할 수 있습니다.

라우팅

비밀번호 확인 폼 표시

비밀번호를 확인하는 뷰를 반환하는 라우트를 정의합니다.

Route::get('/confirm-password', function () { return view('auth.confirm-password'); })->middleware('auth')->name('password.confirm');

이 뷰에는 password 필드가 포함된 폼이 있어야 하며, 민감한 작업을 수행하려면 비밀번호 확인이 필요하다는 안내 문구를 추가하는 것이 좋습니다.

비밀번호 확인 처리

비밀번호 확인 폼 요청을 처리하는 라우트를 정의합니다.

use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Redirect; Route::post('/confirm-password', function (Request $request) { if (! Hash::check($request->password, $request->user()->password)) { return back()->withErrors([ 'password' => ['입력하신 비밀번호가 올바르지 않습니다.'], ]); } $request->session()->passwordConfirmed(); return redirect()->intended(); })->middleware(['auth', 'throttle:6,1']);

이 라우트는 사용자가 입력한 비밀번호가 실제 비밀번호와 일치하는지 확인합니다. 일치하면 세션에 비밀번호 확인 시각을 기록하고, 원래 접근하려 했던 URL로 리다이렉트합니다.

라우트 보호

비밀번호 확인이 필요한 라우트에는 password.confirm 미들웨어를 적용합니다. 비밀번호 확인이 되지 않은 사용자는 자동으로 비밀번호 확인 뷰(password.confirm 라우트)로 리다이렉트됩니다.

Route::get('/settings', function () { // ... })->middleware(['auth', 'password.confirm']); Route::post('/settings', function () { // ... })->middleware(['auth', 'password.confirm']);

커스텀 가드 추가

Auth 파사드의 extend 메서드를 사용해 커스텀 인증 가드를 정의할 수 있습니다. 이 코드는 서비스 프로바이더boot 메서드 안에 작성합니다.

<?php namespace App\Providers; use App\Services\Auth\JwtGuard; use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\Facades\Auth; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * 애플리케이션 서비스를 부트스트랩합니다. */ public function boot(): void { Auth::extend('jwt', function (Application $app, string $name, array $config) { // Illuminate\Contracts\Auth\Guard 구현체를 반환합니다. return new JwtGuard(Auth::createUserProvider($config['provider'])); }); } }

위 예시처럼 가드를 등록한 후 config/auth.php에서 해당 가드를 지정할 수 있습니다.

'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ],

클로저 요청 가드

HTTP 요청 기반의 커스텀 인증 시스템을 가장 간단하게 구현하는 방법은 Auth::viaRequest 메서드를 사용하는 것입니다. 하나의 클로저만으로 인증 로직을 정의할 수 있습니다.

AppServiceProviderboot 메서드 안에서 Auth::viaRequest를 호출합니다. 첫 번째 인수는 가드 이름(임의의 문자열), 두 번째 인수는 HTTP 요청을 받아 사용자 인스턴스 또는 null을 반환하는 클로저입니다.

use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; /** * 애플리케이션 서비스를 부트스트랩합니다. */ public function boot(): void { Auth::viaRequest('custom-token', function (Request $request) { return User::where('token', (string) $request->token)->first(); }); }

커스텀 가드를 정의한 후 config/auth.php에서 사용할 수 있습니다.

'guards' => [ 'api' => [ 'driver' => 'custom-token', ], ],

마지막으로 이 가드를 라우트의 인증 미들웨어에 지정합니다.

Route::middleware('auth:api')->group(function () { // ... });

커스텀 사용자 프로바이더 추가

사용자 데이터를 관계형 데이터베이스가 아닌 별도의 저장소(예: Redis, 외부 API 등)에 보관하는 경우, 커스텀 사용자 프로바이더를 정의해야 합니다. Auth::provider 메서드를 사용해 커스텀 프로바이더를 등록합니다.

<?php namespace App\Providers; use App\Extensions\MongoUserProvider; use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\Facades\Auth; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * 애플리케이션 서비스를 부트스트랩합니다. */ public function boot(): void { Auth::provider('mongo', function (Application $app, array $config) { // Illuminate\Contracts\Auth\UserProvider 구현체를 반환합니다. return new MongoUserProvider($app->make('mongo.connection')); }); } }

이후 config/auth.php에서 이 프로바이더를 사용하도록 설정합니다.

'providers' => [ 'users' => [ 'driver' => 'mongo', ], ],

그리고 guards 설정에서 이 프로바이더를 참조합니다.

'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], ],

User Provider 컨트랙트

Illuminate\Contracts\Auth\UserProvider 구현체는 MySQL, MongoDB 등 영구 저장소에서 Illuminate\Contracts\Auth\Authenticatable 구현체를 조회하는 역할을 담당합니다. 이 두 인터페이스를 통해 사용자 데이터 저장 방식이나 모델 구조에 관계없이 Laravel 인증 메커니즘이 정상 동작할 수 있습니다.

Illuminate\Contracts\Auth\UserProvider 컨트랙트를 살펴봅시다.

<?php namespace Illuminate\Contracts\Auth; interface UserProvider { public function retrieveById($identifier); public function retrieveByToken($identifier, $token); public function updateRememberToken(Authenticatable $user, $token); public function retrieveByCredentials(array $credentials); public function validateCredentials(Authenticatable $user, array $credentials); public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false); }

각 메서드의 역할은 다음과 같습니다.

  • retrieveById: 기본 키(예: MySQL의 auto-increment ID)로 사용자를 조회합니다.
  • retrieveByToken: ID와 remember_token으로 사용자를 조회합니다. "로그인 상태 유지" 기능에 사용됩니다.
  • updateRememberToken: 사용자의 remember_token을 새 토큰으로 업데이트합니다. "로그인 상태 유지" 로그인 성공 또는 로그아웃 시 호출됩니다.
  • retrieveByCredentials: Auth::attempt 호출 시 전달된 자격증명 배열로 사용자를 조회합니다. 비밀번호 검증은 이 메서드에서 수행하지 않습니다.
  • validateCredentials: 조회된 사용자와 자격증명을 비교해 인증 여부를 반환합니다.
  • rehashPasswordIfRequired: 필요한 경우 비밀번호를 재해싱합니다.

Authenticatable 컨트랙트

UserProvider의 각 메서드를 구현할 때 Authenticatable 컨트랙트도 함께 살펴봐야 합니다.

<?php namespace Illuminate\Contracts\Auth; interface Authenticatable { public function getAuthIdentifierName(); public function getAuthIdentifier(); public function getAuthPasswordName(); public function getAuthPassword(); public function getRememberToken(); public function setRememberToken($value); public function getRememberTokenName(); }

각 메서드의 역할은 다음과 같습니다.

  • getAuthIdentifierName: 기본 키 컬럼명을 반환합니다.
  • getAuthIdentifier: 사용자의 기본 키 값을 반환합니다.
  • getAuthPasswordName: 비밀번호 컬럼명을 반환합니다.
  • getAuthPassword: 해시된 비밀번호를 반환합니다.
  • getRememberToken, setRememberToken, getRememberTokenName: "로그인 상태 유지" 토큰을 관리합니다.

이 인터페이스를 구현하면 어떤 ORM이나 저장 계층을 사용하더라도 Laravel 인증 시스템과 연동할 수 있습니다. Laravel은 app/Models 디렉터리에 이 컨트랙트를 구현한 User 모델을 기본으로 제공합니다.

자동 비밀번호 재해싱

Laravel의 기본 비밀번호 해싱 알고리즘은 bcrypt입니다. bcrypt의 "work factor"(해싱 강도)는 config/hashing.php 또는 BCRYPT_ROUNDS 환경 변수로 조정할 수 있습니다.

서버 성능이 향상됨에 따라 해싱 강도를 높이고 싶을 때, 사용자가 다음에 로그인할 때 자동으로 비밀번호를 새 강도로 재해싱해 주는 기능이 있습니다. attempt 또는 validate 메서드 호출 시 기본적으로 자동 재해싱이 수행됩니다.

단, 이 동작을 비활성화하고 싶다면 AppServiceProviderboot 메서드에서 다음과 같이 설정합니다.

use Illuminate\Support\Facades\Auth; Auth::withoutPasswordRehashing();

이벤트

Laravel은 인증 과정에서 다양한 이벤트를 발생시킵니다. 다음 이벤트에 대해 리스너를 정의해 인증 흐름에 개입할 수 있습니다.

이벤트 클래스
Illuminate\Auth\Events\Registered
Illuminate\Auth\Events\Attempting
Illuminate\Auth\Events\Authenticated
Illuminate\Auth\Events\Login
Illuminate\Auth\Events\Failed
Illuminate\Auth\Events\Validated
Illuminate\Auth\Events\Verified
Illuminate\Auth\Events\Logout
Illuminate\Auth\Events\CurrentDeviceLogout
Illuminate\Auth\Events\OtherDeviceLogout
Illuminate\Auth\Events\PasswordReset
Illuminate\Auth\Events\PasswordResetLinkSent
Illuminate\Auth\Events\Lockout

인증

소개

대부분의 웹 애플리케이션은 사용자가 로그인할 수 있는 인증 기능을 제공합니다. 이 기능을 직접 구현하는 것은 생각보다 복잡하고, 잘못 구현하면 보안 취약점이 생길 수 있습니다. 그래서 Laravel은 인증을 빠르고 안전하게 구현할 수 있는 도구들을 기본으로 제공합니다.

Laravel 인증 시스템의 핵심은 가드(Guard)프로바이더(Provider) 로 구성됩니다.

  • 가드: 각 요청에서 사용자를 어떻게 인증할지 정의합니다. 예를 들어 기본으로 제공되는 session 가드는 세션 스토리지와 쿠키를 이용해 인증 상태를 유지합니다.
  • 프로바이더: 영구 저장소(데이터베이스 등)에서 사용자를 어떻게 조회할지 정의합니다. 기본적으로 Eloquent와 쿼리 빌더를 지원하며, 필요에 따라 커스텀 프로바이더를 추가할 수 있습니다.

인증 관련 설정 파일은 config/auth.php에 있습니다. 각 옵션에 대한 설명이 파일 안에 주석으로 잘 정리되어 있으니 참고하세요.

NOTE

가드와 프로바이더는 "역할(role)"이나 "권한(permission)"과는 다른 개념입니다. 사용자 행동에 대한 권한 처리는 인가(Authorization) 문서를 참고하세요.

스타터 킷

빠르게 시작하고 싶다면 새 Laravel 프로젝트에 애플리케이션 스타터 킷을 설치하는 것을 추천합니다. 데이터베이스 마이그레이션 후 브라우저에서 /register에 접속하면 회원가입부터 로그인까지 인증 시스템 전체가 이미 갖춰져 있는 것을 확인할 수 있습니다.

최종 프로젝트에 스타터 킷을 사용하지 않더라도, 학습 목적으로 한 번 설치해 보는 것을 강력히 권장합니다. 스타터 킷에는 인증 관련 컨트롤러, 라우트, 뷰가 모두 포함되어 있어, 실제 코드를 통해 Laravel 인증 시스템이 어떻게 동작하는지 직접 확인할 수 있습니다.

데이터베이스 고려사항

Laravel은 기본적으로 app/Models 디렉터리에 App\Models\User Eloquent 모델을 포함합니다. 이 모델은 기본 Eloquent 인증 드라이버와 함께 사용됩니다.

Eloquent를 사용하지 않는 경우에는 Laravel 쿼리 빌더를 사용하는 database 인증 프로바이더를 사용할 수 있습니다. MongoDB를 사용하는 경우에는 MongoDB 공식 Laravel 사용자 인증 문서를 참고하세요.

App\Models\User 모델에 대한 데이터베이스 스키마를 직접 작성할 경우, 다음 두 가지를 반드시 확인하세요.

  • password 컬럼은 최소 60자 이상이어야 합니다. (새 Laravel 프로젝트에 포함된 기본 마이그레이션은 이미 이 조건을 충족합니다.)
  • users 테이블(또는 동등한 테이블)에 nullable string 타입의 remember_token 컬럼(100자)이 있어야 합니다. 이 컬럼은 "로그인 상태 유지(remember me)" 기능에서 토큰을 저장하는 데 사용됩니다. 기본 마이그레이션에는 이 컬럼도 포함되어 있습니다.

에코시스템 개요

Laravel은 인증과 관련된 여러 패키지를 제공합니다. 본격적으로 시작하기 전에, Laravel 인증 생태계 전체를 한번 살펴보고 각 패키지의 용도를 파악해 두는 것이 좋습니다.

인증이 동작하는 방식

브라우저를 통한 인증 흐름은 다음과 같습니다. 사용자가 로그인 폼에 이메일/비밀번호를 입력하면, 애플리케이션은 자격증명을 확인한 뒤 인증된 사용자 정보를 세션에 저장합니다. 브라우저에는 세션 ID가 담긴 쿠키가 발급되고, 이후 요청마다 이 쿠키를 통해 해당 세션을 찾아 사용자를 "인증된 상태"로 식별합니다.

반면, 외부 서비스가 API를 통해 접근할 때는 브라우저가 없으므로 쿠키 방식은 적합하지 않습니다. 대신 매 요청마다 API 토큰을 함께 전송하고, 애플리케이션은 이 토큰을 검증해 요청을 인증합니다.

Laravel 기본 브라우저 인증 서비스

Laravel은 AuthSession 파사드를 통해 접근할 수 있는 내장 인증 및 세션 서비스를 제공합니다. 이 서비스들은 브라우저에서 시작된 요청에 대해 쿠키 기반 인증을 처리하며, 자격증명 검증, 사용자 인증, 세션 데이터 저장, 세션 쿠키 발급 등을 자동으로 수행합니다.

애플리케이션 스타터 킷

이 문서에서 설명하는 서비스를 직접 활용해 인증 레이어를 구현할 수도 있지만, 무료 스타터 킷을 사용하면 인증 레이어 전체를 현대적인 방식으로 빠르게 구성할 수 있습니다.

Laravel API 인증 서비스

Laravel은 API 토큰 관리와 토큰 기반 요청 인증을 위해 두 가지 선택적 패키지를 제공합니다: PassportSanctum. 이 패키지들은 내장 쿠키 기반 인증과 상호 배타적이지 않으며, 함께 사용할 수 있습니다.

Passport

Passport는 OAuth2 인증 프로바이더로, 다양한 OAuth2 "그랜트 타입"을 지원하여 여러 종류의 토큰을 발급할 수 있습니다. 강력하고 완성도 높은 패키지이지만, 그만큼 복잡합니다. OAuth2 명세의 복잡한 기능이 꼭 필요하지 않은 일반적인 애플리케이션에서는 오히려 불필요한 복잡성을 더할 수 있습니다. SPA나 모바일 앱을 OAuth2로 인증하는 방식 역시 개발자들이 자주 혼란을 겪는 부분입니다.

Sanctum

OAuth2의 복잡성에 대한 대안으로 탄생한 Laravel Sanctum은 브라우저 기반 1st-party 요청과 API 토큰 인증을 모두 처리할 수 있는 단순하고 유연한 패키지입니다.

Sanctum은 요청을 받으면 먼저 세션 쿠키를 통한 인증을 시도하고, 쿠키가 없으면 API 토큰으로 인증을 시도합니다. 이 덕분에 하나의 패키지로 웹 UI와 API 인증을 모두 처리할 수 있습니다. 자세한 동작 방식은 Sanctum의 "동작 방식" 문서를 참고하세요.

자체 웹 UI와 API를 함께 제공하는 애플리케이션, SPA, 또는 모바일 클라이언트가 있는 애플리케이션이라면 Sanctum을 기본 선택으로 고려하세요.

정리: 어떤 스택을 선택해야 할까?

상황에 맞는 인증 방식을 정리하면 다음과 같습니다.

상황추천 방식
브라우저 기반 모놀리식 Laravel 앱Laravel 내장 인증 서비스
API + SPA 또는 모바일 클라이언트Sanctum
OAuth2 전체 스펙이 필요한 경우Passport
AI 클라이언트가 접근하는 MCP 서버Passport (MCP 클라이언트는 OAuth 인증을 기대함)
빠르게 시작하고 싶은 경우스타터 킷

일반적으로 외부에 API를 제공해야 한다면 Sanctum을 우선적으로 검토하세요. Sanctum은 API 인증, SPA 인증, 모바일 인증을 모두 지원하며, "스코프(scope)"나 "어빌리티(ability)" 기능도 제공합니다.

SPA를 Laravel 백엔드로 구동하는 경우 Sanctum을 사용하면서, 인증 라우트를 직접 구현하거나 Laravel Fortify를 헤드리스 인증 백엔드로 활용할 수 있습니다. Fortify는 회원가입, 비밀번호 재설정, 이메일 인증 등의 라우트와 컨트롤러를 제공합니다.

인증 퀵스타트

WARNING

이 섹션은 Laravel 애플리케이션 스타터 킷을 사용하여 사용자를 인증하는 방법을 설명합니다. 스타터 킷은 UI 스캐폴딩을 포함해 빠르게 시작할 수 있도록 도와줍니다. Laravel의 인증 시스템을 직접 통합하고 싶다면 수동 인증 문서를 참고하세요.

스타터 킷 설치

먼저 Laravel 애플리케이션 스타터 킷을 설치하세요. 스타터 킷은 새 Laravel 애플리케이션에 인증 기능을 곧바로 포함할 수 있는 깔끔한 시작점을 제공합니다.

인증된 사용자 가져오기

스타터 킷으로 애플리케이션을 만들고 사용자가 회원가입 및 로그인할 수 있게 됐다면, 현재 인증된 사용자 정보에 접근해야 할 상황이 자주 생깁니다. 요청을 처리하는 중에는 Auth 파사드의 user 메서드로 현재 사용자를 가져올 수 있습니다.

use Illuminate\Support\Facades\Auth; // 현재 인증된 사용자 가져오기 $user = Auth::user(); // 현재 인증된 사용자의 ID 가져오기 $id = Auth::id();

또는, 사용자가 인증된 후에는 Illuminate\Http\Request 인스턴스를 통해서도 인증된 사용자에 접근할 수 있습니다. 타입 힌트로 선언된 클래스는 컨트롤러 메서드에 자동으로 주입됩니다. Illuminate\Http\Request를 타입 힌트로 선언하면, 어떤 컨트롤러 메서드에서든 $request->user()로 현재 사용자를 편리하게 가져올 수 있습니다.

<?php namespace App\Http\Controllers; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; class FlightController extends Controller { /** * 항공편 정보를 업데이트합니다. */ public function update(Request $request): RedirectResponse { $user = $request->user(); // ... return redirect('/flights'); } }

현재 사용자가 인증되어 있는지 확인

현재 HTTP 요청을 보낸 사용자가 인증되어 있는지 확인하려면 Auth 파사드의 check 메서드를 사용하세요. 인증된 사용자라면 true를 반환합니다.

use Illuminate\Support\Facades\Auth; if (Auth::check()) { // 사용자가 로그인한 상태입니다... }

NOTE

check 메서드로 인증 여부를 직접 확인하는 것도 가능하지만, 실제로는 미들웨어를 사용해 특정 라우트나 컨트롤러에 접근하기 전에 인증 여부를 검사하는 방식이 일반적입니다. 자세한 내용은 라우트 보호하기 문서를 참고하세요.

라우트 보호하기

라우트 미들웨어를 사용하면 인증된 사용자만 특정 라우트에 접근하도록 제한할 수 있습니다. Laravel은 Illuminate\Auth\Middleware\Authenticate 클래스에 대한 미들웨어 별칭으로 auth 미들웨어를 기본 제공합니다. 별칭이 이미 내부적으로 등록되어 있으므로, 라우트 정의에 미들웨어를 붙이기만 하면 됩니다.

Route::get('/flights', function () { // 인증된 사용자만 이 라우트에 접근할 수 있습니다... })->middleware('auth');

비인증 사용자 리다이렉트

auth 미들웨어가 인증되지 않은 사용자를 감지하면, login이라는 이름이 지정된 라우트로 자동 리다이렉트합니다. 이 동작을 변경하려면 애플리케이션의 bootstrap/app.php 파일에서 redirectGuestsTo 메서드를 사용하세요.

use Illuminate\Http\Request; ->withMiddleware(function (Middleware $middleware): void { $middleware->redirectGuestsTo('/login'); // 클로저를 사용하는 방법 $middleware->redirectGuestsTo(fn (Request $request) => route('login')); })

인증된 사용자 리다이렉트

guest 미들웨어가 이미 인증된 사용자를 감지하면, dashboard 또는 home이라는 이름의 라우트로 리다이렉트합니다. 이 동작을 변경하려면 bootstrap/app.php 파일에서 redirectUsersTo 메서드를 사용하세요.

use Illuminate\Http\Request; ->withMiddleware(function (Middleware $middleware): void { $middleware->redirectUsersTo('/panel'); // 클로저를 사용하는 방법 $middleware->redirectUsersTo(fn (Request $request) => route('panel')); })

가드 지정하기

라우트에 auth 미들웨어를 연결할 때, 사용자 인증에 사용할 "가드"를 명시적으로 지정할 수도 있습니다. 지정하는 가드 이름은 auth.php 설정 파일의 guards 배열에 정의된 키 중 하나여야 합니다.

Route::get('/flights', function () { // 인증된 사용자만 이 라우트에 접근할 수 있습니다... })->middleware('auth:admin');

로그인 횟수 제한

애플리케이션 스타터 킷을 사용하고 있다면, 로그인 시도에 자동으로 속도 제한(Rate Limiting)이 적용됩니다. 기본적으로 여러 번 인증에 실패하면 1분 동안 로그인이 차단됩니다. 이 제한은 사용자의 아이디(이메일 주소)와 IP 주소를 함께 기준으로 적용됩니다.

NOTE

애플리케이션의 다른 라우트에도 속도 제한을 적용하고 싶다면 속도 제한 문서를 참고하세요.

수동으로 사용자 인증하기

Laravel의 스타터 킷이 제공하는 인증 스캐폴딩을 반드시 사용할 필요는 없습니다. 스캐폴딩을 사용하지 않기로 했다면, Laravel의 인증 클래스를 직접 다뤄야 합니다. 걱정하지 않아도 됩니다. 생각보다 간단합니다!

Auth 파사드를 통해 인증 서비스에 접근하므로, 클래스 상단에 Auth 파사드를 임포트해야 합니다. 핵심 메서드는 attempt입니다. 이 메서드는 주로 로그인 폼에서 전달된 인증 정보를 처리할 때 사용합니다. 인증에 성공하면 세션 고정 공격을 방지하기 위해 반드시 세션을 재생성해야 합니다.

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Auth; class LoginController extends Controller { /** * 인증 시도를 처리합니다. */ public function authenticate(Request $request): RedirectResponse { $credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required'], ]); if (Auth::attempt($credentials)) { $request->session()->regenerate(); return redirect()->intended('dashboard'); } return back()->withErrors([ 'email' => '입력하신 정보와 일치하는 계정을 찾을 수 없습니다.', ])->onlyInput('email'); } }

attempt 메서드는 첫 번째 인수로 키/값 쌍의 배열을 받습니다. 이 배열의 값을 이용해 데이터베이스에서 사용자를 조회합니다. 위 예시에서는 email 컬럼으로 사용자를 찾습니다. 사용자가 발견되면, 데이터베이스에 저장된 해시된 비밀번호와 배열로 전달된 password 값을 비교합니다. 이때 password 값을 직접 해시할 필요가 없습니다. 프레임워크가 자동으로 해시 처리한 뒤 데이터베이스의 값과 비교하기 때문입니다. 두 비밀번호가 일치하면 인증된 세션이 시작됩니다.

NOTE

Laravel의 인증 서비스는 config/auth.php에 설정된 가드(guard)의 "프로바이더(provider)" 설정을 기반으로 사용자를 조회합니다. 기본 설정에서는 Eloquent 유저 프로바이더가 지정되어 있으며, App\Models\User 모델을 사용합니다. 애플리케이션의 요구에 따라 설정 파일에서 이 값들을 변경할 수 있습니다.

attempt 메서드는 인증에 성공하면 true를, 실패하면 false를 반환합니다.

intended 메서드는 인증 미들웨어에 의해 차단되기 전에 사용자가 접근하려 했던 URL로 리다이렉트합니다. 의도한 목적지를 알 수 없는 경우를 대비해 폴백 URI를 인수로 전달할 수 있습니다.

추가 조건 지정하기

이메일과 비밀번호 외에 추가적인 조건을 인증 쿼리에 포함할 수 있습니다. attempt 메서드에 전달하는 배열에 조건을 추가하면 됩니다. 예를 들어, 사용자가 "활성" 상태인지 확인하려면 다음과 같이 작성합니다.

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) { // 인증 성공... }

더 복잡한 쿼리 조건이 필요하다면 자격증명 배열 안에 클로저를 추가할 수 있습니다. 이 클로저는 쿼리 인스턴스를 인수로 받으므로, 애플리케이션의 필요에 맞게 쿼리를 자유롭게 커스터마이징할 수 있습니다.

use Illuminate\Database\Eloquent\Builder; if (Auth::attempt([ 'email' => $email, 'password' => $password, fn (Builder $query) => $query->has('activeSubscription'), ])) { // 인증 성공... }

WARNING

위 예시에서 email은 필수 항목이 아니라 예시로 사용한 것입니다. 실제 데이터베이스 테이블에서 "사용자 이름"에 해당하는 컬럼명을 사용하면 됩니다.

attemptWhen 메서드는 두 번째 인수로 클로저를 받아, 실제 인증 전에 잠재적 사용자를 더 세밀하게 검사할 수 있게 해줍니다. 클로저는 잠재적 사용자를 인수로 받고, 인증 허용 여부에 따라 true 또는 false를 반환해야 합니다.

if (Auth::attemptWhen([ 'email' => $email, 'password' => $password, ], function (User $user) { return $user->isNotBanned(); })) { // 인증 성공... }

특정 가드 인스턴스 사용하기

Auth 파사드의 guard 메서드를 사용하면 인증 시 어떤 가드 인스턴스를 사용할지 지정할 수 있습니다. 이를 통해 애플리케이션의 서로 다른 영역(예: 일반 회원 / 관리자)에 대해 별도의 인증 모델이나 사용자 테이블을 활용한 독립적인 인증을 구성할 수 있습니다.

guard 메서드에 전달하는 가드 이름은 auth.php 설정 파일에 정의된 가드 중 하나여야 합니다.

if (Auth::guard('admin')->attempt($credentials)) { // ... }

로그인 상태 유지 (Remember Me)

많은 웹 애플리케이션은 로그인 폼에 "로그인 상태 유지" 체크박스를 제공합니다. 이 기능을 구현하려면 attempt 메서드의 두 번째 인수로 불리언 값을 전달하면 됩니다.

이 값이 true이면 Laravel은 사용자가 직접 로그아웃하기 전까지 인증 상태를 무기한 유지합니다. 이 기능을 사용하려면 users 테이블에 "remember me" 토큰을 저장할 remember_token 문자열 컬럼이 있어야 합니다. 새 Laravel 애플리케이션에 포함된 기본 users 테이블 마이그레이션에는 이 컬럼이 이미 포함되어 있습니다.

use Illuminate\Support\Facades\Auth; if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) { // 로그인 상태 유지 처리 중... }

"로그인 상태 유지" 기능을 제공하는 경우, viaRemember 메서드를 사용해 현재 인증된 사용자가 "remember me" 쿠키를 통해 인증되었는지 확인할 수 있습니다.

use Illuminate\Support\Facades\Auth; if (Auth::viaRemember()) { // ... }

기타 인증 방법

사용자 인스턴스로 인증하기

이미 존재하는 사용자 인스턴스를 현재 인증된 사용자로 설정해야 할 경우, Auth 파사드의 login 메서드에 해당 인스턴스를 전달하면 됩니다. 전달하는 인스턴스는 반드시 Illuminate\Contracts\Auth\Authenticatable 컨트랙트를 구현해야 합니다. Laravel에 기본 포함된 App\Models\User 모델은 이미 이 인터페이스를 구현하고 있습니다. 이 방법은 사용자가 회원가입을 완료한 직후처럼 이미 유효한 사용자 인스턴스를 가지고 있을 때 유용합니다.

use Illuminate\Support\Facades\Auth; Auth::login($user);

login 메서드의 두 번째 인수로 불리언 값을 전달해 "로그인 상태 유지" 여부를 지정할 수 있습니다. true로 설정하면 사용자가 직접 로그아웃하기 전까지 인증 상태가 유지됩니다.

Auth::login($user, $remember = true);

필요하다면 login 메서드 호출 전에 사용할 가드를 지정할 수 있습니다.

Auth::guard('admin')->login($user);

ID로 사용자 인증하기

데이터베이스 레코드의 기본 키(primary key)를 사용해 사용자를 인증하려면 loginUsingId 메서드를 사용합니다. 인증하려는 사용자의 기본 키를 인수로 전달하면 됩니다.

Auth::loginUsingId(1);

loginUsingId 메서드의 remember 인수에 불리언 값을 전달해 "로그인 상태 유지" 여부를 지정할 수 있습니다.

Auth::loginUsingId(1, remember: true);

단일 요청에 대해서만 인증하기

once 메서드를 사용하면 단 하나의 요청에 대해서만 사용자를 인증할 수 있습니다. 이 메서드는 세션과 쿠키를 전혀 사용하지 않으며, Login 이벤트도 발생시키지 않습니다. API처럼 상태를 유지하지 않는 요청 처리에 유용합니다.

if (Auth::once($credentials)) { // ... }

HTTP Basic 인증

HTTP Basic 인증은 별도의 로그인 페이지를 만들지 않고도 사용자를 빠르게 인증할 수 있는 방법입니다. 라우트에 auth.basic 미들웨어를 연결하는 것만으로 바로 사용할 수 있습니다. auth.basic 미들웨어는 Laravel 프레임워크에 내장되어 있으므로 별도로 정의할 필요가 없습니다.

Route::get('/profile', function () { // 인증된 사용자만 이 라우트에 접근할 수 있습니다... })->middleware('auth.basic');

미들웨어를 연결하면 브라우저에서 해당 라우트에 접근할 때 자동으로 자격 증명 입력 창이 표시됩니다. 기본적으로 auth.basic 미들웨어는 users 테이블의 email 컬럼을 사용자명으로 사용합니다.

FastCGI 사용 시 주의사항

PHP FastCGI와 Apache로 Laravel 애플리케이션을 서비스하는 경우, HTTP Basic 인증이 정상적으로 동작하지 않을 수 있습니다. 이 문제를 해결하려면 애플리케이션의 .htaccess 파일에 다음 내용을 추가하세요.

RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

상태 비저장(Stateless) HTTP Basic 인증

세션에 사용자 식별 쿠키를 저장하지 않고 HTTP Basic 인증을 사용할 수도 있습니다. 이 방식은 주로 API 요청을 인증할 때 유용합니다. 구현하려면 onceBasic 메서드를 호출하는 미들웨어를 정의하면 됩니다. onceBasic 메서드가 응답을 반환하지 않으면 요청이 애플리케이션 내부로 계속 전달됩니다.

<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Symfony\Component\HttpFoundation\Response; class AuthenticateOnceWithBasicAuth { /** * 들어오는 요청을 처리합니다. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { return Auth::onceBasic() ?: $next($request); } }

다음으로, 이 미들웨어를 라우트에 연결합니다.

Route::get('/api/user', function () { // 인증된 사용자만 이 라우트에 접근할 수 있습니다... })->middleware(AuthenticateOnceWithBasicAuth::class);

NOTE

onceBasic은 세션을 사용하지 않기 때문에 요청이 끝나면 인증 상태가 유지되지 않습니다. 매 요청마다 인증 헤더를 다시 전송해야 하므로, 브라우저 기반 사용자보다는 API 클라이언트에 적합합니다.

로그아웃

사용자를 수동으로 로그아웃시키려면 Auth 파사드의 logout 메서드를 사용합니다. 이 메서드는 사용자의 세션에서 인증 정보를 제거하여, 이후 요청이 인증된 상태로 처리되지 않도록 합니다.

logout 메서드 호출 외에도, 사용자의 세션을 무효화하고 CSRF 토큰을 재생성하는 것을 권장합니다. 로그아웃 후에는 일반적으로 애플리케이션의 루트 경로로 리다이렉트합니다.

use Illuminate\Http\Request; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Auth; /** * 사용자를 애플리케이션에서 로그아웃시킵니다. */ public function logout(Request $request): RedirectResponse { Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/'); }

NOTE

세션 무효화와 CSRF 토큰 재생성을 빠뜨리면, 이전 세션 데이터나 토큰이 남아 보안 취약점이 생길 수 있습니다. 로그아웃 처리 시 세 단계를 모두 수행하는 것이 안전합니다.

다른 기기의 세션 무효화

Laravel은 현재 기기의 세션은 유지하면서, 다른 기기에서 활성화된 세션만 무효화(강제 로그아웃)하는 기능을 제공합니다. 이 기능은 사용자가 비밀번호를 변경할 때 기존에 로그인된 다른 기기들을 모두 로그아웃시키고 싶을 때 유용하게 활용할 수 있습니다.

시작하기 전에, Illuminate\Session\Middleware\AuthenticateSession 미들웨어가 세션 인증이 필요한 라우트에 포함되어 있는지 확인하세요. 일반적으로 라우트 그룹에 적용하여 애플리케이션의 대부분의 라우트에 한 번에 적용하는 것이 좋습니다. 이 미들웨어는 auth.session이라는 미들웨어 별칭으로 라우트에 연결할 수 있습니다.

Route::middleware(['auth', 'auth.session'])->group(function () { Route::get('/', function () { // ... }); });

설정이 완료되면 Auth 파사드의 logoutOtherDevices 메서드를 사용할 수 있습니다. 이 메서드는 사용자의 현재 비밀번호 확인을 요구하므로, 애플리케이션에서 입력 폼을 통해 비밀번호를 받아야 합니다.

use Illuminate\Support\Facades\Auth; Auth::logoutOtherDevices($currentPassword);

logoutOtherDevices 메서드가 호출되면 사용자의 다른 모든 세션이 완전히 무효화됩니다. 즉, 이전에 인증되었던 모든 가드에서 로그아웃 처리됩니다.

인증

비밀번호 재확인

애플리케이션을 개발하다 보면, 민감한 작업을 수행하거나 보안이 필요한 영역으로 이동하기 전에 사용자에게 비밀번호를 다시 입력하도록 요구해야 할 때가 있습니다. Laravel은 이 기능을 손쉽게 구현할 수 있도록 내장 미들웨어를 제공합니다. 구현에는 두 개의 라우트가 필요합니다. 하나는 비밀번호 확인 폼을 보여주는 라우트이고, 다른 하나는 입력된 비밀번호를 검증하고 사용자를 원래 목적지로 리디렉션하는 라우트입니다.

NOTE

직접 구현하는 대신 빠르게 시작하고 싶다면, Laravel 애플리케이션 스타터 킷을 사용하세요. 스타터 킷은 비밀번호 재확인 기능을 기본으로 포함하고 있습니다.

설정

비밀번호를 한 번 확인한 사용자는 이후 3시간 동안 다시 확인 요청을 받지 않습니다. 이 유효 시간을 변경하려면 config/auth.php 설정 파일의 password_timeout 값을 수정하면 됩니다.

라우팅

비밀번호 확인 폼

먼저 비밀번호 입력 폼을 보여주는 라우트를 정의합니다.

Route::get('/confirm-password', function () { return view('auth.confirm-password'); })->middleware('auth')->name('password.confirm');

이 라우트가 반환하는 뷰에는 password 필드를 포함한 폼이 있어야 합니다. 또한 사용자가 보안 영역에 접근하려 하므로 비밀번호 확인이 필요하다는 안내 문구를 함께 표시하는 것이 좋습니다.

비밀번호 확인 처리

다음으로, 폼 제출을 처리하는 POST 라우트를 정의합니다. 이 라우트는 비밀번호를 검증하고 사용자를 원래 목적지로 리디렉션하는 역할을 합니다.

use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; Route::post('/confirm-password', function (Request $request) { if (! Hash::check($request->password, $request->user()->password)) { return back()->withErrors([ 'password' => ['입력하신 비밀번호가 일치하지 않습니다.'] ]); } $request->session()->passwordConfirmed(); return redirect()->intended(); })->middleware(['auth', 'throttle:6,1']);

이 라우트의 동작을 단계별로 살펴보겠습니다.

  1. Hash::check()로 입력된 비밀번호가 현재 인증된 사용자의 비밀번호와 일치하는지 확인합니다.
  2. 비밀번호가 유효하면 passwordConfirmed() 메서드를 호출합니다. 이 메서드는 세션에 비밀번호 확인 시각을 기록하여, Laravel이 마지막 확인 시점을 추적할 수 있게 합니다.
  3. 마지막으로 redirect()->intended()로 사용자가 원래 이동하려던 목적지로 리디렉션합니다.

throttle:6,1 미들웨어는 1분 내 최대 6회 요청으로 제한하여 무차별 대입 공격(brute-force)을 방지합니다.

라우트 보호

비밀번호 재확인이 필요한 라우트에는 password.confirm 미들웨어를 지정해야 합니다. 이 미들웨어는 Laravel 기본 설치에 포함되어 있으며, 사용자가 비밀번호를 확인하기 전에 접근하려 했던 목적지 URL을 세션에 자동으로 저장합니다. 비밀번호 확인이 완료되면 저장된 목적지로 자동 리디렉션됩니다. 목적지를 세션에 저장한 후 미들웨어는 사용자를 password.confirm 이름이 지정된 라우트로 리디렉션합니다.

Route::get('/settings', function () { // ... })->middleware(['password.confirm']); Route::post('/settings', function () { // ... })->middleware(['password.confirm']);

커스텀 가드 추가하기

Auth 파사드의 extend 메서드를 사용하면 직접 인증 가드를 정의할 수 있습니다. extend 호출은 서비스 프로바이더 안에 위치해야 합니다. Laravel에는 이미 AppServiceProvider가 포함되어 있으므로, 그곳에 코드를 추가하는 것이 일반적입니다.

<?php namespace App\Providers; use App\Services\Auth\JwtGuard; use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\Facades\Auth; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { // ... /** * 애플리케이션 서비스를 부트스트랩합니다. */ public function boot(): void { Auth::extend('jwt', function (Application $app, string $name, array $config) { // Illuminate\Contracts\Auth\Guard 구현체를 반환합니다... return new JwtGuard(Auth::createUserProvider($config['provider'])); }); } }

위 예시처럼, extend에 전달하는 콜백은 반드시 Illuminate\Contracts\Auth\Guard 인터페이스의 구현체를 반환해야 합니다. 이 인터페이스에는 커스텀 가드를 완성하기 위해 구현해야 할 몇 가지 메서드가 정의되어 있습니다.

커스텀 가드를 정의한 후에는 auth.php 설정 파일의 guards 항목에서 해당 가드를 참조할 수 있습니다.

'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ],

클로저 기반 요청 가드

HTTP 요청 기반의 커스텀 인증을 가장 간단하게 구현하는 방법은 Auth::viaRequest 메서드를 사용하는 것입니다. 클래스를 별도로 만들 필요 없이, 단일 클로저로 인증 로직을 빠르게 정의할 수 있습니다.

AppServiceProviderboot 메서드 안에서 Auth::viaRequest를 호출하면 됩니다. 첫 번째 인수는 인증 드라이버 이름(커스텀 가드를 식별하는 임의의 문자열)이고, 두 번째 인수는 HTTP 요청을 받아 인증된 사용자 인스턴스를 반환하거나, 인증 실패 시 null을 반환하는 클로저입니다.

use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; /** * 애플리케이션 서비스를 부트스트랩합니다. */ public function boot(): void { Auth::viaRequest('custom-token', function (Request $request) { return User::where('token', (string) $request->token)->first(); }); }

커스텀 인증 드라이버를 정의했다면, auth.php 설정 파일의 guards 항목에 드라이버로 등록합니다.

'guards' => [ 'api' => [ 'driver' => 'custom-token', ], ],

이후 라우트에 인증 미들웨어를 적용할 때 해당 가드를 지정하면 됩니다.

Route::middleware('auth:api')->group(function () { // ... });

커스텀 사용자 프로바이더 추가하기

관계형 데이터베이스가 아닌 다른 방식으로 사용자 정보를 저장하고 있다면, 직접 커스텀 인증 사용자 프로바이더를 구현해야 합니다. Auth 파사드의 provider 메서드를 사용하여 커스텀 프로바이더를 등록할 수 있습니다. 이 때 반환되는 객체는 반드시 Illuminate\Contracts\Auth\UserProvider 인터페이스를 구현해야 합니다.

<?php namespace App\Providers; use App\Extensions\MongoUserProvider; use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\Facades\Auth; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { // ... /** * 애플리케이션 서비스를 부트스트랩합니다. */ public function boot(): void { Auth::provider('mongo', function (Application $app, array $config) { // Illuminate\Contracts\Auth\UserProvider 인스턴스를 반환합니다... return new MongoUserProvider($app->make('mongo.connection')); }); } }

프로바이더를 등록했다면, auth.php 설정 파일에서 새 프로바이더를 사용하도록 변경합니다. 먼저 새 드라이버를 사용하는 provider 항목을 정의합니다.

'providers' => [ 'users' => [ 'driver' => 'mongo', ], ],

이후 guards 설정에서 해당 프로바이더를 참조합니다.

'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], ],

UserProvider 컨트랙트

Illuminate\Contracts\Auth\UserProvider 구현체는 MySQL, MongoDB 등 다양한 영속 저장소에서 Illuminate\Contracts\Auth\Authenticatable 구현체를 가져오는 역할을 합니다. 이 두 인터페이스 덕분에 사용자 데이터가 어떤 방식으로 저장되든, 또는 어떤 클래스가 인증된 사용자를 표현하든 관계없이 Laravel의 인증 메커니즘이 일관되게 동작할 수 있습니다.

Illuminate\Contracts\Auth\UserProvider 컨트랙트를 살펴보면 다음과 같습니다.

<?php namespace Illuminate\Contracts\Auth; interface UserProvider { public function retrieveById($identifier); public function retrieveByToken($identifier, $token); public function updateRememberToken(Authenticatable $user, $token); public function retrieveByCredentials(array $credentials); public function validateCredentials(Authenticatable $user, array $credentials); public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false); }

각 메서드의 역할은 다음과 같습니다.

retrieveById MySQL의 자동 증가 기본키처럼 사용자를 식별하는 값을 받아 해당 사용자의 Authenticatable 구현체를 반환합니다.

retrieveByToken 고유한 $identifier와 "로그인 상태 유지(remember me)" 토큰인 $token으로 사용자를 조회합니다. 토큰은 보통 remember_token 컬럼에 저장됩니다. 일치하는 토큰을 가진 Authenticatable 구현체를 반환해야 합니다.

updateRememberToken $user 인스턴스의 remember_token을 새 $token으로 갱신합니다. "로그인 상태 유지" 인증이 성공하거나 사용자가 로그아웃할 때 새 토큰이 발급됩니다.

retrieveByCredentials Auth::attempt 호출 시 전달된 자격증명 배열을 받아 저장소에서 일치하는 사용자를 조회합니다. 일반적으로 $credentials['username'] 값으로 사용자 레코드를 검색하는 쿼리를 실행합니다. Authenticatable 구현체를 반환해야 하며, 이 메서드에서 비밀번호 검증이나 인증을 시도해서는 안 됩니다.

validateCredentials 주어진 $user$credentials를 비교하여 사용자 인증을 검증합니다. 예를 들어, 일반적으로 Hash::check를 사용하여 $user->getAuthPassword()$credentials['password']를 비교합니다. 비밀번호가 유효하면 true, 그렇지 않으면 false를 반환합니다.

rehashPasswordIfRequired 필요하고 지원되는 경우 사용자의 비밀번호를 재해시합니다. 보통 Hash::needsRehash로 재해시 필요 여부를 판단하고, 필요하다면 Hash::make로 비밀번호를 재해시한 뒤 저장소의 사용자 레코드를 업데이트합니다.

Authenticatable 컨트랙트

UserProvider의 각 메서드를 살펴봤으니, 이번에는 Authenticatable 컨트랙트를 확인해 보겠습니다. retrieveById, retrieveByToken, retrieveByCredentials 메서드는 모두 이 인터페이스의 구현체를 반환해야 합니다.

<?php namespace Illuminate\Contracts\Auth; interface Authenticatable { public function getAuthIdentifierName(); public function getAuthIdentifier(); public function getAuthPasswordName(); public function getAuthPassword(); public function getRememberToken(); public function setRememberToken($value); public function getRememberTokenName(); }

인터페이스 자체는 단순합니다.

  • getAuthIdentifierName: 사용자의 기본키 컬럼 이름을 반환합니다.
  • getAuthIdentifier: 사용자의 기본키 값을 반환합니다. MySQL 기반이라면 자동 증가 기본키가 될 것입니다.
  • getAuthPasswordName: 사용자의 비밀번호 컬럼 이름을 반환합니다.
  • getAuthPassword: 사용자의 해시된 비밀번호를 반환합니다.
  • getRememberToken / setRememberToken / getRememberTokenName: "로그인 상태 유지" 토큰의 조회, 설정, 컬럼명을 처리합니다.

이 인터페이스 덕분에 어떤 ORM이나 저장소 추상화 계층을 사용하더라도 인증 시스템이 동일하게 동작합니다. Laravel은 기본적으로 app/Models 디렉터리에 이 인터페이스를 구현한 App\Models\User 클래스를 포함하고 있습니다.

인증

비밀번호 자동 재해싱

Laravel의 기본 비밀번호 해싱 알고리즘은 bcrypt입니다. bcrypt의 "작업 계수(work factor)"는 config/hashing.php 설정 파일이나 BCRYPT_ROUNDS 환경 변수로 조정할 수 있습니다.

CPU·GPU 성능이 향상됨에 따라 bcrypt 작업 계수도 주기적으로 높여주는 것이 좋습니다. 작업 계수를 올리면, 사용자가 스타터 킷 또는 attempt 메서드를 통해 로그인할 때 Laravel이 자동으로 기존 비밀번호를 새 작업 계수로 재해싱합니다.

NOTE

비밀번호 자동 재해싱은 일반적으로 애플리케이션 동작에 영향을 주지 않습니다. 그러나 이 동작이 불필요하다면 아래 방법으로 비활성화할 수 있습니다.

자동 재해싱을 비활성화하려면 먼저 hashing 설정 파일을 퍼블리시합니다:

php artisan config:publish hashing

퍼블리시된 설정 파일에서 rehash_on_login 값을 false로 지정합니다:

'rehash_on_login' => false,

이벤트

Laravel은 인증 과정에서 다양한 이벤트를 발생시킵니다. 아래 이벤트들에 대해 리스너를 등록하면 로그인, 로그아웃, 잠금 등 인증 흐름의 각 단계에 원하는 로직을 추가할 수 있습니다.

이벤트 이름
Illuminate\Auth\Events\Registered
Illuminate\Auth\Events\Attempting
Illuminate\Auth\Events\Authenticated
Illuminate\Auth\Events\Login
Illuminate\Auth\Events\Failed
Illuminate\Auth\Events\Validated
Illuminate\Auth\Events\Verified
Illuminate\Auth\Events\Logout
Illuminate\Auth\Events\CurrentDeviceLogout
Illuminate\Auth\Events\OtherDeviceLogout
Illuminate\Auth\Events\Lockout
Illuminate\Auth\Events\PasswordReset
Illuminate\Auth\Events\PasswordResetLinkSent

NOTE

예를 들어 회원 가입 후 환영 이메일을 보내고 싶다면 Registered 이벤트에 리스너를 연결하고, 로그인 실패 횟수를 별도로 기록하고 싶다면 Failed 이벤트를 활용하세요. 이벤트 기반으로 인증 부가 기능을 구현하면 핵심 인증 로직을 수정하지 않아도 됩니다.

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

번역일: 2026년 7월 28일