세상의 모든 지식

Laravel Middleware 정의와 사용법 본문

Web/PHP & Laravel

Laravel Middleware 정의와 사용법

JuniorEinstein 2018. 2. 26. 22:19
728x90

오늘 여러가지로 라라벨을 만지다가 문뜩 Middleware에 대한 글을 써봐야겠다고 생각했다.


라라벨 공식 Docs : https://laravel.com/docs/5.6/middleware


미들웨어란?

미들웨어어플리케이션에 들어오는 HTTP 요청들을 필터링하는 데에 사용된다. 예를 들면 로그인에 관련된 처리가 있다. 어떤 사람이 로그인이 된 채로 HTTP 요청을 보내면 문제없이 접속할 수 없지만, 로그인이 되어 있지 않은 요청이 온다면 Middleware는 로그인 페이지로 리다이렉션하는 작업을 수행할 수 있다.


라라벨에서 생성한 미들웨어는 app/Http/Middleware 에 위치된다.


<미들웨어의 작동 플로우>


미들웨어는 두 가지 방향으로 활용할 수 있다.


하나는 HTTP 요청이 컨트롤러에 전달되기 전에 작업을 수행하는 것이고,

1
2
3
4
5
6
7
8
9
10
11
<?php
class CustomMiddleware
{
    public function handle($request, Closure $next)
    {
        // 여기에 있는 작업들은 요청이 컨트롤러에 전달되기 전에 수행된다.
 
        return $next($request);
    }
}
 
cs


다른 한 가지는 HTTP 요청이 컨트롤러에 전달된 후에 작동시키는 경우이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class CustomMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
 
        // 여기에 있는 작업들은 HTTP 요청이 컨트롤러에 전달된 후에 작동한다.
 
        return $response;
    }
}
 
cs



나도 미들웨어를 사용하기 시작한지 얼마 안됐다. 예전에는 모든 Controller가 상속받는 상위 Controller 클래스에 protected로 메소드를 만들어서 사용했다.


주로 사용했던 매소드는 사용자의 로그인 여부를 파악하고, 로그인이 되어 있지 않으면 로그인 창으로 redirect 시키는 매소드였다. 그러다 보니까 로그인이 안 되어 있을 때 사용자를 로그인 창으로 리다이렉트 시키는 매소드를 매번 컨트롤러에 적어 주어야 했고, 수정하기에도 불편한 점이 많았다.


미들웨어를 사용하면서 라우팅 단계에서 요청이 가기 전에 요청에 대한 처리를 하고 넘어가는 과정을 통해 위의 번거로움을 대거 해결한 것 같아서 공유하고자 한다.


말로만 설명하면 이해가 안되니, 기존의 코드를 보면서 이해해보자.


<기존의 방식>


1. routes/web.php

(라우터)

1
2
3
4
5
6
7
<?php
 
// routes/web.php
// 미들웨어를 사용하지 않은 기존의 라우팅 방식
Route::redirect('/''HomeController@index');
 
 
cs
d

2. app/Http/Controllers/Controller.php

(부모 컨트롤러, 모든 컨트롤러가 상속하는 클래스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
 
// app/Http/Controllers/Controller.php
namespace App\Http\Controllers;

class Controller extends BaseController
{
    protected function redirectLogin()
    {
        if(session('logged_in'=== false) {
            return Redirect::to('login')->send();
        }
    }
}
 
 
cs
2

3. app/Http/Controllers/HomeController.php

(사용자가 만든 컨트롤러, 모든 컨트롤러는 부모 컨트롤러 App\Http\Controllers\Controller을 상속받는다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
 
// app/Http/Controllers/HomeController.php
namespace App\Http\Controllers;
 
class HomeController extends Controller
{
    public function index()
    {
        $this->redirectLogin();
        return view('main');
    }
}
 
 
cs


이렇게 되면 만약 컨트롤러에서 index() 이외에 다른 매소드에서도 로그인이 되어 있지 않을 때 리다이렉션을 하고 싶다면, 각가의 메소드에 모두 "$this->redirectLogin()"을 적어 주어야 한다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
 
// app/Http/Controllers/HomeController.php
namespace App\Http\Controllers;
 
class HomeController extends Controller
{
    public function index()
    {
        // 모든 매소드마다 $this->redirectLogin(); 을 써주어야 한다.
        $this->redirectLogin();
        return view('main');
    }
 
    public function board()
    {
        // 모든 매소드마다 $this->redirectLogin(); 을 써주어야 한다.
        $this->redirectLogin();
        return view('board');
    }
 
    public function show()
    {
        // 모든 매소드마다 $this->redirectLogin(); 을 써주어야 한다.
        $this->redirectLogin();
        return view('show');
    }
}
 
cs


이렇게 되면 코드를 관리하기에 굉장히 까다로워진다.


1
2
3
4
5
6
7
<?php
 
public function __construct()
{
    $this->redirectLogin();
}
 
cs

을 사용하는 경우에도 마찬가지이다.


다른 컨트롤러에서도 로그인이 안되어 있을 때 리다이렉션을 하고 싶다면 모든 컨트롤러의 상단에 생성자를 써 주어야 하는 불편함이 있다.



반면,

<미들웨어를 사용한 방식>


0. 우선 Artisan CLI을 통해 미들웨어를 생성한다.

1
php artisan make:middleware LoginMiddleware
cs

생성된 미들웨어는 app/Http/Middleware에 위치한다.


1. app/Http/Middleware/LoginMiddleware

Artisan을 통해 생성한 미들웨어이다. 로그인 되지 않은 사용자를 로그인페이지로 이동시키는 작업을 수행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
 
namespace App\Http\Middleware;
 
use Closure;
 
class LoginMiddleware
{
    public function handle($request, Closure $next)
    {
        // 만약 로그인이 되어 있지 않다면 로그인 페이지로 이동한다.
        if(session('logged_in'=== false) {
            return redirect('/login');
        }
 
        return $next($request);
    }
}
 
cs



2. app/Http/Kernel.php

만든 미들웨어는 커널에 반드시 등록해야 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
 
namespace App\Http;
 
use Illuminate\Foundation\Http\Kernel as HttpKernel;
 
class Kernel extends HttpKernel
{
    // global middleware. 어플리케이션에 들어오는 모든 HTTP 요청에 적용된다.
    protected $middleware = [
        \Illuminate\Foundation\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,
    ];
 
    // 같이 사용되는 미들웨어를 그룹지어 놓은 것이다.
    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',
        ],
    ];
 
    // 어플리케이션 라우팅에 사용되는 미들웨어다. 여기에 우리가 만든 미들웨어를 등록(Register)해 주어야 한다.
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\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,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        // 아래와 같이 우리가 만든 미들웨어를 등록해 준다.
        // '미들웨어의 이름' => 우리가 만든 미들웨어 클래스
        // 로 등록한다.
        'login' => \App\Http\Middleware\LoginMiddleware::class,
    ];
}
 
cs


3. routes/web.php

(라우터)

1
2
3
4
5
6
7
8
9
10
<?php
 
// 우리가 등록한 미들웨어의 이름으로 미들웨어를 사용할 수 있다.
Route::get('/''HomeController@index')->middleware('login');
 
// 아니면 라우팅 그룹으로 미들웨어를 사용할 수 있다.
Route::middleware(['login'])->group(function() {
    Route::get('/board''HomeController@board');
    Route::get('/show''HomeController@show');
});
cs


4. app/Http/Controllers/Controller

이 방식은 부모 컨트롤러에 아무런 코드도 추가하지 않아도 된다.


5. app/Http/Controllers/HomeController

이전 방식과 다르게 이제는 아무런 조치도 취하지 않아도 로그인된 사용자만 넘어온다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
 
// app/Http/Controllers/HomeController.php
namespace App\Http\Controllers;
 
class HomeController extends Controller
{
    public function index()
    {
        // 모든 매소드마다 로그인되지 않았을 때의 리다이렉션 코드가 없다.
        // 컨트롤러를 거치기 전에 미들웨어에서 모두 처리되기 때문이다.
        return view('main');
    }
 
    public function board()
    {
        return view('board');
    }
 
    public function show()
    {
        return view('show');
    }
}
 
cs


728x90
Comments