[Laravel 기본] 9. Middleware

Middleware

컴퓨터 관점에서 미들웨어

일반적으로 Middleware 라는 용어는 Application 과 OS (운영체제) 사이에 존재하는 컴퓨터 소프트웨어 (software glue) 라고 불립니다. 이 미들웨어는 둘 사이의 연결 역할을 하면서 중간에서 특정한 기능을 수행합니다.

어플리케이션 관점에서 미들웨어

어플리케이션 내부에서도 같은 의미로 미들웨어가 사용됩니다. 어플리케이션은 요청에 알맞은 처리를 진행한 후 응답을 하는 일을 합니다. 미들웨어는 이 요청과 응답 사이에 존재하여 특정한 기능을 수행합니다. 요청을 통과시켜 응답을 얻는다라는 개념도 틀린 말이 아닙니다. ( 스프링에서 AOP, Filter, intercept 개념과 비슷하다고 보시면 됩니다. )

Laravel Middleware

라라벨에서도 위와 같이 어플리케이션 미들웨어를 제공합니다. 어플리케이션 관점에서 미들웨어의 제일 쉬운 예제로 사용자 인증을 들 수 있겠습니다. 보통 웹 어플리케이션에서 사용자 정보 페이지를 요청하는 경우에 인증 미들웨어를 통과시켜 성공하는 경우 사용자 정보 페이지를 응답, 실패하는 경우 로그인 페이지로 리다이렉트하는 개념으로 사용됩니다.

사용자 인증에서 미들웨어 사용

미들웨어 정의하기

지금부터는 미들웨어를 직접 만들어 사용해보겠습니다. 앞선 포스팅에서 Service Provider 생성한 것처럼 Laravel Artisan 를 이용해 커맨드 명령어로 생성하겠습니다.

php artisan make:middleware LogUserAccess
app/Http/middleware 디렉토리에 생성 된다.

app/Http/middleware 디렉토리 아래에는 이미 라라벨에서 구현해놓은 미들웨어들이 존재합니다. 인증, 쿠키, CSRF Token 관련된 미들웨어들이 존재합니다.

app/Http/middleware/LogUserAccess.php 파일을 열어보겠습니다.

<?php

namespace App\Http\Middleware;

use Closure;

class LogUserAccess
{
    public function handle($request, Closure $next)
    {
        // 미들웨어 중간 기능
        // Request를 탈취??하여 사용자 접속 로그를 남김..
        // ... //
        
        return $next($request);
    }
}

미들웨어는 구현이 단순합니다. Request 를 사용하여 해당 작업을 수행 후 Closure인 $next($request) 를 리턴합니다. 도중에 Request 를 탈취하여 사용한 뒤 그대로 반환 한다는 의미입니다.

모든 작업을 수행한 뒤에 미들웨어를 통과시키는 코드도 가능합니다. 이런 경우에는 Closure 작업을 마친 후에 해당 미들웨어 동작을 수행할 것입니다.

    public function handle($request, Closure $next)
    {
        // Closure 의 다른 작업을 마친 결과를 받아
        $response = $next($request);

        // 사용자 로그를 남김
        return $response;
    }

미들웨어 등록하기

미들웨어를 작성하였다면 Application에 등록하는 작업을 수행하여야합니다. app/Http/Kernel.app 에 등록하면 됩니다.

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    // Global Middleware 
    protected $middleware = [
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
    ];
    // Grouped Middleware
    // Route 디렉토리에선 다음과 같이 사용된다. 
    // Route::get('/', function () {})->middleware('web');
    // Route::group(['middleware' => ['web']], function () {});
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];
    // Route Middleware
    // Route 디렉토리에서 다음과 같이 사용 된다.
    // Route::get('/', function () {})->middleware('first', 'second');
    protected $routeMiddleware = [
        '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,
    ];
    
    // Define Middleware Priority
    protected $middlewarePriority = [
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\Authenticate::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];
}
  • $middleware => 전역으로 사용되는 미들웨어를 등록합니다.
  • $middlewareGroups => 그룹으로 미들웨어를 묶어서 사용합니다.
  • $routeMiddleware => 라우트에서 사용될 미들웨어를 정의합니다.
  • $middlewarePriority => 미들웨어의 순서를 정의합니다.

작성하는 미들웨어 기능에 맞게 등록하면 됩니다.

TL;DR

  • 라라벨에서 미들웨어는 요청을 탈취하여 정의한 기능을 수행한 뒤 응답을 돌려준다. (통과의 개념)
  • 라라벨에서는 인증, 쿠키, CRSF 토큰 관련 미들웨어들이 구현되어 있다.
  • middleware를 정의한 뒤 app/Http/Kernel.php 에 기능에 맞는 미들웨어 등록 단계를 거친다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다