반응형

잘 납품되었던 프로젝트 뼈대를 가져와서 다른 프로젝트를 또 만들고 만들고... 이렇게 하다보니 이전에 배웠던 스프링 개념도 많이 흐릿해지고 헷갈리게 되는것 같습니다.

시간이 지나면서 기존 개념도 많이 잊어먹었고, 요구사항에 맞게 스프링 설정을 하면서 어려움을 겪는 느낌이 들어 다시한번 공부를 하고 정리를 해보고자 합니다.(기초지만 역시 주기적으로 다시 봐주고 정리할 필요가 있는 것 같습니다.😎)

 

구동순서

1. was(톰캣 등)를 통해 프로젝트를 구동을 하게되면 해당 프로젝트 내부의 web.xml을 로드합니다.

web.xml은 서블릿 배포 기술자로 DD(Deployment Descriptor)라고도 불립니다. WEB-INF 디렉토리에 존재하며 웹 어플리케이션의 설정을 구성하고 있습니다.

webapp-WEB-INF에 위치합니다.

 

 

2. web.xml 파일을 로드하면서 Servlet Container가 구동됩니다.

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:egovframework/spring/context-*.xml</param-value>
</context-param>

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

<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/egovframework/springmvc/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

 

3. Servlet Container가 구동되면서 ContextLoaderListener클래스가 자동으로 메모리에 생성됩니다. 

ContextLoaderListener는 서블릿 이전에 서블릿을 초기화 시켜주며 contextConfigLocation을 설정파일들의 위치를 지정시켜줍니다.

 

4. contextConfigLocation는 공통으로 사용할 의존성 설정파일들을 지정하며, <param-value>부분에 파일 경로를 입력해주면 됩니다.

저는 전자정부프레임워크를 사용하면서 기본 위치가 'egovframework/springmvc/'으로 되어있고, dispatcher-servlet.xml읽도록 설정했습니다.

 

5. dispatcher-servlet.xml을 읽어서 새로운 Spring Container를 생성하고, Controller 객체를 메모리에 올립니다.

 

6. dispatcher-servlet.xml(servlet-context.xml) 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:task="http://www.springframework.org/schema/task"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
                http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
                http://www.springframework.org/schema/task
                http://www.springframework.org/schema/task/spring-task-3.0.xsd">
                
    <task:annotation-driven></task:annotation-driven>

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <context:component-scan base-package="egovframework"/>

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/jsp/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
</beans>

- annotation-driven: xml이 길고 복잡해지면서 대안으로 나타났습니다. 클래스, 메소드 등에 @를 달아 기능을 수행할 수 있도록 동작하기 위해 설정합니다. (xml Bean 등록이 더 우선순위가 높습니다.)

- mvc:annotation-driven: @Controller @RequestMapping 등 컨트롤러에서 해당하는 기능을 설정할 수 있게 해줍니다. 

- task:annotation-driven: @Scheduled 어노테이션을 사용을 위해 처리합니다.(스케줄러 관련)

- org.springframework.web.servlet.view.InternalResourceViewResolver: 컨트롤러가 모델을 리턴하고 DisapatcherServlet이 해당하는 파일을 처리할 때 필요한 정보를 기술하는 태그 접미사가 'WEB-INF/jsp'이면서 '.jsp'로 끝나는 파일들을 찾습니다. 

WEB-INF/jsp/login/login.jsp

- context:component-scan: 특정 패키지의 클래스들을 스캔하여 어노테이션을 확인하고 bean 등록을 한다. @Component @Controller @Service @Repository등이 클래스에 설정해야 등록된다.

 

 

 

 

 

웹 요청 동작순서

1. 사용자가 브라우저를 통해 주소를 입력합니다. - ( http://localhost/login.do )

web.xml에서 설정했던 정보에 맞는 요청일 경우 DispatcherServlet이 해당 요청을 먼저 가로채서 적합한 Controller에 매핑을 해줍니다.

 

2. <servlet-mapping/>부분이 있는데, 설정된 <servlet-name/>에 해당하는 매핑 설정을 할 수 있습니다.

예를들어 <url-pattern/>부분이 '/'으로 처리되어 있다면 모든 요청을 가로챕니다. 하지만 설정부분은 '*.do'로 되어있어서 'login.do'와 같은 형태만 적용이 됩니다.

 

3. 가로챈 매핑정보를 통해 처리할 Controller를 찾은 후, 적용된 코드에 따라 기능이 처리된다.

   3-1. Controller(mapping) -> View

   3-2. Controller(mapping) -> Service -> DAO -> mapper -> DB -> DAO -> Service -> Controller -> Return

 

4. 3-1과 같은 처리가 수행되면 ViewResolver에 의해 해당하는 view를 반환한다.

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/jsp/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>

dispatcher-servlet.xml에 설정된 ViewResolver부분에 맞는 prefix, suffix의 정보를 토대로 view페이지를 제공합니다.

(저는 tiles3를 적용해서 다르게 설정이 되어있습니다.)

@RequestMapping(value = "/login.do")
public ModelAndView login(ModelAndView mv) {
    mv.setViewName("login/login");
    return mv;
}

http://localhost/login.do -> '/WEB-INF/jsp/login/login.jsp'

 

5. 해당하는 viewDispatcherServlet에 보내면 DispatcherServlet은 클라이언트에게 데이터를 전송한다.

이때, 모델의 속성값이 있으면 같이 전송된다. (해당하는 값은 .jsp파일에서 ${변수명}을 통해 사용이 가능하다)

 

 

 

반응형