게임/ASP.NET Core
11. Filter
seeyoun
2024. 4. 15. 23:17
◆ Filter
미들웨어에 대해서는 알아봤었다.
- HTTP Request 및 Response를 처리하는 중간 부품이라고 했다.
근데 사실 이런 중간 부품으로 사용할 수 있는 파이프라인이 하나 더 있는데, 바로 필터 파이프라인이다.
필터링은 말그대로 무언가를 걸러주는 역할을 의미한다.
- 허가받는 특정 사람들만 액션에 접근할 수 있게 하는 것
- 로그인한 유저들에게만 보이도록 하는 것
필터가 없으면, 이런 코드를 모든 Action에 일일이 추가해야 했을 것임.
nice한 기능인듯하다.
필터 사용 시점
그러면 필터는 어떤 시점에 추가할 수 있는걸까?
다음과 같이 작업들의 중간중간에 넣을 수 있다.
- Request
- Routing
- Filter
- Model Binding (+Validation)
- Filter
- Action
- Filter
- ViewResult
- Filter
- HTML Response
넣는 시점에 따라 필터의 이름과 종류가 달라진다.
- Authorization Filter
- 인증. 권한이 있는지 확인. (매우 중요한 필터)
- 필터들 중에서 가장 먼저 실행된다.
- 권한이 없다면, 더이상 밑으로 안 보내고 흐름을 끊어서 빠져나감. (Short-Cutting)
- Resource Filter
- Authorization 필터 다음으로 실행되는 필터이며, 맨 마지막에도 실행됨
(OnResourceExecuting / OnResourceExecuted) - 많이 사용되는 필터이며, 공용 코드를 넣을때 주로 사용.
- 얘도 Short-Cutting 가능
- Authorization 필터 다음으로 실행되는 필터이며, 맨 마지막에도 실행됨
- Action Filter
- 액션 호출 전/후에 실행
- 모델링에 대한 체크 등에 사용하면 좋음
- Exception Filter
- 예외를 처리할 때 사용
- Result Filter
- IActionResult (결과물) 전/후에 실행
- 결과물에 대한 최종 수정 작업 가능. 최종 결과물을 xml형식으로 바꿔달라거나 그런 것 가능
필터 vs 미들웨어
필터랑 미들웨어는 뭐가 다를까?
- 미들웨어는 항상 양방향(In/Out)인 반면, 필터는 꼭 그렇지만은 않다.
- 필터 중에 Resource, Action, Result는 2번 실행됨. 나머진 1번
- 미들웨어는 모든 Request에 대해 실행되는 반면, 필터는 MVC 미들웨어와 연관된 Request에 대해서만 실행된다
- 필터는 MVC Action이라는 미들웨어에서 동작하는 미들웨어라고 볼 수 있다.
- 요청 파이프라인에서 미들웨어들을 타고 가며 처리를 하다가, Action에 넘어오면 여기서 이제 필터 파이프라인이 진행되는 것이다.
- 미들웨어와 달리, 필터는 적용 범위를 선택할 수 있다.
- global: 모든 컨트롤러
- controllter: 특정 컨트롤러
- action: 특정 액션
- 또한 필터는 MVC의 ModelState나 IActionResults 등 세부 정보에 접근할 수 있다.
필터 구현
실제로 필터를 만들어보자.
필터를 만들기 위해서는 종류별로 정의되어있는 필터 interface를 구현하면 된다.
다음과 같은 필터 인터페이스들이 존재한다.
- Authorization
- IAuthorizationFilter, IAsyncAuthorizationFilter
- Resource
- IResouceFilter, IAsyncResourceFilter
- ...
- ...
1. 우선 using을 추가해준다
using Microsoft.AspNetCore.Mvc.Filters;
2. 그리고 원하는 종류의 필터를 만든다.
public class TestResourceFilter : Attribute, IResourceFilter
{
//전
public void OnResourceExecuting(ResourceExecutingContext context)
{
Console.WriteLine("ResourceExecuting");
}
//후
public void OnResourceExecuted(ResourceExecutedContext context)
{
Console.WriteLine("ResourceExcuted");
}
}
- IResourceFilter을 구현한 리소스 필터이다.
- Attribute 클래스도 상속받았는데, 이는 애트리뷰트화 해서 사용할 수 있다는 뜻이다.
- 컨트롤러나 액션에다 [TestResourceFilter] 형식으로 애트리뷰트를 붙이면 이 필터를 적용하겠다는 뜻이다.
- 리소스 필터의 경우 적용되는 시점이 두 번이었는데, 구현한 두 메소드가 각 시점에 해당하는 메소드임을 알 수 있다.
3. (Optional)
만약 전역 범위에 필터가 적용되도록 하고싶다면, 애트리뷰트가 아닌 다른 방법을 사용한다.
Program.cs에서 다음과 같이 설정해주면 된다.
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add <TestResourceFilter>();
});
4. 이렇게 필터를 넣어주고 https://localhost:7080/Home/Test를 실행하면, 동작하는 순서는 다음과 같다.
OnResourceExecuting() => Test() => OnResourceExecuted()
※ 참고로 여러 범위의 필터를 중복해서 걸어줄 수도 있는데, 동작하는 순서는 다음과 같이 직관적이다.
- Executing인 경우 : Global → Controller → Action
- Executed인 경우 : Action → Controller → Global
- 굳이 직접 명시적으로 실행 순서를 지정하는 방법도 있다.
- IOrderedFilter을 상속받아서 구현하면 된다.
- IOrderedFilter 인터페이스의 int Order 기본값은 0이며, 작을수록 먼저 실행된다.
- Order가 같은 경우에는 앞서 언급한 순서에 따라 실행된다.