# 서블릿,필터,리스너 보충자료

### 1. **서블릿 필터(Filter)**

#### 역할

* **요청(request) 및 응답(response) 데이터 처리**: 클라이언트로부터 들어오는 요청을 가로채거나, 서블릿이나 JSP가 응답을 생성한 후 이를 가로채 추가 처리를 수행합니다.
* 주로 다음과 같은 작업에 사용됩니다:
  * 요청/응답 데이터 수정
  * 요청 로깅 및 모니터링
  * 인증 및 권한 검사
  * 데이터 압축 (예: GZIP)
  * CORS 설정 등

#### 동작 방식

1. 클라이언트의 요청이 서버로 들어오면, \*\*필터 체인(Filter Chain)\*\*이 실행됩니다.
2. 필터는 요청을 처리하거나, 필요한 경우 요청을 다음 필터나 서블릿으로 전달합니다.
3. 서블릿이 응답을 생성하면, 필터가 응답을 가로채 필요한 처리를 수행한 뒤 클라이언트로 보냅니다.

#### 동작 순서

1. `web.xml` 또는 `@WebFilter`에 등록된 필터는 **순서대로** 실행됩니다.
2. 필터 체인의 흐름:
   * 요청(Request) → 필터1 → 필터2 → 서블릿 → 필터2 → 필터1 → 응답(Response)

#### 필터 구현 방법

1. `javax.servlet.Filter` 인터페이스 구현.
2. 주요 메서드:
   * `init(FilterConfig config)`: 필터 초기화.
   * `doFilter(ServletRequest request, ServletResponse response, FilterChain chain)`: 요청/응답 처리.
   * `destroy()`: 필터 종료 처리.

```java
@WebFilter("/*") // 모든 요청에 대해 적용
public class LoggingFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        System.out.println("Request received at " + new Date());
        chain.doFilter(request, response); // 다음 필터나 서블릿으로 요청 전달
        System.out.println("Response sent at " + new Date());
    }
}
```

***

### 2. **서블릿 리스너(Listener)**

#### 역할

* **이벤트 기반 동작**: 웹 애플리케이션의 특정 이벤트(예: 시작, 종료, 세션 생성/소멸 등)를 감지하고 처리합니다.
* 주요 사용 사례:
  * 애플리케이션 초기화 작업 (예: 리소스 로딩, 데이터베이스 연결 설정).
  * 세션 추적 (예: 로그인 사용자 수 추적).
  * 리소스 정리 (예: 데이터베이스 연결 종료).

#### 동작 방식

1. 리스너는 특정 이벤트가 발생할 때 자동으로 호출됩니다.
2. 웹 컨테이너는 이벤트 발생 시 리스너를 실행하여 적절한 작업을 수행합니다.

#### 동작 순서

1. 애플리케이션 시작 시 등록된 리스너가 호출됩니다.
2. 세션 관련 이벤트가 발생하면, 관련 리스너가 실행됩니다.
3. 애플리케이션 종료 시 종료 이벤트 리스너가 호출됩니다.

#### 리스너 종류

1. **ServletContextListener**:
   * 애플리케이션 시작/종료 이벤트 처리.
   * 주요 메서드:
     * `contextInitialized(ServletContextEvent event)`: 애플리케이션 초기화 작업.
     * `contextDestroyed(ServletContextEvent event)`: 애플리케이션 종료 작업.
2. **HttpSessionListener**:
   * 세션 생성/소멸 이벤트 처리.
   * 주요 메서드:
     * `sessionCreated(HttpSessionEvent event)`: 세션 생성 시 호출.
     * `sessionDestroyed(HttpSessionEvent event)`: 세션 종료 시 호출.
3. **ServletRequestListener**:
   * 요청(Request) 생성/소멸 이벤트 처리.
   * 주요 메서드:
     * `requestInitialized(ServletRequestEvent event)`: 요청 초기화 시 호출.
     * `requestDestroyed(ServletRequestEvent event)`: 요청 종료 시 호출.

#### 리스너 구현 방법

1. 리스너 인터페이스를 구현.
2. `@WebListener` 또는 `web.xml`에 등록.

```java
@WebListener
public class AppContextListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("Application started!");
    }
    
    public void contextDestroyed(ServletContextEvent event) {
        System.out.println("Application stopped!");
    }
}
```

***

### 3. **필터와 리스너의 차이점**

| 특징        | **필터(Filter)**            | **리스너(Listener)**               |
| --------- | ------------------------- | ------------------------------- |
| **동작 방식** | 요청/응답을 가로채 처리             | 특정 이벤트를 감지하고 처리                 |
| **목적**    | 요청/응답 전후 데이터 변경, 인증, 로깅 등 | 애플리케이션, 세션, 요청의 상태 변화 감지        |
| **실행 시점** | 요청이 들어오거나 응답이 생성될 때 실행    | 애플리케이션/세션/요청의 생명 주기 이벤트 발생 시 실행 |
| **등록 방법** | `@WebFilter` 또는 `web.xml` | `@WebListener` 또는 `web.xml`     |
| **체인 구조** | 필터 체인으로 연결되어 동작           | 독립적으로 동작                        |

***

### 4. **필터와 리스너의 동작 순서**

1. 애플리케이션 초기화:
   * `ServletContextListener.contextInitialized` 실행.
   * 초기화 작업(예: 설정 파일 로딩, 데이터베이스 연결).
2. 클라이언트 요청 처리:
   * `ServletRequestListener.requestInitialized` 실행.
   * 필터 체인 실행: 요청 → 필터1 → 필터2 → 서블릿.
   * 서블릿 처리 후 응답 생성 → 필터 체인 응답 처리: 필터2 → 필터1.
   * `ServletRequestListener.requestDestroyed` 실행.
3. 세션 관련 이벤트:
   * 세션 생성 시: `HttpSessionListener.sessionCreated` 실행.
   * 세션 종료 시: `HttpSessionListener.sessionDestroyed` 실행.
4. 애플리케이션 종료:
   * `ServletContextListener.contextDestroyed` 실행.
   * 종료 작업(예: 리소스 정리, 로그 기록).

***

### 5. **필터와 리스너를 함께 사용하는 예시**

* **필터**:
  * 모든 요청에 대해 로깅.
  * 특정 API에 대해 인증 처리.
* **리스너**:
  * 애플리케이션 시작 시 설정 파일 로드.
  * 세션 생성/종료 시 사용자 활동 로그 기록.

## **생명주기**

### **서블릿 생명주기의 주요 단계**

1. **서블릿 생성 (Initialization)**
   * 서블릿 컨테이너는 서블릿 객체를 메모리에 로드하고 초기화합니다.
   * 초기화는 `init()` 메서드를 통해 이루어지며, 서블릿이 최초로 요청되기 전에 한 번만 호출됩니다.
2. **요청 처리 (Request Handling)**
   * 클라이언트가 서블릿에 요청을 보내면 컨테이너는 `service()` 메서드를 호출하여 요청을 처리합니다.
   * `service()` 메서드는 HTTP 요청 메서드(GET, POST 등)에 따라 적절한 `doGet()`, `doPost()` 등의 메서드를 호출합니다.
3. **서블릿 소멸 (Destruction)**
   * 애플리케이션 종료 시 또는 서블릿이 더 이상 필요 없을 때, 컨테이너는 서블릿 객체를 소멸시킵니다.
   * 소멸 시 `destroy()` 메서드가 호출되며, 리소스 정리(예: 데이터베이스 연결 종료, 스레드 정리 등)를 수행할 수 있습니다.

***

### **서블릿 생명주기 메서드**

#### 1. **`init()`**

* **호출 시점**: 서블릿이 처음 생성될 때 한 번 호출됩니다.
* **목적**: 서블릿의 초기화 작업 수행 (예: 설정 파일 읽기, 데이터베이스 연결 설정).
* **예시**:

  ```java
  @Override
  public void init() throws ServletException {
      System.out.println("Servlet is being initialized");
  }
  ```

#### 2. **`service()`**

* **호출 시점**: 클라이언트 요청이 있을 때마다 호출됩니다.
* **목적**: 요청에 따라 적절한 메서드(`doGet`, `doPost`)를 호출.
* **컨테이너 동작**: 요청 메서드(GET, POST 등)에 따라 `doGet()` 또는 `doPost()` 메서드로 분기.
* **예시**:

  ```java
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) 
          throws ServletException, IOException {
      System.out.println("Processing request");
      super.service(req, resp); // 부모 클래스의 service() 호출
  }
  ```

#### 3. **`destroy()`**

* **호출 시점**: 서블릿이 컨테이너에서 제거될 때 호출됩니다.
* **목적**: 리소스 정리(예: 열려 있는 파일이나 데이터베이스 연결 종료).
* **예시**:

  ```java
  @Override
  public void destroy() {
      System.out.println("Servlet is being destroyed");
  }
  ```

***

### **생명주기 흐름 (Lifecycle Flow)**

1. **서블릿 로드 및 초기화**:
   * 웹 애플리케이션이 시작되거나 서블릿에 처음 요청이 들어올 때 서블릿 클래스가 로드됩니다.
   * 컨테이너는 서블릿 객체를 생성하고, `init()` 메서드를 호출합니다.
2. **요청 처리**:
   * 클라이언트의 HTTP 요청이 들어오면, 컨테이너는 `service()` 메서드를 호출합니다.
   * `service()`는 요청 타입에 따라 `doGet()`, `doPost()` 등 적절한 메서드를 실행합니다.
3. **서블릿 소멸**:
   * 웹 애플리케이션이 종료되거나 서블릿이 필요 없게 되면, 컨테이너는 `destroy()` 메서드를 호출하여 서블릿을 소멸시킵니다.

***

### **서블릿 생명주기의 단계별 예시 코드**

```java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class MyServlet extends HttpServlet {

    // 1. 초기화 단계
    @Override
    public void init() throws ServletException {
        System.out.println("Servlet Initialized");
    }

    // 2. 요청 처리 단계
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        System.out.println("Handling GET request");
        resp.getWriter().write("Hello, World!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        System.out.println("Handling POST request");
        resp.getWriter().write("POST request received");
    }

    // 3. 소멸 단계
    @Override
    public void destroy() {
        System.out.println("Servlet Destroyed");
    }
}
```

***

### **생명주기와 멀티스레드**

* 서블릿은 기본적으로 멀티스레드 환경에서 실행됩니다.
* 하나의 서블릿 객체가 여러 클라이언트 요청을 동시에 처리하므로, **스레드 안전성**에 주의해야 합니다.
  * 서블릿 인스턴스 변수(멤버 변수) 사용 시 동기화가 필요합니다.
  * 지역 변수는 스레드 안전하므로 선호됩니다.

***

### **주의 사항**

1. **`init()`은 한 번만 호출됨**:
   * 서블릿 객체는 싱글톤으로 생성되며, `init()`은 한 번만 호출됩니다.
2. **`service()`는 요청마다 호출됨**:
   * 클라이언트 요청이 올 때마다 호출되므로, 비즈니스 로직을 구현하는 핵심 메서드입니다.
3. **`destroy()`는 마지막 정리 작업에 사용**:
   * 리소스 정리 코드를 반드시 작성해야 메모리 누수를 방지할 수 있습니다.
4. **애플리케이션 종료 시 동작**:
   * 서블릿 컨테이너가 종료되거나 서블릿이 언로드될 때 `destroy()`가 호출됩니다.
