Apache Tomcat / / 2024. 10. 8. 09:43

Spring MVC, SessionFactory Bean, ContextLoaderListener, ServletContextListener

Spring MVC 흐름(출처-https://sundaland.tistory.com/24)

1. Request (요청):

 

클라이언트(주로 브라우저)에서 HTTP 요청을 보내면, Spring 애플리케이션의 DispatcherServlet이 그 요청을 받게 돼. DispatcherServlet은 Spring MVC의 핵심 요소로, 모든 요청을 중앙에서 관리하고 조정하는 역할을 해. 모든 HTTP 요청은 우선 DispatcherServlet을 거쳐가며, 이 서블릿이 적절한 컨트롤러로 요청을 전달해.

 

2. Handler Mapping (핸들러 매핑):

 

요청이 들어오면 DispatcherServlet은 어떤 컨트롤러(Handler)가 이 요청을 처리할지 결정해야 해. 이때 HandlerMapping이 사용돼. HandlerMapping은 들어온 요청의 URL, 요청 메서드(GET, POST 등), 패턴 등에 따라 적합한 컨트롤러(Handler)를 찾아줘.

 

HandlerMapping의 역할은 매우 중요한데, Spring은 여러 가지 HandlerMapping 전략을 제공해:

 

RequestMappingHandlerMapping: 주로 @RequestMapping, @GetMapping 같은 애노테이션을 기반으로 URL과 컨트롤러를 연결해.

SimpleUrlHandlerMapping: URL을 직접 명시적으로 매핑할 때 사용돼.

 

HandlerMapping은 찾은 컨트롤러 정보를 DispatcherServlet에 전달해.

 

3. Handler Adapter (핸들러 어댑터):

 

컨트롤러(Handler)를 찾았다면, 그걸 실행하는 과정이 필요해. HandlerAdapter가 이 역할을 해. 각 Handler(컨트롤러)가 다를 수 있는데, 이를 쉽게 실행할 수 있도록 어댑터가 컨트롤러와 상호작용할 수 있게 도와줘.

 

Spring에서는 다양한 HandlerAdapter를 제공하지만, 주로 RequestMappingHandlerAdapter가 자주 사용돼. 이 어댑터는 @RequestMapping이 붙은 메서드를 호출하고, 그 결과를 받아서 DispatcherServlet에 넘겨줘.

 

4. Controller (컨트롤러):

 

이제 Controller가 호출돼. 컨트롤러는 클라이언트의 요청을 처리하고, 그 과정에서 비즈니스 로직이 필요하면 Service 계층을 호출해 처리해. Service는 주로 비즈니스 로직을 담당하고, 필요하면 데이터베이스 작업을 위해 Repository와 통신해.

 

컨트롤러의 역할은 크게 두 가지야:

 

1. 비즈니스 로직 처리: 사용자의 요청에 따라 데이터를 처리하거나 특정 동작을 수행해. 이때 주로 서비스 계층과 상호작용해.

2. ModelView 결정: 사용자가 볼 화면(View)과 화면에 필요한 데이터를 모델로 전달해. 컨트롤러는 이를 위해 view name과 모델 데이터를 DispatcherServlet에 넘겨줘.

 

Controller에서 주로 사용되는 애노테이션은:

 

@Controller: 클래스에 붙여 컨트롤러임을 명시.

@RequestMapping: 메서드에 붙여 특정 URL 패턴에 매핑.

@GetMapping, @PostMapping: HTTP 메서드에 따라 URL 매핑.

 

5. View Name (뷰 이름):

 

Controller가 작업을 마치면, 결과로 view name(화면 이름)과 Model 데이터를 반환해. view name은 어떤 화면을 렌더링할지 결정하는 중요한 정보야.

 

6. View Resolver (뷰 리졸버):

 

ViewResolver는 Controller가 반환한 view name을 받아서 실제로 보여줄 View를 결정해. 보통 이 View는 HTML, JSP, Thymeleaf, Freemarker와 같은 템플릿 엔진에 의해 렌더링되는데, Spring에서는 이 템플릿 엔진을 쉽게 사용할 수 있도록 다양한 ViewResolver를 제공해.

 

예를 들어, InternalResourceViewResolver는 JSP와 같은 템플릿을 찾고, ThymeleafViewResolver는 Thymeleaf 템플릿을 찾아서 뷰를 처리해. 이렇게 ViewResolver가 결정된 View를 반환하면, 그 View가 사용자에게 보여질 실제 화면을 준비하게 돼.

 

7. Model (모델):

 

Model은 화면에 표시할 데이터를 담고 있어. 이 데이터는 컨트롤러에서 생성되고, 뷰에서 참조해 사용자에게 보여주게 돼. Model은 주로 키-값 쌍으로 데이터가 담기는데, 뷰는 이 데이터를 받아서 동적으로 페이지를 생성해.

 

예를 들어, 컨트롤러에서 사용자 목록을 모델에 담아 뷰로 넘겨주면, 뷰에서는 그 데이터를 활용해 HTML로 렌더링해 브라우저에 표시할 수 있어.

 

8. View (뷰):

 

View는 최종적으로 사용자에게 보여질 화면이야. View는 사용자가 요청한 정보를 시각적으로 제공하는 역할을 해. 예를 들어, 사용자 목록을 요청했다면 그 결과를 HTML 페이지로 변환해 사용자에게 보여주는 것이 View의 역할이야.

 

View는 Model에서 제공된 데이터를 사용해 동적으로 생성되고, 사용자에게 결과를 반환해. Spring에서는 JSP, Thymeleaf, Freemarker, 그리고 다양한 템플릿 엔진을 지원해 뷰를 생성할 수 있어.

 

9. Response (응답):

 

마지막으로 준비된 View는 사용자에게 HTTP 응답으로 전달돼. 이때 응답은 HTML, JSON, XML 등의 형식일 수 있고, 클라이언트는 이 응답을 받아서 화면에 보여주게 돼.

 

요약:

 

1. 클라이언트가 요청을 보내면 DispatcherServlet이 요청을 받아.

2. HandlerMapping이 요청에 맞는 컨트롤러를 찾아주고, HandlerAdapter가 그 컨트롤러를 실행해.

3. 컨트롤러는 비즈니스 로직을 처리하고, 결과를 Model에 담아 View Name과 함께 반환해.

4. ViewResolver가 view name에 맞는 View를 찾아 사용자에게 보여줄 화면을 준비해.

5. 최종적으로 사용자는 해당 View(HTML 등)를 브라우저에서 볼 수 있게 돼.


Spring MVC와 서블릿 컨테이너 간의 상호작용(출처-https://sundaland.tistory.com/24)

Servlet Container (서블릿 컨테이너):

 

서블릿 컨테이너는 서블릿을 관리하고, 서블릿에 대한 생명주기를 처리해. 여기서 생명주기란 서블릿이 처음 로드되고 초기화(init), 실행(service), 그리고 종료(destroy)되는 과정을 말해. 서블릿 컨테이너의 주요 역할은 HTTP 요청을 받아 서블릿으로 전달하고, 그 결과를 다시 HTTP 응답으로 클라이언트에게 반환하는 거야.

 

1. Servlet Filter:

요청이 서블릿에 도달하기 전에 필터가 먼저 실행돼. 이 필터는 보안, 로깅, 요청 수정 등을 처리할 수 있어. 이 필터를 통해 요청을 걸러내거나 추가적인 작업을 수행할 수 있어.

2. Servlet Lifecycle:

init(): 서블릿이 처음 로드될 때 한 번 실행돼. 서블릿 초기화 작업을 이 단계에서 수행해.

service(): 실제로 클라이언트의 요청을 처리하는 부분이야. doGet() 또는 doPost()와 같은 메서드를 통해 요청이 처리돼.

destroy(): 서블릿이 종료될 때 호출돼. 여기서 자원을 해제하거나 마지막 정리 작업을 할 수 있어.

 

Spring MVC Container (스프링 MVC 컨테이너):

 

서블릿 컨테이너와 별도로 Spring MVC는 Spring MVC Container를 통해 동작해. Spring MVC에서 DispatcherServlet이 중심 역할을 맡고 있어. DispatcherServlet은 Spring MVC의 요청을 처리하는 메인 서블릿이야.

 

1. DispatcherServlet:

사용자가 보낸 HTTP 요청은 Servlet Container의 DispatcherServlet으로 전달돼.

DispatcherServlet은 요청을 받아서, Spring의 Controller로 요청을 넘겨.

2. Controller:

Controller는 Spring MVC의 구성요소로, 클라이언트의 요청을 처리하는 역할을 해. 클라이언트로부터 받은 요청을 처리하고, 그 결과를 다시 DispatcherServlet에 반환해.

Controller는 필요한 비즈니스 로직을 처리하거나, 필요한 데이터를 가져오기 위해 Service 계층과 상호작용할 수 있어.

3. Service:

여기서 중요한 점은, 이미지에서 Service로의 직접 연결이 잘못된 경로로 표시돼 있어(빨간색 “X”). Controller가 직접 Service 계층을 호출해서 비즈니스 로직을 처리하고, 그 결과를 사용자가 요청한 내용에 맞게 반환해.

4. Response:

Controller에서 요청이 처리되고 나면, 다시 DispatcherServlet을 통해 그 결과가 HTTP 응답으로 클라이언트에게 전달돼.

 

정리:

 

이 이미지에서는 Spring MVC가 서블릿 컨테이너와 어떻게 통합되는지 보여주고 있어.

 

서블릿 컨테이너는 기본적인 서블릿 실행 환경을 제공하고, DispatcherServlet이 그 위에서 Spring MVC 애플리케이션의 모든 요청을 관리해.

Spring MVC Container는 DispatcherServlet을 통해 Controller와 상호작용하고, 필요한 경우 Service 계층을 호출해 비즈니스 로직을 처리해.

최종적으로, 클라이언트가 보낸 요청은 여러 단계를 거쳐 처리된 후 다시 클라이언트에게 응답으로 전달돼.

 

Tip💡

appBase: Tomcat 호스트 전체의 기본 애플리케이션 배포 디렉터리.

docBase: 특정 애플리케이션의 실제 파일 또는 디렉터리가 위치한 경로.


Hibernate에서 SessionFactory를 만드는 Bean은 주로 Spring과 함께 사용될 때 설정을 통해 정의돼. Spring을 사용할 경우, Spring의 DI(의존성 주입) 시스템을 통해 Hibernate의 SessionFactory를 관리할 수 있어.

 

Hibernate SessionFactory란?

 

SessionFactory는 Hibernate에서 매우 중요한 객체로, 데이터베이스와의 세션을 생성하는 역할을 해. 애플리케이션 내에서 데이터베이스와의 모든 상호작용은 Session을 통해 이루어지며, SessionFactory는 이러한 Session을 생성하는 공장 역할을 해.

 

Spring에서 SessionFactory Bean 생성 방법

 

Spring Boot나 Spring Framework에서는 SessionFactory를 자동으로 설정하거나, 수동으로 구성할 수 있어. 주로 Hibernate와 JPA를 사용할 때 EntityManagerFactory를 대신 사용하지만, Hibernate의 기본 설정을 사용하는 경우 SessionFactory도 수동으로 생성할 수 있어.

 

예시 1: Spring Boot 자동 설정

 

Spring Boot에서는 보통 spring-boot-starter-data-jpa 의존성을 추가하면 Spring이 Hibernate와 JPA 설정을 자동으로 해줘서 별도로 SessionFactory Bean을 만들 필요가 없지만, 만약 SessionFactory를 직접 사용하고 싶다면 다음과 같은 방식으로 LocalSessionFactoryBean을 이용해 Bean을 생성할 수 있어.

 

예시 2: 수동 설정 (XML 설정 또는 자바 설정)

 

자바 설정 (Java Configuration)

@Configuration
public class HibernateConfig {

    @Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource); // 데이터 소스 주입
        sessionFactory.setPackagesToScan("com.example.model"); // 엔티티 패키지 스캔 경로 설정
        sessionFactory.setHibernateProperties(hibernateProperties()); // Hibernate 속성 설정
        return sessionFactory;
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/your_database");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        return dataSource;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        properties.put("hibernate.show_sql", "true");
        properties.put("hibernate.hbm2ddl.auto", "update");
        return properties;
    }
}

 

위 코드에서는 LocalSessionFactoryBean을 사용해 SessionFactory를 Bean으로 등록하고 있어. 주요 포인트는:

 

setDataSource(): 데이터베이스 연결을 위한 DataSource를 설정.

setPackagesToScan(): 엔티티 클래스들이 위치한 패키지를 지정해 Hibernate가 이 패키지를 스캔할 수 있게 해.

setHibernateProperties(): Hibernate에 필요한 설정을 제공하는 Properties 객체를 설정.

 

XML 설정 (구 버전 방식)

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="packagesToScan" value="com.example.model"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/your_database"/>
    <property name="username" value="root"/>
    <property name="password" value="password"/>
</bean>

 

XML 설정 방식은 요즘 자주 쓰이진 않지만, 여전히 사용 가능한 방식이야. 여기서 sessionFactory Bean은 자바 설정 방식과 비슷한 원리로 동작해.

 

요약:

 

Spring 환경에서 Hibernate의 SessionFactory를 만드는 가장 일반적인 방법은 LocalSessionFactoryBean을 사용해 SessionFactory를 Bean으로 등록하는 거야. 이 설정은 주로 Hibernate의 데이터베이스 연결, 엔티티 관리, 그리고 Hibernate의 속성 설정 등을 포함해. Spring Boot에서는 이러한 설정들이 대부분 자동으로 제공되기 때문에, 수동 설정은 Spring Boot가 아닌 환경이나 고급 커스터마이징이 필요할 때 주로 사용돼.


**ContextLoaderListener**는 Spring 애플리케이션에서 매우 중요한 역할을 하는 클래스로, Spring의 ApplicationContext를 초기화하고 관리하는 역할을 해. 주로 서블릿 기반의 웹 애플리케이션에서 사용돼.

 

역할 및 개념

 

**ContextLoaderListener**는 ServletContextListener를 구현한 클래스인데, 웹 애플리케이션이 시작될 때 Spring의 애플리케이션 컨텍스트(ApplicationContext)를 로드하고 초기화하는 역할을 해. 이 컨텍스트는 애플리케이션 내에서 Bean을 관리하고, 각종 의존성을 주입하는 중요한 컨테이너야. 웹 애플리케이션이 종료될 때는 컨텍스트를 정리해.

 

주요 기능

 

1. ApplicationContext 초기화:

ContextLoaderListener는 애플리케이션이 처음 시작될 때, web.xml 파일에서 지정된 Spring의 application context 파일을 읽어서 애플리케이션 전반에 걸친 Bean 설정을 로드하고 초기화해.

이를 통해 각종 서비스, 리포지토리, 데이터 소스, 트랜잭션 관리자 등 여러 구성 요소를 애플리케이션이 시작할 때 미리 설정하고 관리할 수 있게 돼.

2. 웹 애플리케이션과의 통합:

ContextLoaderListener는 서블릿 컨텍스트와 Spring의 애플리케이션 컨텍스트 간의 다리 역할을 해. 웹 애플리케이션이 시작될 때 서블릿 컨텍스트에 의해 호출되며, 이때 Spring의 애플리케이션 컨텍스트를 설정하는 데 사용돼.

3. 애플리케이션 종료 시 정리:

애플리케이션이 종료될 때 ContextLoaderListener는 애플리케이션 컨텍스트의 자원을 정리하고, 종료 처리도 담당해. 이를 통해 안전하게 애플리케이션을 종료할 수 있어.

 

web.xml에서의 설정

 

Spring 기반의 웹 애플리케이션에서는 web.xml 파일에 ContextLoaderListener를 등록해서 사용해. 예를 들어:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

 

<listener> 태그: 여기서 ContextLoaderListener를 리스너로 등록하고 있어. 이 리스너는 서블릿 컨텍스트가 초기화될 때 실행돼.

<context-param> 태그: contextConfigLocation은 Spring 애플리케이션 컨텍스트 파일의 경로를 지정해. 이 예시에서는 /WEB-INF/applicationContext.xml이 설정 파일로 지정돼 있는데, 이 경로에 있는 XML 파일을 읽어서 Bean 설정을 초기화하는 거야.

 

Spring Boot에서의 역할

 

Spring Boot에서는 기본적으로 ContextLoaderListener를 수동으로 설정할 필요는 없어. Spring Boot는 자동 설정을 통해 이 리스너의 역할을 내부적으로 처리해주기 때문에, 별도로 web.xml을 사용하지 않고도 애플리케이션 컨텍스트가 자동으로 관리돼.

 

ContextLoaderListener와 DispatcherServlet의 관계

 

ContextLoaderListener: 애플리케이션 전역에 걸친 Root ApplicationContext를 관리해. 주로 서비스, 데이터 소스, 리포지토리와 같은 전역적인 Bean을 관리하는 데 사용돼.

DispatcherServlet: Spring MVC 애플리케이션에서 사용되는 서블릿으로, 각 요청을 처리하고 컨트롤러를 호출하는 역할을 해. 각 DispatcherServlet은 자체적인 WebApplicationContext를 가질 수 있어, 즉 웹 요청과 관련된 Bean들을 따로 관리할 수 있는 거지.

 

간단히 말해, ContextLoaderListener는 애플리케이션이 시작될 때 전역적인 Spring 애플리케이션 컨텍스트를 초기화하고, DispatcherServlet웹 요청 처리에 특화된 컨텍스트를 관리해.

 

요약

 

**ContextLoaderListener**는 Spring의 애플리케이션 컨텍스트를 초기화하고 종료 시 정리하는 역할을 함.

주로 애플리케이션 전역의 Bean들을 관리하는 데 사용되며, web.xml을 통해 등록됨.

DispatcherServlet과 함께 사용되며, 전역 컨텍스트와 웹 요청을 처리하는 컨텍스트를 구분하여 관리함.

Spring Boot에서는 기본적으로 자동 설정이 되기 때문에, 수동 설정이 필요 없음.


**ServletContextListener**는 Java EE에서 서블릿 컨텍스트의 생명주기 이벤트를 처리하는 리스너 인터페이스야. 이 리스너는 웹 애플리케이션이 시작되거나 종료될 때 특정 작업을 수행하기 위해 사용돼. 예를 들어, 애플리케이션이 시작될 때 초기화 작업을 수행하거나 종료될 때 리소스를 정리하는 작업을 수행할 수 있어.

 

주요 역할

 

ServletContextListener는 두 가지 주요 메서드를 제공해:

 

1. contextInitialized(ServletContextEvent sce):

이 메서드는 웹 애플리케이션이 시작될 때 호출돼.

여기서 서블릿 컨텍스트를 초기화하고 필요한 자원을 설정하거나, 데이터베이스 연결을 열거나, 전역적으로 필요한 초기 데이터를 설정할 수 있어.

2. contextDestroyed(ServletContextEvent sce):

이 메서드는 웹 애플리케이션이 종료될 때 호출돼.

웹 애플리케이션이 종료되면서, 리소스를 해제하거나, 파일이나 데이터베이스 연결을 닫는 작업을 이 메서드에서 수행해.

 

ServletContextListener의 사용 예시

 

다음은 ServletContextListener의 기본 사용 예시야:

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyAppServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 애플리케이션 시작 시 초기화 작업
        System.out.println("웹 애플리케이션이 시작되었습니다.");
        
        // 필요한 리소스 또는 전역 변수를 초기화할 수 있음
        sce.getServletContext().setAttribute("globalVariable", "someValue");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 애플리케이션 종료 시 리소스 정리 작업
        System.out.println("웹 애플리케이션이 종료되었습니다.");
        
        // 파일이나 데이터베이스 연결 닫기
    }
}

 

@WebListener: 이 애노테이션은 ServletContextListener가 서블릿 컨텍스트에서 동작하도록 설정하는 역할을 해. web.xml에 설정하지 않고도 동작하게 만들어 줘.

contextInitialized: 애플리케이션이 시작될 때 호출되는 메서드로, 초기화 작업을 이곳에서 수행할 수 있어. 예를 들어, 전역 변수나 데이터베이스 연결 설정 등을 할 수 있지.

contextDestroyed: 애플리케이션이 종료될 때 호출되며, 여기서 자원을 정리하는 작업을 할 수 있어.

 

web.xml을 사용한 설정

 

애노테이션을 사용하지 않고, web.xml에 직접 설정할 수도 있어. 다음은 ServletContextListenerweb.xml에 설정하는 예야:

<listener>
    <listener-class>com.example.MyAppServletContextListener</listener-class>
</listener>

 

이렇게 설정하면 애플리케이션이 시작될 때 MyAppServletContextListener가 호출되고, 종료될 때도 마찬가지로 호출돼.

 

주요 사용 사례

 

1. 애플리케이션 초기화: 애플리케이션 시작 시, 필요한 전역 변수를 설정하거나 데이터베이스 커넥션 풀을 초기화하는 데 사용할 수 있어.

2. 리소스 정리: 애플리케이션 종료 시, 열려 있는 파일이나 데이터베이스 연결을 안전하게 닫는 데 사용돼.

3. 전역 설정 관리: 서블릿 컨텍스트에 전역적인 설정이나 데이터를 저장하고 애플리케이션 전반에서 참조할 수 있도록 설정할 수 있어.

 

요약

 

**ServletContextListener**는 서블릿 컨텍스트의 시작과 종료 시에 특정 작업을 처리하기 위한 리스너야.

**contextInitialized**는 애플리케이션이 시작될 때 호출되고, **contextDestroyed**는 애플리케이션이 종료될 때 호출돼.

주로 애플리케이션 시작 시 초기화 작업을 하고, 종료 시 자원을 정리하는 작업을 처리하는 데 사용돼.

애노테이션이나 web.xml을 통해 설정할 수 있어.

 

'Apache Tomcat' 카테고리의 다른 글

@RequestMapping handler method  (0) 2024.10.11
@GetMapping, @PostMapping  (0) 2024.10.08
@RestController, View Resolver, RESTful API  (0) 2024.10.08
Apache Tomcat Server  (1) 2024.10.07
Servlet, DispatcherServlet, Special Bean  (2) 2024.10.07
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유