Laravel의 Middleware는 애플리케이션으로 들어온 HTTP요청을 처리하는 과정 중에 요청을 필터링하는데에 사용할 수 있는 기능이다. 실제 web서버의 처리과정 전후에 처리할 로직을 미들웨어에 정의함으로써 생성자나 메서드 하나하나마다 공통 처리를 정의하지 않도록 해준다.
Laravel에서의 Middleware은 아래의 artisan 명령어를 통해서 추가할 수 있으며, app\Http\Middleware 하위에서 관리된다.
php artisan make:middleware SampleMiddleware
생성된 middleware파일
<?php
namespace App\Http\Middleware;
use Closure;
class SampleMiddleware
{
public function handle($request, Closure $next)
{
// 전처리를 위한 코드 작성
// 전처리만을 위한 코드라면 return $next($request);를 작성
$response = $next($request);
// 후처리를 위한 코드 작성
return $response;
}
}
등록된 Middleware의 handle메서드 안에서 전・후처리의 로직을 작성할 수 있다.
각각의 처리 과정에서 아래와 같은 기능을 Middleware에 등록하고 사용하면 좋을 것 같다.
전처리 : 인증 및 권한부여, 유효성 검사, 보안 관련 처리, 언어 및 지역 설정
후처리 : HTTP 헤더 설정, 예외 처리, 성능 모니터링
공통 : 로그 기록, 캐싱(캐시 저장), API호출, 데이터 가공
단순히 Middleware를 등록하는 것만으로 필터링이 되는 것이 아니며, 만들어진 Middleware를 등록하고 각각의 위치에 적용하는 과정이 필요하다.
우선 app/Http/Kernel.php의 $routeMiddleware에 작성한 Middleware의 클래스와 실제 사용시 필요한 키를 지정한다.
protected $routeMiddleware = [
'first' => \App\Http\Middleware\Authenticate::class,
'second' => \Illuminate\Auth\Middleware\Authorize::class,
];
동일 파일에서 다수의 Middleware를 $middlewareGroups을 통해 하나의 그룹으로 묶어서 관리할 수도 있다. 특히 web, api의 그룹은 각 라우터에 해당하는 HTTP요청에 자동으로 적용한다.
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
],
'api' => [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
등록된 Middleware는 $middlewarePriority를 통해 실행 우선순위를 정할 수 있다.
protected $middlewarePriority = [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
지정 후 아래와 같이 사용이 가능하다.
// 하나의 Middleware 지정 ※ 그룹도 동일하게 키를 사용
Route::get('/profile', function () {})
->middleware('first');
// 여러 Middleware 지정
Route::get('/profile', function () {})
->middleware(['first', 'second']);
// use키워드를 활용한 클래스 직접 지정
use App\Http\Middleware\EnsureTokenIsValid;
Route::get('/profile', function () {})
->middleware(EnsureTokenIsValid::class);
// Middleware처리에 인자를 넘길때
// public function handle($request, Closure $next, $p1, $p2)의 경우
Route::put('/post/{id}', function ($id) {
//
})->middleware('role:p1value,p2value'); // p1, p2에 각 value가 할당
// 그룹으로 묶어서 관리시 특정 HTTP요청에 한해서 Middleware 제외
Route::middleware([EnsureTokenIsValid::class])->group(function () {
Route::get('/', function () {});
Route::get('/profile', function () {})
->withoutMiddleware([EnsureTokenIsValid::class]);
});
// 전체 그룹에 특정 Middleware 제외
Route::withoutMiddleware([EnsureTokenIsValid::class])->group(function () {
Route::get('/profile', function () {
//
});
});