본문 바로가기
Spring/study

spring 2강 스프링의 실행 과정 / 디렉토리 구조 / 주요 특징

by avvin 2019. 5. 28.

spring 2강 스프링의 실행 과정, 스프링의 특징


Spring의 실행 과정


Dynamic Web Project에선 Web Content


Spring Legacy Project에선 src - main - webapp 


webapp - WEB-INF : 설정파일이 위치한곳// spring view(.jsp)가 위치해있다. (web.xml도 여기에)


가장 먼저 실행되는 파일

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
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
    <!-- 스프링의 환경설정 파일 로딩 -->
    <context-param> //가장 먼저 실행되는 부분 : root-context.xml
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 서블릿의 환경설정 -->
    <servlet>
        <servlet-name>appServlet</servlet-name> //DispatcherServlet은 스프링 프레임워크에 포함된 클래스
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param> //DispatcherServlet을 읽어들이고 모든 서블릿에 대한 요청을 DispatcherServlet가 처리함
            <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>
    <!-- 한글 처리를 위한 인코딩 필터 -->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
cs


root-context.xml > servlet-context.xml > ... 순으로 차례대로 실행




root-context.xml : DB 연결관련 소스코드 위치

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
<?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:context="http://www.springframework.org/schema/context"
    xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
    xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
    <!-- Root Context: defines shared resources visible to all other web components -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!-- 드라이버 클래스 이름이 변경됨 -->
        <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
        <!-- 연결문자열에 log4jdbc가 추가됨 -->
        <property name="url"
            value="jdbc:log4jdbc:oracle:thin:@localhost:1521:xe" />
        <property name="username" value="hr" />
        <property name="password" value="hr" />
    </bean>
    <!-- 아파치 DBCP 설정 -->
    <!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
        destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" 
        /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" /> 
        <property name="username" value="java" /> <property name="password" value="java1234" 
        /> </bean> -->
    <!-- SqlSessionFactory 객체 주입 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:/mybatis-config.xml"></property>
        <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property>
    </bean>
    <!-- SqlSession 객체 주입 -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"
        destroy-method="clearCache">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
    </bean>
 
</beans>
 
 
 
cs


context.xml ( jsp 공부할때 커넥션풀 사용시 server.xml에서만 DB설정 jsp인강 커넥션풀부분 다시 보기(버전 차이일 수 있음) )





JSP에서 서블릿 작성, 사용할 때  

1. web.xml 코드에 URL과 서블릿을 맵핑(대응)시키는 방법

2. 어노테이션 사용(최신버전만 가능)하는 방법


Spring에서는 1번 방식으로 수정했던 소스코드와 같이 web.xml에서 서블릿 설정을 하고 

서블릿에 대한 모든 요청은 DispatcherServlet(스프링 프레임워크에 포한된 클래스)에서 처리한다


servlet-context.xml : 웹 서비스 관련된 설정

막줄 <context:component-scan base-package="com.example.spring01" />

// com.example.spring01 : 이 패키지 안에 있는 모든 클래스들을 다 읽어들인다는 뜻


클래스 이름 상단에 @Controller 어노테이션이 붙어있으면 서블릿 클래스라는 뜻


@RequestMapping  ( value ="/" , method = RequestMethod.GET)

public String home( ... ) {

...

]

return "home"; // 정확히는 "/WEB-INF/views/home.jsp"; 인데 home 앞뒤 경로는 servlet-context.xml에 설정돼있다.

}


http://localhost/spring01/ <<  이 슬래시에서 위 home( ... ) 메서드 실행됨



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
30
<?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 http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://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>
    <!-- 스프링 빈을 태그로 등록하지 않고 자동으로 검색(auto scan) --> 
    <context:component-scan base-package="com.example.spring01" />
 
</beans:beans>
 
cs


Console 창

10:51:58.256 [http-nio-8090-exec-8] INFO [com.example.spring01.HomeController.home:27]-

Welcome home! The client locale is ko_KR.


HomeController.java

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.example.spring01;
 
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);
        //Console : 10:51:58.256 [http-nio-8090-exec-8] INFO [com.example.spring01.HomeController.home:27]-
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate ); // jsp 페이지에 formattedDate 넘김
        //request 안쓰고 MVC패턴의 Model(DB 관리 객체)로???
        return "home";
    }
    
}
 
cs


home.jsp // 위 HomeController.java 에서 serverTime 넘겨받음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Home</title>
</head>
<body>
    <h1>Hello world!</h1>
 
    <P>The time on the server is ${serverTime}.</P>
</body>
</html>
 
cs






스프링의 디렉토리 구조




- src / main / java : 자바 코드( Controller, Model, Service )


- src / main / resources : 자바코드에서 참조하는 리소스 파일들 ex)sqlMapConfig.xml, mybatis의 mapper 등 설정파일


- src / test / java : 테스트 관련 코드. 

클래스를 만들면 배포 전 테스트 과정을 거친다. Junit이라는 테스트 자동화 툴이 자동으로 테스트해준다.


- src / test / resources : 테스트 코드에서 참조하는 리소스 파일들


- src / main / webapp :  JSP의 Web Content 와 같은 공간, jsp파일 생성

웹서비스 루트 디렉토리 (외부에서 접근 가능)

WEB-INF에 있는건 시스템 디렉토리라서 외부에서 접근 못함. 


- webapp / WEB-INF :

WEB-INF에 있는 jsp파일에서는 바로 실행못하고 클래스를 경유해서만 실행시킬수 있다.

하지만 webapp 바로 아래 만든 jsp는 직접 접근(직접 실행)이 가능하다.


- webapp / WEB-INF / spring : 스프링의 환경 설정 파일


- webapp / WEB-INF / spring / root-context.xml : 서블릿과 관련되지 않은  모든 리소스에 대한 설정

- webapp / WEB-INF / spring / appServlet / servlet-context.xml : 서블릿과 관련된 리소스에 대한 설정

  ( root-context.xml / servlet-context.xml  별 차이는 없다. 

   코딩하다보면 설정이 많아지니까 나눠서 관리하는 것을 권장)


- webapp / WEB-INF / views : html, jsp 페이지 위치

(WEB-INF는 외부에서 접근불가능하므로 컨트롤러를 경유해서 접근가능)


- webapp / WEB-INF / classes : 컴파일된 클래스



- webapp / resources : js, css, iamge 등의 정적인 웹 리소스 파일 



- pom.xml : 메이븐에서 참조하는 설정 파일



스프링의 주요 특징


- POJO (Plain Old Java Object) 기반의 구성 : 별도의 API가 필요하지 않은 일반적인 자바 코드를 이용하여 개발 가능


- AOP ( Aspect Oriented Programming ) :  반복적인 코드를 줄이고 개발자가 비즈니스 로직에만 집중할 수 있도록 지원


- MVC 구조


- WAS(web application )에 종속적이지 않은 개발 환경




- 의존성 주입(DI)을 통한 객체 간의 관계 구성


-DI (Dependency InJection, 의존관계 주입)

- 객체 간의 의존성을 개발자가 설정하는 것이 아닌 스프링 컨테이너가 주입시켜주는 기능

- 객체를 쉽게 확장하고 재사용할 수 있음


강한 결합 :  

new를 통해 생성자를 직접 호출하여 객체를 생성하는 경우

생성자가 private 처리되면 생성자 호출 불가능


//B의 코드가 변경되면  A의 코드도 변경되는 경우 = A와 B는 의존 관계가 있다. = A는 B에 의존한다.

강한 결합은 유지보수가 어렵다.



느슨한 결합 :  

멤버 메서드 안에서 생성자를 선언하고 이 메서드를 호출하여 객체를 생성하는 경우, 

생성자가 프라이빗 처리돼도 객체 생성 가능


// B의 코드 변경이 A에 영향을 미치지 않도록 느슨하게 설계 


느슨한 결합 처리를 하기위해서 나온것이 DI (Dependency Injection)



-Ioc ( Inversion of Control, 제어의 역전 ) - 객체에 대한 제어권


- 기존에는 개발자에게 제어권이 있었음 (new 연산자로 객체 생성)

- 객체의 제어권을 스프링에게 넘김

- 인스턴스의 라이프사이클을 개발자가 아닌 스프링 프레임워크(스프링 컨테이너)가 담당


HomeController 객체를 생성한 적이 없는데도 프로젝트를 시작하면 알아서 실행된다.

@Controller 어노테이션이 있으면 가장 먼저 실행되는 web.xml에서 servlet-context.xml 을 실행하면서

컨트롤러 서블릿 클래스 ( 스프링 객체, '스프링 빈'이라고 한다 )를 읽어들이면서 메모리에 객체를 할당한다.


'Spring > study' 카테고리의 다른 글

JUnit Test 정리  (0) 2019.05.30
컨텍스트( context )  (0) 2019.05.30
spring 4강 Controller와 View의 연결 방법  (0) 2019.05.29
spring 3강 로깅, 데이터베이스 연결 테스트  (0) 2019.05.28
Spring 1강 개발 환경설정  (0) 2019.05.27