
PHP ์จ๋ผ์ธ ๊ฐ์
>PHP - ๊ณ ๊ธ
๐ PHP ๊ณ ๊ธ - 3์ฃผ์ฐจ: ์ธ์ฆ ๋ฐ ๊ถํ ๊ด๋ฆฌ (ํ๋ ์์ํฌ) - 02 ๋ฏธ๋ค์จ์ด(Middleware)๋ฅผ ์ด์ฉํ ์ ๊ทผ ์ ์ด
![]() |
ํ์ | 10.0 | ๋ผ์ด์ผ์ค | free |
---|---|---|---|---|
์ฌ์ฉ์ํ์ | 10.0 | ์ด์์ฒด์ | ||
๋ค์ด๋ก๋ | 1 | ํ์ผํฌ๊ธฐ | 0 | |
์ ์์ฌ | LUZENSOFT | ๋ฑ๋ก์ผ | 2025-09-14 14:11:16 | |
์กฐํ์ | 2 |
๋ฏธ๋ค์จ์ด(Middleware)๋ ๋ฌด์์ธ๊ฐ?
#๋ฏธ๋ค์จ์ด (Middleware)๋ #์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์ฒญ(Request)์ด ๋ผ์ฐํธ์ ๋๋ฌํ๊ธฐ ์ ์ด๋ ์๋ต(Response)์ด ์ฌ์ฉ์์๊ฒ ์ ๋ฌ๋๊ธฐ ์ ์ ์คํ๋๋ ์ฝ๋ ๊ณ์ธต์ ์๋ฏธํฉ๋๋ค. ์ด๋ ์ฃผ๋ก ์์ฒญ๊ณผ ์๋ต์ #ํํฐ๋ง ํ๊ฑฐ๋, ํน์ ์์ ์ ์ํํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ์ ํต์ฌ ๋ก์ง๊ณผ ๋ถ๋ฆฌํ์ฌ #ํก๋จ ๊ด์ฌ์ฌ (Cross-cutting Concerns)๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ธ์ฆ ๊ฒ์ฌ, ๋ก๊น , #CORS (Cross-Origin Resource Sharing) ํค๋ ์ถ๊ฐ ๋ฑ์ด ๋ฏธ๋ค์จ์ด์ ๋ํ์ ์ธ ์ญํ ์ ๋๋ค.
๋ฏธ๋ค์จ์ด๋ฅผ ์ด์ฉํ ์ ๊ทผ ์ ์ด์ ํ์์ฑ
์ ํ๋ฆฌ์ผ์ด์
์์ ๋ชจ๋ ๋ผ์ฐํธ๋ ์ปจํธ๋กค๋ฌ์ ์ง์ ์ ๊ทผ ์ ์ด ๋ก์ง์ ๊ตฌํํ๋ ๊ฒ์ ๋นํจ์จ์ ์ด๋ฉฐ ์ฝ๋ ์ค๋ณต์ ์ผ๊ธฐํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๊ด๋ฆฌ์๋ง ์ ๊ทผํ ์ ์๋ ํ์ด์ง๊ฐ ์ฌ๋ฌ ๊ฐ ์์ ๋, ๊ฐ ํ์ด์ง๋ง๋ค if (user_is_admin()) { ... }
์ ๊ฐ์ ์ฝ๋๋ฅผ ๋ฐ๋ณตํด์ ์์ฑํด์ผ ํฉ๋๋ค. ๋ฏธ๋ค์จ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ #์ ๊ทผ ์ ์ด ๋ก์ง์ ํ ๊ณณ์ ์ง์ค์์ผ ๊ด๋ฆฌํ ์ ์์ผ๋ฉฐ, ์ฝ๋์ #์ฌ์ฌ์ฉ์ฑ ์ ๋์ด๊ณ #์ ์ง๋ณด์ ๋ฅผ ์ฉ์ดํ๊ฒ ๋ง๋ญ๋๋ค.
Laravel์์ ๋ฏธ๋ค์จ์ด ๊ตฌํ ๋ฐ ํ์ฉ
#Laravel ์์๋ ๋ฏธ๋ค์จ์ด๋ฅผ ๋งค์ฐ ์ง๊ด์ ์ผ๋ก ๊ตฌํํ๊ณ ์ฌ์ฉํ ์ ์์ต๋๋ค.
#๋ฏธ๋ค์จ์ด ์์ฑ
PHP
php artisan make:middleware AdminMiddleware
์ด ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด
app/Http/Middleware/AdminMiddleware.php
ํ์ผ์ด ์์ฑ๋ฉ๋๋ค.<br>
PHP
<?php namespace AppHttpMiddleware; use Closure; use IlluminateHttpRequest; use SymfonyComponentHttpFoundationResponse; class AdminMiddleware { /** * Handle an incoming request. * * @param Closure(IlluminateHttpRequest): (SymfonyComponentHttpFoundationResponse) $next */ public function handle(Request $request, Closure $next): Response { if (!auth()->check() || !auth()->user()->isAdmin()) { return redirect('/home')->with('error', '๊ด๋ฆฌ์๋ง ์ ๊ทผํ ์ ์์ต๋๋ค.'); } return $next($request); } }
handle
๋ฉ์๋์์ ์์ฒญ์ด ๋ค์ ๋ฏธ๋ค์จ์ด ๋๋ ๋ผ์ฐํธ ํธ๋ค๋ฌ๋ก ์งํ๋๊ธฐ ์ ์ ๋ก์ง์ ์ํํฉ๋๋ค. ์ฌ๊ธฐ์๋ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ๋์ด ์๊ณ ๊ด๋ฆฌ์์ธ์ง ํ์ธํ๋ฉฐ, ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ฆฌ๋ค์ด๋ ์ ํฉ๋๋ค.#๋ฏธ๋ค์จ์ด ๋ฑ๋ก
app/Http/Kernel.php
ํ์ผ์ ๋ฏธ๋ค์จ์ด๋ฅผ ๋ฑ๋กํด์ผ ํฉ๋๋ค.PHP
protected $routeMiddleware = [ // ... 'admin' => AppHttpMiddlewareAdminMiddleware::class, ];
๋ฏธ๋ค์จ์ด ์ ์ฉ
๋ผ์ฐํธ์ ๋ฏธ๋ค์จ์ด๋ฅผ ์ ์ฉํฉ๋๋ค.
PHP
Route::middleware(['auth', 'admin'])->group(function () { Route::get('/admin/dashboard', function () { // ๊ด๋ฆฌ์ ๋์๋ณด๋ }); });
์ ์์์์๋
auth
๋ฏธ๋ค์จ์ด(๋ก๊ทธ์ธ ์ฌ๋ถ ํ์ธ)์admin
๋ฏธ๋ค์จ์ด(๊ด๋ฆฌ์ ์ฌ๋ถ ํ์ธ)๋ฅผ ๋์์ ์ ์ฉํ์ฌ, ๋ก๊ทธ์ธ๋ ๊ด๋ฆฌ์๋ง/admin/dashboard
๊ฒฝ๋ก์ ์ ๊ทผํ ์ ์๋๋ก ํฉ๋๋ค.
Symfony์์ ๋ฏธ๋ค์จ์ด(Event Listener)๋ฅผ ์ด์ฉํ ์ ๊ทผ ์ ์ด
#Symfony ์์๋ ๋ฏธ๋ค์จ์ด๋ผ๋ ์ฉ์ด ๋์ #Event #Listener ๋ #Event #Subscriber ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฌํ ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค. Symfony์ #์ด๋ฒคํธ ๋์คํจ์ฒ (Event Dispatcher) ์์คํ ์ ํ์ฉํ์ฌ ์์ฒญ ์ฒ๋ฆฌ ๊ณผ์ ์ค ํน์ ์์ ์ ์ฝ๋๋ฅผ ์คํํ ์ ์์ต๋๋ค.
#์ด๋ฒคํธ ๋ฆฌ์ค๋ ์์ฑ
src/EventSubscriber/AccessDeniedSubscriber.php
ํ์ผ์ ์์ฑํฉ๋๋ค.PHP
<?php namespace AppEventSubscriber; use SymfonyComponentEventDispatcherEventSubscriberInterface; use SymfonyComponentHttpKernelEventRequestEvent; use SymfonyComponentHttpKernelKernelEvents; use SymfonyComponentSecurityCoreSecurity; use SymfonyComponentHttpFoundationRedirectResponse; use SymfonyComponentRoutingRouterInterface; class AccessDeniedSubscriber implements EventSubscriberInterface { private $security; private $router; public function __construct(Security $security, RouterInterface $router) { $this->security = $security; $this->router = $router; } public static function getSubscribedEvents() { return [ KernelEvents::REQUEST => ['onKernelRequest', 10], ]; } public function onKernelRequest(RequestEvent $event) { $request = $event->getRequest(); $route = $request->attributes->get('_route'); // ์์: /admin ๊ฒฝ๋ก์ ๋ํ ์ ๊ทผ ์ ์ด if (str_starts_with($route, 'admin_') && !$this->security->isGranted('ROLE_ADMIN')) { $event->setResponse(new RedirectResponse($this->router->generate('app_home'))); } } }
์ด ๋ฆฌ์ค๋๋
KernelEvents::REQUEST
์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๋ ์คํ๋๋ฉฐ, ์์ฒญ๋ ๋ผ์ฐํธ๊ฐadmin_
์ผ๋ก ์์ํ๊ณ ์ฌ์ฉ์๊ฐROLE_ADMIN
์ญํ ์ ๊ฐ์ง๊ณ ์์ง ์๋ค๋ฉด ํ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ์ ํฉ๋๋ค.์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ๋ก (์๋ ๋ฑ๋ก)
Symfony 4.x ์ด์์์๋ ์๋น์ค ์ปจํ ์ด๋์ ์ ์๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์๋์ผ๋ก ๋ฑ๋ก๋ฉ๋๋ค. ๋ณ๋์ ์ค์ ์์ด ์๋น์ค์ ์ฃผ์ ๋ ํ ์๋์ผ๋ก ์๋ํฉ๋๋ค.
์ ๊ทผ ์ ์ด ์ค์
#Security ์ปดํฌ๋ํธ์
security.yaml
ํ์ผ์ ํตํด ๋์ฑ ์ ์ธ์ ์ผ๋ก ์ ๊ทผ ์ ์ด๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.YAML
# config/packages/security.yaml security: # ... access_control: - { path: ^/admin, roles: ROLE_ADMIN } - { path: ^/profile, roles: ROLE_USER }
์ ์ค์ ์
/admin
์ผ๋ก ์์ํ๋ ๋ชจ๋ ๊ฒฝ๋ก์ ๋ํดROLE_ADMIN
์ญํ ์ด ํ์ํ๋ฉฐ,/profile
๋ก ์์ํ๋ ๊ฒฝ๋ก์๋ROLE_USER
์ญํ ์ด ํ์ํจ์ ์๋ฏธํฉ๋๋ค.
๋ฏธ๋ค์จ์ด/์ด๋ฒคํธ ๋ฆฌ์ค๋ ํ์ฉ ์ ๊ณ ๋ ค์ฌํญ
#์์: ์ฌ๋ฌ ๋ฏธ๋ค์จ์ด/๋ฆฌ์ค๋๊ฐ ์ ์ฉ๋ ๊ฒฝ์ฐ ์คํ ์์๊ฐ ์ค์ํ ์ ์์ต๋๋ค. ํ๋ ์์ํฌ๋ง๋ค ์์ ์ ์ด ๋ฐฉ์์ด ๋ค๋ฅด๋ฏ๋ก ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํด์ผ ํฉ๋๋ค.
#์ฑ๋ฅ: ๋ฏธ๋ค์จ์ด/๋ฆฌ์ค๋๊ฐ ๋๋ฌด ๋ง๊ฑฐ๋ ๋ณต์กํ ๋ก์ง์ ํฌํจํ๋ฉด ์์ฒญ ์ฒ๋ฆฌ ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค. ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ๊ณ , ๋ก์ง์ ์ต์ ํํด์ผ ํฉ๋๋ค.
#์ฌ์ฌ์ฉ์ฑ: ์ผ๋ฐ์ ์ธ ์ ๊ทผ ์ ์ด ๋ก์ง์ ๋ฏธ๋ค์จ์ด/๋ฆฌ์ค๋๋ก ๊ตฌํํ๊ณ , ํน์ ์ปจํธ๋กค๋ฌ์๋ง ์ ์ฉ๋๋ ์ธ๋ถ ๋ก์ง์ ์ปจํธ๋กค๋ฌ ๋ด์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ฏธ๋ค์จ์ด ๋๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ ํ๋ ์์ํฌ ๊ธฐ๋ฐ #์ ํ๋ฆฌ์ผ์ด์ ์์ #๋ณด์ ๋ฐ #์ ๊ทผ ์ ์ด ๋ฅผ ๊ตฌํํ๋ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด๋ฅผ ํตํด ์ฝ๋์ ์์ง๋๋ฅผ ๋์ด๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ #์์ด์ถ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ์ฌ ๋ธ๋ก๊ทธ ์ฑ์ฅ์ ๊ฐ์ํํ์ธ์.
๋จ์๊ฐ์ ์๋ฐฑ ๋ช ์ ์ด์์ ์ถ๊ฐํ๊ณ , ๋ธ๋ก๊ทธ ์ง์๋ฅผ ์์น์ํค๋ ๊ฐ์ฅ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค.
์๋ํ๋ #์ด์์ถ๊ฐ, #๋๊ธ, #๊ณต๊ฐ ๊ธฐ๋ฅ์ ํตํด ์ค์ ํ๋ํ๋ ์ด์์ ํ๋ณดํ๊ณ , ๋ธ๋ก๊ทธ ํ์ฑ๋๋ฅผ ๋์ฌ ๋ณด์ธ์.
๋ธ๋ก๊ทธ ์ด์ ์๊ฐ์ ์ ์ฝํ๊ณ ์ถ๋ค๋ฉด ์ง๊ธ ๋ฐ๋ก ์์ํด ๋ณด์ธ์.
์ง์์ ์ธ #์ํต ๊ด๋ฆฌ๋ฅผ ํตํด ๋ธ๋ก๊ทธ ์ ์ฌ๋ ฅ์ ๊ทน๋ํํ ์ ์์ต๋๋ค.
#๋ธ๋ก๊ทธ๋ง์ผํ #๋ธ๋ก๊ทธ์ฑ์ฅ #๋ธ๋ก๊ทธ๊ด๋ฆฌ #๋ค์ด๋ฒ๋ธ๋ก๊ทธ