본문 바로가기

웹개발/설정

Spring MVC Project 구조 분석

* 스프링 프레임 워크

1. 스프링은 POJO (Plain Old Java Object) 방식의 프레임워크로서, 일반적인 J2EE 프레임워크에 비해 특정 라이브러리를 사용할 필요가 없어서 개발이 쉬우며, 기존 라이브러리의 지원이 용이합니다.

 

2. 스프링은 관점지향프로그래밍, AOP(Aspect Oriented Programming)를 지원합니다. 트랜잭션, 로깅, 보안 등 여러 모듈, 여러 계층에서 적용되는데, 이런 코드들을 실제 비지니스 로직과 분리할 수 있도록 도와줍니다. 한때, AOP가 OOP(Object Oriented Programming)를 대체하는 기술로 생각되기도 했지만, 실제로 AOP는 OOP를 더욱 OOP스럽게 보완해 주는 기술입니다.

 

3. 스프링은 의존성 주입, DI (Dependency Injection)를 지원합니다. 이는 객체간의 의존관계를 관리하는 기술이라고 생각하면 됩니다. 어떤 객체가 필요로 하는 객체를 자기 자신이 직접 생성하는것이 아니라, 외부에 있는 다른곳에서 자신이 필요로 하는 객체를 주입받는것을 말합니다.

 

4. 스프링은 제어 반전, IoC (Inversion of Controller)를 지원합니다. 컨트롤의 제어권이 개발자가 아니라 프레임워크에 있음을 말합니다. 즉, 객체의 생성부터 모든 생명주기의 관리까지 객체의 제어권이 바뀐것을 의미합니다.

출처 : http://addio3305.tistory.com/36?category=772645

 

스프링에서 MVC를 쓰는 이유는 스프링이 제공하는 트랜젝션, DI, AOP를 손쉽게 사용하기 위해서라고 한다. 그리고 스트럿츠와 같은 프레임워크와 연동하려면 설정의 중복과 개발 과정에서 오는 불편함들을 줄일 수 있다고 한다. 스프링도 다른 MVC 프레임워크와 같이 컨트롤러를 사용하여 클라이언트의 요청을 처리하는데, 이 컨트롤러의 역할을 DispatcherServlet에서 한다. 그럼 이제 스프링 MVC 구조를 살펴보자

 

 구성 요소  설명 
 DispatcherServlet  클라이언트의 요청을 전달받아 요청에 맞는 컨트롤러가 리턴한 결과값을 View에 전달하여 알맞은 응답을 생성 
 HandlerMapping  클라이언트의 요청 URL을 어떤 컨트롤러가 처리할지 결정 
 Controller  클라이언트의 요청을 처리한 뒤, 결과를 DispatcherServlet에게 리턴 
 ModelAndView  컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담음 
 ViewResolver  컨트롤러의 처리 결과를 생성할 뷰를 결정 
 View  컨트롤러의 처리 결과 화면을 생성, JSP 또는 Velocity 템플릿 파일 등을 뷰로 사용 

 

출처: 갱짱.Study

 

그림 001. Java Source 디렉토리 

그림 002. Spring 설정 및 쿼리 디렉토리

그림 003.  테스트 풀더

그림 004. 스프링 설정 파일

                  - servlet-context.xml : Spring Container 가동 설정

                  -  root-context.xml : Spring Container 가동 설정

                     -  component-scan 과 / @Controller , @Service.... / @Autowired

그림 005. JSP 디렉토리

 

그림 006. 톰켓 프로젝트 설정 파일

그림 007. 외부 라이브러리 설정 파일

 


1. Maven Dependencies

 

 Maven에서 자동적으로 받아오는 라이브러리들을 확인할 수 있는 곳이다. 프로젝트를 진행하다 보면 이러한 라이브러리를 추가하여 다운받아야 할 경우가 생긴다. 그럼 필요한 라이브러리를 직접 다운받아서 해당 폴더에 넣느냐? 그렇지 않다. 프로젝트 내에서 태그를 이용해 간단히 추가하거나 삭제할 수 있다. pom.xml이 이러한 라이브러리를 추가하고 관리할 수 있는 곳이다. pom.xml을 한번 살펴보자.

맨 밑에 있는 pom.xml을 열어보자

<properties></properties> 태그는 변수의 개념으로 많이 사용되는 변수를 선언해서 밑에서 편하게 쓰기 위해서이다. 많이 사용되는 값을 변수로 지정한다. 수정의 용이함이 있기에 일일이 찾아서 수정할 필요가 없다. <org.springframework-version>3.1.1.RELEASE</org.springframework-version> 처럼 변수 선언을 해 놓으면 밑에서 ${org.springframework-version}로 사용할 수 있다. 만약 버전이 바뀌면 선언한 곳의 버전만 수정해주면 된다.

 

<repositories></repositories> 태그도 있는데, 실제 라이브러리를 다운 받을 장소를 의미한다. 따로 설정할 필욘 없다. 만약 인터넷이 없는 곳에서 프로젝트를 진행하게 되면 내부 저장소를 만들고, 내부 저장소에서 라이브러리를 다운 받는다고 한다. 

 

<dependency></dependency> 태그는 라이브러리 하나를 의미한다. 가장 알아둬야 할 중요한 태그이다. 이 태그를 이용해서 라이브러리를 추가하거나 삭제할 수 있다. 번거롭게 원하는 라이브러리를 직접 다운받아 폴더에 넣지 않아도 태그 하나로 라이브러리를 추가할 수 있다.

 

2. Web.xml

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
32
33
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 
    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml</param-value>
    </context-param>
    
    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 
    <!-- Processes application requests -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
        
    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
 
</web-app>
cs

web.xml은 tomcat(WAS)이 최초 구동될 때, WEB-INF 디렉토리에 존재하는 web.xml을 읽고, 그에 해당하는 웹 어플리케이션 설정을 구성한다.

- 스프링 context 설정 (7~10행) contextConfigLocation

스프링 context 설정파일 목록을 불러오기 위한 곳이다. 9행에서는 context 경로를 설정할 수 있는 곳이다.

 

- DispatcherServlet 설정 (18~26행)

<servlet> 태그를 이용해서 DispatcherServlet를 설정할 수 있다. 23행의 경로를 통해 스프링 설정 정보를 읽어온다.

 

- 요청URL (28~31행)

요청 URL 패턴(30행)을 설정한다. 서블릿에서 어떠한 요청을 할 때, 이 패턴을 통해서만 요청이 전달된다. .html 등의 직접적인 요청은 전달되지 않는다.

 

3. servlet-context.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />
 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />
 
    <!-- 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/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    
    <context:component-scan base-package="com.spring.novice" />
    
    
    
</beans:beans>
 
cs

서블릿이란 간단하게 말하면 자바에서 동적 웹 프로젝트를 개발할 때, 사용자의 요청와 응답을 처리해주는 역할을 한다.

- ViewResolver 설정 (19~22행)

Controller 에서 ModelAndView로 뷰이름을 설정하는데 이 뷰이름과 매칭되는 것을 찾기 위해 사용된다. Controller에서 처리한 결과를 생성할(보내줄) View를 결정한다. 서블릿 설정이 자동으로 prefix와 suffix를 붙이는 역할을 한다. 이것으로 인해 우리가 일일이 전체경로와 .jsp를 붙이지 않도록 도와준다. 원래는 경로마다 /WEB-INF/views/home.jsp 이런식으로 사용해야하는데, 이걸로 인해서 우리는 간단하게 home만 사용하면 여기서 자동으로 붙여서 보내준다.

 

- Bean 설정 (24행)

스프링에서 사용하는 Bean을 일일이 xml 선언하지 않고 필요한 것을 어노테이션(Annoation)을 자동으로 인식하게 해준다.

 

4. root-context.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- Root Context: defines shared resources visible to all other web components -->
        
</beans>
 
cs

지금은 아무것도 없지만 스프링 관련 여러가지 설정 파일들을 등록하여 읽을 수 있는 곳이다. 구조를 재정의 하면서 context-*.xml로 변경하여 여러 설정 파일들을 등록할 것이다

 

5. Controller

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
32
33
34
35
36
37
38
39
40
package com.spring.novice;
 
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
    
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    
    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "home";
    }
    
}
 
cs

- @Controller (17행)

Controller 어노테이션(Annoation)을 설정한 것이다. 웹 클라이언트에서 들어온 요청을 해당 비즈니스 로직으로 분기시켜주고, 수행 결과의 응답을 해주는 Dispatcher 역할을 한다.

Annotaion 설명 참고 : http://www.nextree.co.kr/p5864/

 

- @RequestMapping (25행)

웹 클라이언트에서 들어온 요청에 해당하는 비즈니스 로직을 찾아주는 역할을 한다. value에 적힌 게 요청url인데, jsp에서 주는 경로와 다르르면 찾지를 못하기 때문에 오타나 url주소에 주의하자. method에 GET방식인지 POST방식인지 알 수 있다. 대부분 POST 이기에 지워도 무방하다. 

 

- ModelAndView (34, 36행) Model

34행은 비즈니스 로직을 수행한 결과를 화면에 보내주는 역할이다. serverTime이라는 이름으로 formattedDate를 전송함을 의미한다.

36행은 수행 결과를 어디로 보내줄 지 명시하는 곳이다. home은 home.jsp파일을 의미하고 서블릿 설정에서 자동으로 앞에 "/WEB-INF/views/"를 붙여주고(prefix), 뒤에 ".jsp"를 붙여준다(suffix). ModelAndView는 다양한 형태가 존재한다.

 

6. JSP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
    <title>Home</title>
</head>
<body>
<h1>
    Hello world!  
</h1>
 
<P>  The time on the server is ${serverTime}. </P>
</body>
</html>
 
cs

- ModelAndView (12행) View

Controller에서 34행에 model.addAttribute("serverTime", formattedDate ); 부분이 있었다. serverTime이라는 이름으로 formattedDate를 전송함(결과값)을 의미했는데, model로 보내진 serverTime이 view에서 ${serverTime} 방식으로 사용됨을 볼 수 있다. ${serverTime} 부분에서 서버에서 넘어온 결과(formattedDate)를 화면에 보여준다.