-
서블릿 필터(filter)에 대해서백엔드/서블릿&JSP 2021. 1. 13. 15:45
2021/01/06 - [백엔드/서블릿&JSP] - javax.servlet 패키지
위와 같이 이미 servlet 패키지를 설명하면서 서블릿 필터에 대해서 이미 한번 포스팅한 적이 있다.
서블릿의 필터란 서블릿으로 전달되는 클라이언트의 request 혹은 서블릿에서 클라이언트로 전달되는
response를 중간에 가로채서 필터링을 위해 객체와 메서드를 정의해 둔 인터페이스다.
그림으로 나타내면 아래와 같다.
필터는 클라이언트와 서블릿 사이에서 전달되는 request와 response를 중간에서 가로채서
특정한 작업을 하게 된다.
모든 request와 response에 적용되야 하는 작업 예를 들어 문자 인코딩 작업 등을 필터로 해준다.
불필요하게 반복되는 작업을 필터를 통해 적용함으로써 코드를 줄이고 생산성을 높이는 것이다.
필터의 필요성
위와 같은 폼을 가진 HTML 문서가 있다고 가정하자. 코드는 아래와 같다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form action="encoding" method="post"> 이름 <input type="text" name="name"><br> 나이 <input type="text" name="age"><br> 장소 <input type="text" name="place"><br> <input type="submit"> </form> </body> </html>
그리고 이 form을 전달해서 처리하는 서블릿이 있다고 가정해보자. 코드는 아래와 같다.
@WebServlet("/encoding") public class encoding extends HttpServlet{ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); String name = request.getParameter("name"); String age = request.getParameter("age"); String place = request.getParameter("place"); out.print("이름은 "+name+"<br>"); out.print("나이는 "+age+"<br>"); out.print("장소는 "+place+"<br>"); } }
form을 통해 이름, 나이, 장소를 입력하면 서블릿이 받아서 처리한 후 화면에 출력한다.
그런데 이때 문제가 있다 바로 문자 인코딩이다.
2021/01/13 - [백엔드/서블릿&JSP] - 서블릿에서 한글 문자 인코딩하기
인코딩 편에서 이미 이야기했듯이 서블릿을 통해 문자를 처리하기 위해선 문자 인코딩이 필요하다.
그리고 인코딩을 위해선 매번 request와 response 객체에 메서드를 통해 문자 인코딩을 지정해야했다.
만약 서블릿이 단 하나라면 이렇게 처리해도 상관없지만 만약 서블릿이 1000개가 있다고 가정해보자.
그럼 매번 저 메서드를 1000개의 문서에 모두 코드로 입력해야 한다.
하지만 필터를 이용하면 이러한 수고를 덜 수 있다.
필터 만들어보기
클래스를 만들고 filter를 구현하면 아래와 같은 코드가 만들어진다.
package test; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; @WebFilter("/*") public class EncodingFilter implements Filter{ @Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) { System.out.println("필터입니다."); } }
WebFilter 어노테이션을 통해 해당 url로 들어오는 모든 서블릿 요청을 필터링하도록 URL을 지정한다.
그리고 doFilter 안에 필터링할 내용을 입력해주면 된다.
그리고나서 처음에 작성한 html 문서를 실행해서 데이터를 서블릿으로 전달해보자.
그럼 필터가 작동해서 아래 이미지처럼 콘솔창에 메시지를 볼 수 있다.
필터는 잘 작동한다. 하지만 문제가 하나 생긴다.
정작 제출은 되는데 그 결과물이 나타나지 않는다.
그 이유는 바로 HTML에서 보낸 request를 필터가 전달 받아서 아무 처리도 하지 않고 있기 때문이다.
필터는 request가 요청을 보내면 "필터입니다"라는 메시지를 띄우라고만 써놨기때문에
콘솔창에 문자 출력 이후 필터는 더 이상 작동하지 않는 것이다.
이때는 doFilter 메서드를 사용해서 Filter를 통과하는 request와 response를 처리해줘야 한다.
위 이미지처럼 파라미터로 받은 request, response 객체를 doFilter의 매개변수로 넣어주면 된다.
이렇게하면 필터가 제대로 작동되고 request와 response가 제대로 왕복하는 것을 확인할 수 있다.
이때 알아둬야 할 것이 필터로 처리할 것이 있다면 가급적 chain.doFilter 전에 해야 한다.
필터의 실행 순서는 위와 같다.
모든 request는 doFilter 이전에 처리를 해야한다.
doFilter 실행과 함께 흐름이 서블릿으로 넘어가기 때문이다.
즉 doFilter가 실행되면 서블릿이 실행되고 request는 이미 넘어갔으므로 어떤 처리를 해도 소용이 없다.
추가적으로 문자 인코딩의 경우 response도 doFilter 이전에 해야 정상적인 처리가 가능하다.
이것이 가능한 이유는 response 객체의 생성 시점은 reponse 될 때가 아니기 때문이다.
사용자 request가 웹 컨테이너에 전달된 순간 미리 만들어졌므로 이러한 것이 가능하다.
@WebFilter("/*") public class EncodingFilter implements Filter{ @Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=UTF-8"); chain.doFilter(request, response); } }
위와 같이 처리하고 나면 서블릿에서 문자 인코딩을 위한 메서드들을 삭제해도 아래와 같은 결과가 나온다.
필터는 이렇게보면 굉장히 편리하지만 필터에 너무 많은 내용을 넣으면 순서가 꼬이는 경우도 있다.
그렇기 때문에 필터를 적용하기 전에 여러 가지를 고려해봐야 한다.
'백엔드 > 서블릿&JSP' 카테고리의 다른 글
JSP의 내장객체, 암시적 객체(implicit object) - application, pageContext, page (0) 2021.01.14 서블릿 데이터 저장소 - request, session, ServletContext (0) 2021.01.14 서블릿에서 한글 문자 인코딩하기 (0) 2021.01.13 서블릿 기초 형태 (0) 2021.01.13 forward와 sendRedirect 차이 (0) 2021.01.11