본문 바로가기
Front-end (국비)/이론

필터 클래스

by Hwanii_ 2023. 7. 5.
728x90

1.

필터 클래스 란?

(.java 클래스)

 

필터 클래스는 중요한 개념 이다.

 

실제, 현업에서도 자체 솔루션 이나, 프레임워크 등, 사실

이러한 필터 클래스 들이 기본 제공 되서 사용되고 있다.

 

이렇게, 현업에서도 기본 제공 되서 그냥 사용 하고 있기 때문에,

이 개념 자체를 모르게 되는 경우가 많아 질 수 있다.

 

(사실은, 실제로 필터 클래스를 건드릴 일이 없긴 한데,,)

 

이러한 개념이 있다는 것을 알고 가면 좋을듯 하다.

 

2.

필터 클래스를 왜 사용할까 ?

 

스노우 어플 필터를 생각 하기

>>

카메라 렌즈에 내 얼굴을 보이게 되면, 얼굴이 보정 된다.

 

정수기 필터를 생각 하기

>>

물이 필터를 통과 하면 물이 정수 된다.

 

 

 

사용자 (브라우저, 클라이언트) 의 요청이 들어올 때,

특정한 기능을 부여 하기 위해서 사용 한다.

 

ex) 인코딩, 권한 확인, 로그, 보안, ..

 

인코딩 예시

>>

사용자가 입력한 값이 한글일 때, UTF-8을 지원 하지 않는 상황 이라면,

한글이 깨져서, DB에 저장되게 될것이다.

그래서, 사용자가 입력한 값을 받기 전에,

인코딩 필터를 거치고, 값을 받는 식으로 구현 된다.

 

권한 확인 예시

>>

카페에 회원 등급에 따라서, 게시글을 볼 수 있거나 없거나 ..

 

3.

필터 클래스는 일반적으로 언제 동작 할까 ?

 

View ----- 필터 클래스 (기능 부여) >> C

 

일반적으로, 사용자 (브라우저, 클라이언트) 의 요청 직후에 바로 호출 된다.

 

정확하게는, Filter mappings 를 설정한 시간에 호출 된다 !

 

근데, 보통 이 Filter mappings 를 설정하는 때가,

사용자가 요청한 직후로 설정 하는게 대다수 이다.

 

그래서, 

필터 클래스가 언제 동작 해요 ? 라는 질문에,

일반적으로, 사용자의 요청 직후에 동작 해요 ~

라고 말할 수 있는 것이다.

 

4.

[ POJO 와 Not POJO 개념 ]

 

POJO :

Plain of Java Object

>>

아무것도 없는, 구식의 자바 객체 라는 의미 이다.

( == 오래된 방식의 순수한 자바 객체 를 의미 한다. )

 

본인이 평소에 공부용으로 만들었던, StudentVO, MemberVO, ..

일반 class 파일로 생성 할 수 있는 자바 클래스 들을 POJO 라고 한다.

 

Not POJO :

>>

말 그대로, POJO가 아니라는 뜻이다.

 

Filter, Listener, Servlet 등이 Not POJO 에 해당한다.

 

위의 예시의 class 파일들을 생성하면,

이미 수많은 파일들이 import 가 되어있는 모습을 확인 할 수 있다.

 

 

즉, 이렇게 기본 제공 되는 기능들이 이미 많은 클래스를

 

Not POJO 클래스 라고 한다.

 

 

 

하지만, POJO (Plain of Java Object) 를 지향 해야 하는 이유가 있다.

 

특정 기술과 환경에 (스프링 프레임워크, .. 등) 종속 되어 의존 하게 되는

자바 코드는 가독성이 떨어지고, 유지 보수에 어려움이 생긴다.

 

또한, 특정 기술의 클래스를 상속 받거나, 직접 의존 하게 되어,

확장성이 매우 떨어지는 단점이 존재 한다.

 

이러한 말들은, 자바가 객체 지향 설계의 장점을 잃어 버렸다는 것을 의미 한다.

 

그래서, POJO 라는 개념이 등장 했다.

 

본래의 자바의 장점을 살리는 '오래된 방식의 '순수한' 자바 객체 라는 의미 이다.

 

[참고]

POJO라는 용어는 이후,

주로 특정 자바 모델이나 기능, 프레임워크 등을 따르지 않은 자바 오브젝트를 지칭하는 말로 사용 한다.

 

스프링 프레임워크는 POJO 방식의 프레임워크이다.

 

5.

 

<form action = "test04.jsp" method = "post">

보낼 데이터 : <input type = "text" name = "data">

<input type = "submit" value = "데이터 전송">

 

</form>

 

위와 같은 form 태그가 있다.

 

사용자가, text 형식으로 값을 입력 하고, data 라는 이름으로 test04.jsp 로 데이터가 전송 된다.

 

이때, 사용자가 입력하고 데이터를 전송 할 때, post 방식으로 데이터가 전송되고,

만약에, UTF-8 인코딩이 안되있다면, 사용자가 한글 데이터를 전송 했을 때,

한글이 깨지는 현상이 발생 한다.

 

그래서, 필터 클래스를 통해 인코딩을 구현해 보려고 한다.

 

도착한 데이터 : ${param.data} // test04.jsp

// form 태그로 전송받은 데이터 라서,

// EL 식을 사용 할 때, param.data 가 된다. (속성 (멤버변수) 이 아니다.)

 

 

 

깨짐 없이 잘 전송된 모습 이다.

 

아래에서, 어떻게 필터 클래스를 구현 했는지 확인해보자.

 

우선 필터 클래스를 생성 하는 방법 이다.

 

 

.java 파일 이기에, wepapp 폴더가 아닌, 자바 폴더에 생성 해야 한다.

 

 

패키지명이 현재, model 패키지 밖에 없으므로,

Java package : model 로 작성 하고,

 

Class name 은, 인코딩 필터라서, EncFilter 라고 그냥 지어 주었다.

 

(package를 model 이 아니라, controller 로 해서 넣어 줘야 하나 ..?)

 

작성후 Next 클릭.

 

 

Filter mappings 영역 이다.

 

우측의 Edit 버튼을 누른다.

 

 

Filter Mapping 을 Edit 해준다.

 

위에 정리 했듯이,

 

필터 클래스는 일반적으로 언제 동작 할까 ?

 

View ----- 필터 클래스 (기능 부여) >> C

 

일반적으로, 사용자 (브라우저, 클라이언트) 의 요청 직후에 바로 호출 된다.

 

정확하게는, Filter mappings 를 설정한 시간에 호출 된다 !

 

보통 이 Filter mappings 를 설정하는 때가,

사용자가 요청한 직후로 설정 하는게 대다수 !

 

그래서, *.jsp 로 작성하고, OK 버튼을 누른다.

 

그러면, 필터 클래스가 생성 된다 !

 

[ 개념 ]

*.jsp 로 하는 이유 ?

 

*.jsp로 해야, 사용자가 요청 했을 때가 되고,

모든 .jsp 페이지에서 를 의미 한다.

 

만약에, a_index.jsp 로 설정 해놓았다면 ?

a_index.jsp 에서만 으로 된다.

 

a_index.jsp 에서 사용자가 요청 했을 때만,인코딩 호출이 적용 되는 것이다.

 

참고로, 사용자의 요청 이라는 것은 다음과 같다.

 

웹 브라우저 에서,

사용자가 어떤 요청 버튼을 눌러도 요청이고,

f5를 눌러서 새로 고침을 실행해도 요청이고,

submit 버튼을 눌러서, 데이터를 전송해도 요청 이다.

 

6.

 

필터 클래스

 

 

 

이미지와 같이, 수많은 것들이 import 되어있는 Not POJO 클래스가 생성 된다.

 

@WebFilter("*.jsp")

public class EncFilter extends HttpFilter implements Filter {

private String encoding;

// Not POJO 클래스에서, 멤버변수는 생성자에서 초기화 하지 않고, init 함수 내부에서 초기화 한다.

public EncFilter() {

// 디폴트 생성자 (기본 생성자) 가 꼭 필수라서 해당 코드가 작성 되어 있는 것이다.

super();

// TODO Auto-generated constructor stub

}

public void destroy() {

// 필터가 메모리에서 해제될 때, 자동 호출 된다.

// TODO Auto-generated method stub

}

 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

request.setCharacterEncoding(this.encoding);

// init() 함수에서 초기화 된, 값을 이곳에 적어 준다.

chain.doFilter(request, response);

}

 

public void init(FilterConfig fConfig) throws ServletException {

// 필터가 '최초로 생성될때' 자동으로 호출 된다. 그래서, 딱 한번만 사용 된다.

// TODO Auto-generated method stub

 

this.encoding = fConfig.getServletContext().getInitParameter("encoding");

 

System.out.println("정말로 한번만 사용 됬는지를 확인하는 로그.");

}

}

 

 

 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

 

doFilter 함수 내부에, 인코딩 처리 로직을 작성 한다.

왜냐하면, 인코딩 처리는 보통, 사용자의 요청을 받기 전에 인코딩을 하는게 일반적인 상황 이다.

 

사용자의 요청을 받는 코드는 무엇일까 ?

 

바로, 이것이다.

 

chain.doFilter(request, response);

 

chain.doFilter() 이 바로, 사용자의 요청 이다.

이곳에, 사용자의 요청 정보가 모두 저장 되어 있다.

사용자의 요청 정보를 확인 한다.

왜 ?

>>

사용자가 어떤 요청을 했는지를 파악해서, 다음 페이지로 이동 하기 때문 이다.

 

암튼, 사용자의 요청을 받는 코드보다 앞에, 인코딩 처리 로직을 작성 하면 된다.

 

그리고 한가지 개념이 또 있다.

 

request.setCharacterEncoding("UTF-8"); // UTF-8을 그대로 작성 하지 않는다.

 

request.setCharacterEncoding(this.encoding);

// private encoding; 으로 멤버변수를 선언.

// this.encoding = UTF-8 으로 초기화를 해서,

// 위와 같이 사용 해야 한다.

 

원래는, 위의 메서드가 UTF-8 메서드 이기 때문에, 저렇게 작성 해도 되는데,

 

유지 보수의 용이함을 위해서, 인자의 UTF-8 을 사용 하기 위한 멤버변수를 

 

상단에 선언 한다.

 

public class EncFilter extends HttpFilter implements Filter {

private String encoding;

 

근데, encoding 의 값을 원래는, 생성자 에서 초기화 해주지만,

 

Not POJO 클래스 에서는, 생성자에서 멤버변수를 초기화 해주지 않는다.

 

왜냐하면, 클래스 내부에 기능이 너무 많기에, 생성자를 새롭게 만들지 않기 때문 이다.

 

그러면 멤버변수 초기화를 어디서 해야 하는걸까 ?

 

바로, init() 함수에서 멤버변수의 값을 초기화 해준다.

 

public void init(FilterConfig fConfig) throws ServletException {

// init() 메서드는, 필터가 '최초로 생성될 때' 자동으로 호출 된다.

// 즉, init() 메서드는, 딱 한번만 호출 된다.

this.encoding = fConfig.getServletContext().getInitParameter("encoding");

 

여기서도 또 하나의 개념이 존재 한다.

 

원래 라면, this.encoding = UTF-8  으로 적어주면 끝인데,

 

위의 코드는 도대체 무슨 코드인걸까 ?

 

바로 아래의 개념 이다.

 

 

webapp - META-INF - web.xml

 

web.xml 설정 파일을 생성 한다.

 

web.xml 파일의 내용을 로드해서 (불러와서) 사용 하는 식으로 구현 한다.

 

왜 이렇게 할까 ?

 

만약에, 

 

 

로 작성 했다고 해보자.

 

근데, "UTF-8" 말고, 다른 값으로 변경 하고 싶은거야 ~

 

그래서 JAVA를 재 작성 했어 ~

 

그러면 재 컴파일이 필요 하겠지 ?

 

컴파일을 다시 한다 ? == 서버를 다시 시작 한다.

 

따라서, 서버가 최소 1초 이상 정지 되는 문제가 발생 한다.

 

결론은, JAVA를 재 작성 하는 일을 만들지 않는게 좋은 상황 이다.

 

그래서, .xml 파일에 데이터를 설정하고,

 

해당 파일에서 내용을 로드 하는 식으로 구현 하는 것이다 !

 

 

web.xml 파일 내부 이다.

 

7번째 ~ 8번째 라인의 코드는, encoding = "UTF-8" 이라는 의미 이다.

 

web.xml 을 사용 하기 위해서는, 3번째 라인의 코드를 꼭 작성 해야 한다.

 

 

this.encoding = fConfig.getServletContext().getInitParameter("encoding");

 

끝으로,

서버를 위해 사용중인 톰캣에서 디폴트 설정 으로,

WEB-INF 하위폴더에서 web.xml을 확인하도록 되어 있기 때문에,

web.xml 파일에 위와 같이 작성 하고,

web.xml 파일의 내용을 로드해서 (불러와서) 사용 하는 식으로

구현이 가능한 것이다.

 

반응형