본문 바로가기

미들웨어

번역일: 2026년 6월 20일

미들웨어

소개

미들웨어는 애플리케이션에 들어오는 HTTP 요청을 검사하고 필터링하는 편리한 메커니즘입니다. 예를 들어, Laravel에는 사용자가 인증되었는지 확인하는 미들웨어가 기본으로 포함되어 있습니다. 인증되지 않은 사용자라면 로그인 화면으로 리다이렉트하고, 인증된 사용자라면 요청을 그대로 애플리케이션 내부로 통과시킵니다.

인증 외에도 다양한 목적의 미들웨어를 직접 작성할 수 있습니다. 예를 들어, 요청 로깅 미들웨어는 애플리케이션에 들어오는 모든 요청을 기록할 수 있습니다. Laravel 프레임워크에는 인증, CSRF 보호 등 여러 미들웨어가 기본으로 포함되어 있으며, 이들은 모두 app/Http/Middleware 디렉터리에 위치합니다.

미들웨어는 HTTP 요청이 애플리케이션에 도달하기 전에 통과해야 하는 일련의 "관문(레이어)"이라고 생각하면 이해하기 쉽습니다. 각 레이어는 요청을 검사하고, 필요에 따라 요청을 거부하거나 다음 단계로 전달합니다.

미들웨어 정의하기

새 미들웨어를 생성하려면 make:middleware Artisan 명령어를 사용합니다:

php artisan make:middleware EnsureTokenIsValid

이 명령어를 실행하면 app/Http/Middleware 디렉터리에 EnsureTokenIsValid 클래스가 생성됩니다. 아래 예시에서는 요청에 포함된 token 값이 지정된 값과 일치할 때만 라우트 접근을 허용하고, 그렇지 않으면 home URI로 리다이렉트합니다:

<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class EnsureTokenIsValid { /** * 들어오는 요청을 처리합니다. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { if ($request->input('token') !== 'my-secret-token') { return redirect('home'); } return $next($request); } }

token이 일치하지 않으면 클라이언트에게 리다이렉트 응답을 반환하고, 일치하면 $next($request)를 호출하여 요청을 애플리케이션 내부로 전달합니다. $next 콜백은 요청을 다음 미들웨어(또는 최종 핸들러)로 "통과"시키는 역할을 합니다.

NOTE

모든 미들웨어는 서비스 컨테이너를 통해 resolve됩니다. 따라서 미들웨어의 생성자에서 필요한 의존성을 타입 힌트로 선언하면 자동으로 주입받을 수 있습니다.

요청 처리 전후 작업

미들웨어는 요청이 애플리케이션에 전달되기 또는 에 작업을 수행할 수 있습니다.

다음 미들웨어는 요청이 처리되기 에 작업을 수행합니다:

<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class BeforeMiddleware { public function handle(Request $request, Closure $next): Response { // 요청 처리 전 작업 수행 return $next($request); } }

반면, 다음 미들웨어는 요청이 처리된 에 작업을 수행합니다:

<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class AfterMiddleware { public function handle(Request $request, Closure $next): Response { $response = $next($request); // 응답 반환 전 작업 수행 return $response; } }

두 패턴의 차이는 $next($request) 호출 위치에 있습니다. 호출 전에 로직을 작성하면 "전처리", 호출 후에 작성하면 "후처리"가 됩니다.

미들웨어 등록하기

전역 미들웨어

애플리케이션의 모든 HTTP 요청에 대해 실행되어야 하는 미들웨어는 app/Http/Kernel.php 파일의 $middleware 속성에 추가합니다.

라우트에 미들웨어 지정하기

특정 라우트에만 미들웨어를 적용하려면 라우트 정의 시 middleware 메서드를 체이닝합니다:

use App\Http\Middleware\Authenticate; Route::get('/profile', function () { // ... })->middleware(Authenticate::class);

배열을 전달하면 여러 미들웨어를 한 번에 지정할 수 있습니다:

Route::get('/', function () { // ... })->middleware([First::class, Second::class]);

매번 전체 클래스명을 사용하는 대신, app/Http/Kernel.php$middlewareAliases 속성에 별칭을 등록하면 더 간결하게 사용할 수 있습니다. Laravel이 기본 제공하는 미들웨어들도 이미 이 목록에 등록되어 있습니다:

// App\Http\Kernel 클래스 내부... protected $middlewareAliases = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, ];

별칭을 등록한 뒤에는 라우트에서 간결하게 사용할 수 있습니다:

Route::get('/profile', function () { // ... })->middleware('auth');

특정 라우트에서 미들웨어 제외하기

라우트 그룹에 미들웨어를 적용했을 때, 그룹 내 특정 라우트에서만 해당 미들웨어를 제외하고 싶다면 withoutMiddleware 메서드를 사용합니다:

use App\Http\Middleware\EnsureTokenIsValid; Route::middleware([EnsureTokenIsValid::class])->group(function () { Route::get('/', function () { // ... }); Route::get('/profile', function () { // ... })->withoutMiddleware([EnsureTokenIsValid::class]); });

라우트 그룹 전체에서 특정 미들웨어를 제외할 수도 있습니다:

use App\Http\Middleware\EnsureTokenIsValid; Route::withoutMiddleware([EnsureTokenIsValid::class])->group(function () { Route::get('/profile', function () { // ... }); });

NOTE

withoutMiddleware 메서드는 라우트에 직접 지정된 미들웨어만 제거할 수 있으며, 전역 미들웨어에는 적용되지 않습니다.

미들웨어 그룹

여러 미들웨어를 하나의 키로 묶어서 라우트에 편리하게 지정하고 싶다면, HTTP 커널의 $middlewareGroups 속성을 활용하세요.

Laravel은 웹 라우트와 API 라우트에 공통적으로 적용할 미들웨어를 묶은 webapi 그룹을 기본으로 제공합니다. 이 두 그룹은 App\Providers\RouteServiceProvider에 의해 각각 routes/web.phproutes/api.php 파일의 라우트에 자동으로 적용됩니다:

/** * 애플리케이션의 라우트 미들웨어 그룹 * * @var array */ protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];

미들웨어 그룹은 개별 미들웨어와 동일한 방식으로 라우트에 지정할 수 있습니다:

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

NOTE

webapi 미들웨어 그룹은 App\Providers\RouteServiceProvider에 의해 routes/web.phproutes/api.php 파일에 자동으로 적용됩니다. 별도로 지정하지 않아도 됩니다.

미들웨어 실행 순서 지정

미들웨어는 라우트에 지정된 순서대로 실행되는 것이 기본이지만, 지정 순서와 무관하게 실행 순서를 강제해야 할 때가 있습니다. 이런 경우 app/Http/Kernel.php$middlewarePriority 속성을 사용합니다. 이 속성이 파일에 없다면 아래 기본값을 직접 추가하면 됩니다:

/** * 우선순위가 지정된 미들웨어 목록 * * 전역 미들웨어가 아닌 경우, 이 목록의 순서대로 실행이 강제됩니다. * * @var string[] */ protected $middlewarePriority = [ \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, \Illuminate\Cookie\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class, \Illuminate\Routing\Middleware\ThrottleRequests::class, \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class, \Illuminate\Contracts\Session\Middleware\AuthenticatesSessions::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Auth\Middleware\Authorize::class, ];

미들웨어 파라미터

미들웨어는 추가 파라미터를 받을 수 있습니다. 예를 들어, 특정 액션을 수행하기 전에 인증된 사용자가 특정 "역할(role)"을 가지고 있는지 확인해야 한다면, 역할 이름을 파라미터로 받는 EnsureUserHasRole 미들웨어를 만들 수 있습니다.

추가 파라미터는 $next 인수 다음에 선언합니다:

<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class EnsureUserHasRole { /** * 들어오는 요청을 처리합니다. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next, string $role): Response { if (! $request->user()->hasRole($role)) { // 리다이렉트... } return $next($request); } }

라우트 정의 시 미들웨어 이름 뒤에 :으로 구분하여 파라미터를 전달합니다:

Route::put('/post/{id}', function (string $id) { // ... })->middleware('role:editor');

파라미터가 여러 개라면 쉼표로 구분합니다:

Route::put('/post/{id}', function (string $id) { // ... })->middleware('role:editor,publisher');

종료 가능한 미들웨어(Terminable Middleware)

HTTP 응답이 브라우저로 전송된 이후에 작업을 수행해야 하는 경우가 있습니다. 미들웨어에 terminate 메서드를 정의하고, 웹 서버가 FastCGI를 사용하고 있다면 응답 전송 후 terminate 메서드가 자동으로 호출됩니다:

<?php namespace Illuminate\Session\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class TerminatingMiddleware { /** * 들어오는 요청을 처리합니다. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { return $next($request); } /** * 응답이 브라우저에 전송된 후 처리할 작업을 수행합니다. */ public function terminate(Request $request, Response $response): void { // ... } }

terminate 메서드는 요청($request)과 응답($response) 객체를 모두 전달받습니다. 종료 가능한 미들웨어를 정의한 후에는 app/Http/Kernel.php 파일의 전역 미들웨어 또는 라우트 미들웨어 목록에 등록해야 합니다.

Laravel은 terminate 메서드를 호출할 때 서비스 컨테이너에서 미들웨어의 새 인스턴스를 resolve합니다. handleterminate가 동일한 인스턴스를 공유해야 한다면, 컨테이너에 싱글톤으로 등록하세요. 일반적으로 AppServiceProviderregister 메서드에서 처리합니다:

use App\Http\Middleware\TerminatingMiddleware; /** * 애플리케이션 서비스를 등록합니다. */ public function register(): void { $this->app->singleton(TerminatingMiddleware::class); }

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

번역일: 2026년 6월 20일