티스토리 뷰

Spring

스프링 동작방식

jalha 2019. 5. 31. 16:41

동작순서

1. 클라이언트가 URL로 접근하여 정보를 요청한다.

2. DispatcherServlet이 해당 요청을 매핑한 컨트롤러가 있는지 검색하도록 HandlerMapping에 물어본다.

(DispatcherServlet은 web.xml에 포함되어 있으며, Springframework에서 제공한다)

3. HandlerMapping은 해당 컨트롤러에 처리를 요청한다.

4. 컨트롤러에서는 service-dao-db-dao-service 간의 흐름을 타고 dto를 받는다.

(여기서 service와 dao는 model이라고하며, 컨트롤러, 뷰를 합쳐 mvc패턴이라고한다 )

5. 컨트롤러는 클라이언트의 요청을 처리하고 결과를 출력할 view의 이름을 DispatcherServlet으로 리턴한다.

6. DispatcherServlet은 컨트롤러에서 보내온 view이름을 토대로 처리해서 view를 검색할수있도록 ViewResolver한테 요청한다.

(ViewResolver는 설정파일에 포함되어있으며 Springframework에서 제공한다. prefix="/WEB-INF/jsp/" suffix=".jsp"등으로 쓰여져있다.)

7. ViewResolver는 처리결과를 View에 송신해 Client가 볼수있도록한다.

 

 

***xml파일간 흐름***

 

was(톰캣..) 실행( server start 눌렀을 때) 

1. web.xml(=서블릿 배포 기술자, DD, deployment descriptor)이 로딩된다.

2. web.xml에 등록된 ContextLoaderListener가 생성된다.

 

  • ContextLoaderListener는 java class로 ServletContextListener 인터페이스를 구현하고 있으며 부모는 ContextLoader다.
    • in web.xml...
<listener>
        <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class>
</listener>

위 코드를 작성하면 디폴트값으로 applicationContext.xml을 찾아서 모든 서블릿과 필터들이 공유하는 루트 컨텍스트를 생성한다.

 

만약 해당 파일이 없다면

org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml] 와 같은 에러가 발생할 수 있다.

 

applicationContext.xml말고 커스터마이징한 파일을 통해 만들고 싶다면

<!-- 자바파일을 쓰려면 AnnotationConfigWebApplicationContext를 추가해줘야한다. -->
	<context-param>
		<param-name>contextClass</param-name>
		<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
	</context-param>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>webGame.config.AppConfig</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
<!-- xml파일로 설정하려면 아래와 같이 설정할수있다. -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>webGame/config/applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

 

 

3. ContextLoaderListener는 applicationContext.xml(or Appconfig.java, root-context.ml)을 로딩한다.

  • ContextLoaderListener는 루트 웹 어플리케이션 컨텍스트(= bean factory)를 생성한다.
    • Root WebApplicationContext는 DAO, VO 등 웹과 독립적인 객체들을 담아둔다.
    • 웹어플리케이션 전체에 사용가능한 DB연결 등이 사용된다.

4. applicationContext.xml에 등록되어 있는 루트 스프링 컨테이너가 구동된다. 이때 개발자가 작성한 비즈니스 로직(serviceImple)에 대한 부분과 DAO, VO(= DTO)같은 웹과 관련없는 객체들이 생성된다.

 

요청 받았을 때

1. 요청을 받으면 web.xml에서 DispatcherServlet을 생성한다. 

  • 클라이언트로부터 요청 온 메시지를 분석하여 알맞은 PageController에게 전달하고 응답을 받아 요청에 따른 응답을 어떻게 할지 결정한다. (실직적인 작업은 PageController에서 이루어짐)
< !-- 프론트 컨트롤러 서블릿 배치하기 -- >
< !-- servlet-name을 맞춰야하며, 나중에 DispatcherServlet가 해당 이름의 *-servlet.xml을 로딩하게 된다.-- >
< servlet >
< servlet-name >app< /servlet-name >
< servlet-class >org.springframework.web.servlet.DispatcherServlet< /servlet-class >
< /servlet >
< servlet-mapping >
< servlet-name >app< /servlet-name >
< url-pattern >/< /url-pattern >
< /servlet-mapping >

 

2. DispatcherServlet는 app-context.xml(or WebConfig.java)을 로딩한다.

  • 이때 웹 어플리케이션 컨텍스트가 생성된다.
  • app-context.xml에서 컨트롤러, 뷰리졸버, 뷰, 핸들러 매핑 등 설정을 한다.
  • @RequestMapping에 대해 핸들러 매핑이 수행된다. 어떤 URL이 올때 어떤 메서드를 실행하겠다는 매핑 테이블을 만드는 것이다. 한번 init()을 통해 매핑 테이블이 등록되면 이후엔 service()만 실행해서 사용된다.
< !-- XML 설정 파일에서는 페이지 컨트롤러 객체만 생성한다. -- >
    < context:component-scan base-package="webGame"/ >
    
    < !-- 기존의 ViewResolver를 교체하기
                    이 ViewResolver는 request handler가 리턴한 경로의
                    앞, 뒤에 공통 경로를 추가하여 JSP 파일을 찾아 실행한다.
    -- >
    < bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        < property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/ >
        < property name="prefix" value="/WEB-INF/jsp/"/ >
        < property name="suffix" value=".jsp"/ >
    < /bean >

 

3. 두번째 스프링 컨테이너가 구동되며 응답에 맞는 pageController들이 동작한다. 이때 첫번째 스프링 컨테이너가 구동되면서 생성된 DAO, VO, serviceImpl클래스와 협업하여 처리하게 된다.

  • service()메서드가 실행되어 DispatcherServlet은 Handlermapping에게 질의를 하고, 어떤 URL요청에 대하여 어떤 메서드를 수행해야 할지 분기시킨다.
  • 컨트롤러는 return에 작성된 분기명을 보고 응답할 view를 찾기 위해 viewresolver에게 질의를 해서 view객체를 반환받고 전달할 데이터를 추가하여 클라이언트에게 응답한다.

※ 각 컨테이너 객체(루트 애플리케이션컨텍스트, 애플리케이션컨텍스트)는 싱글톤이며 thread safe(멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없음을 뜻함. 하나의 함수가 한 스레드로부터 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하여 동시에 함께 실행되더라도 각 스레드에서의 함수의 수행 결과가 올바로 나오는 것)하다. (그래서 인스턴스 변수(클래스변수)가 없는 것이다.)

 

 

 

 

 

 

Spring boot 에서의 과정

 

Spring boot는 내부적으로 내장 톰켓을 가지고 있다. 즉 스프링 부트가 실행되면서 내부적으로 내장톰켓(서블릿 컨테이너)가 실행된다. 

Spring boot는 ServletContainerInitializer를 구현한 TomcatStarter의 onStartup 메소드를 먼저 실행한다.

 

DispatcherServletAutoConfiguration.class에 구성되어져있는 DispatchServlet 빈 등록으로 자동 등록되어진다. 

  • DispatcherServlet이 스프링에 빈으로 등록되어진다.
  • 서블릿 컨테이너 컨텍스트에 서블릿을등록한다.
  • 서블릿 컨테이너 필터에 등록설정 해놓은 필터들을 등록한다.
  • 디스팻처서블릿에 각종 핸들러 매핑이 된다.(컨트롤러 빈들이 다 생성되어 싱글톤으로 관리되어진다.)

실행만 했는데

 

 

디스패처 서블릿이 생성되면서 WebapplicationContext가 생성된다. 하나는 dispatch에 의해 생성되는 WebApplicationContext이며, 다른 하나는 스프링에 ContextLoader에 의해 생성되는 Root WebapplicationContext가 있다.

 

위와 같이 spring boot에서는 실행과 동시에 컨테이너 객체 두개가 구동된다는 것을 알 수 있다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함