본문 바로가기
교재 실습/자바 웹 개발 워크북

64. ServletContextListener와 객체 공유 (1)

by Jint 2022. 7. 9.

서블릿 컨테이너는 웹 애플리케이션의 상태를 모니터링 할 수 있도록 웹 애플리케이션의 시작에서 종료까지 주요한 사건에 대해 알림 기능을 제공한다. 이런 알림 기능을 이용하고 싶다면, 규칙에 따라 객체를 만들어 DD 파일(web.xml)에 등록하면 된다. 이렇게 사건이 발생했을 때 알림을 받는 객체를 '리스너(Listener)'라고 부른다(그림 1).

 

그림 1 (웹 애플리케이션의 상태 감시와 사건 인지)

다음은 서블릿 컨테이너가 알려주는 주요 사건과 그 규칙이다.

분류 사건 인터페이스
웹 애플리케이션 시작하거나 종료할 때 javax.servlet.ServletContextListener
ServletContext에 값을 추가하고, 제거하고, 대체할 때 javax.servlet.ServletContextAttributeListener
세션 생성, 소멸 할 때 javax.servlet.http.HttpSessionListener
활성, 비활성 할 때 javax.servlet.http.HttpSessionActivationListener
HttpSession에 값을 추가하고, 제거하고, 대체할 때 javax.servlet.http.HttpSessionAttributeListener
요청 요청을 받고 응답할 때 javax.servlet.ServletRequestListener
ServletRequest에 값을 추가하고, 제거하고, 대체할 때 javax.servlet.ServletRequestAttributeListener

앞의 표에서 언급한 사건 중에서 이번 절에서 다룰 사건은 웹 애플리케이션의 시작과 종료 사건이다. 즉 ServletContextListener 인터페이스의 활용법을 배워 본다.

 

예제를 살펴보면 서블릿은 요청을 처리하기 위해 매번 DAO 인스턴스를 생성한다. 이렇게 요청을 처리할 때마다 객체를 만들게 되면 많은 가비지(garbage)가 생성되고, 실행 시간이 길어진다. 서비스를 요청하는 클라이언트가 적을 경우에는 문제가 되지 않지만, 요청이 많아진다면 부담이 될 것이다.

 

DAO의 경우처럼 여러 서블릿이 사용하는 객체는 서로 공유하는 것이 메모리 관리나 실행 속도 측면에서 좋다. DAO를 공유하려면 ServletContext에 저장하는 것이 좋다. ServletContext는 웹 애플리케이션이 종료될 때까지 유지되는 보관소이기 떄문이다(그림 2).

그림 2 (ServletContext를 통해 DAO 공유)

그러면 서블릿이 사용할 DAO 객체는 언제 준비해야 할까? 공유할 객체들은 서블릿이 실행되기 전에 준비되어야 한다. 따라서 보통 웹 애플리케이션을 시작할 때 공유 객체들을 준비한다.

 

이미 '45. 데이터 보관소 (1), 46. 데이터 보관소 (2)'에서 DB 커넥션 객체를 공유하고자 AppInitServlet 클래스를 만든 적이 있다. 이 서블릿에서 DAO 객체를 준비해도 된다. 하지만, 서블릿을 통해 공유 객체를 준비하는 것보다 더 좋은 방법은 웹 애플리케이션 이벤트를 이용하는 것이다.

 

웹 애플리케이션이 시작되거나 종료되는 사건이 발생하면, 이를 알리고자 서블릿 컨테이너는 리스너의 메서드를 호출한다. 바로 이 리스너에서 DAO를 준비하면 된다. DAO 뿐만 아니라 AppInitServlet 클래스가 하던 일도 이 리스너에서 처리하면 된다.

 

이제 리스너를 활용하여 공유 객체를 준비해본다.

 

1. ServletContextListener의 활용

웹 애플리케이션의 시작과 종료 사건을 담당할 리스너를 준비한다. AppInitServlet 클래스가 하던 일을 이 리스너로 옮긴다. 또한, MemberDao 클래스의 인스턴스 생성도 이 리스너에서 준비한다. 다음은 리스너의 구동과 서블릿들의 DAO 공유 과정을 보여주는 그림이다(그림 3).

그림 3 (리스너의 구동 과정과 DAO 공유)

① 웹 애플리케이션이 시작되면, 서블릿 컨테이너는 ServletContextListener의 구현체에 대해 contextInitialized() 메서드를 호출한다.

② 리스너는 DB 커넥션 객체를 생성한다.

③ 리스너는 DAO 객체를 생성한다.

④ 그리고 DB 커넥션 객체를 DAO에 주입한다.

⑤ 서블릿들이 DAO 객체를 사용할 수 있도록  ServletContext 보관소에 저장한다.

⑥ 만약 웹 애플리케이션이 종료되면, 서블릿 컨테이너는 리스너의 contextDestroyed() 메서드를 호출한다.

이렇게 ServletContext에 저장된 DAO 객체를 서블릿들이 꺼내 쓰는 것이다.

 

참고도서 : https://freelec.co.kr/book/1674/

 

[열혈강의] 자바 웹 개발 워크북

[열혈강의] 자바 웹 개발 워크북

freelec.co.kr

댓글