ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 학원 day86. 스프링 웹 구축하기
    기록 2023. 1. 4. 12:53

    지금 사용하는건 스프링 5.3.6버전인데 스프링 6부터는 톰캣 10을 지원한다.

    자바 17을 사용하는데 현장에서는 자바8이다. 

    톰캣 9버전(9.0.70)을 다운받을 것이다.

    이클립스 Preference 열어서 톰캣을 등록한다.

    eGovFrame Web Project를 클릭하고 톰캣 9로 설정


    - 개발자가 만드는 것 : JSP, Controller, Service, Mapper

    - DispatcherServlet이 생성하는 건 자식 스프링 컨테이너이고, ContextLoadListener가 생성하는 건 루트 스프링 컨테이너이다.

    - 자식 스프링 컨테이너에는 주로 웹과 관련된 것들이 등록되어 있다. (컨트롤러, 뷰, 인터셉트, 리졸브)

    - 자식 스프링 컨테이너는 의존성 주입에 필요한 객체가 자식 스프링 컨테이너에 존재하지 않으면, 루트 스프링 컨테이너에서 찾아서 의존성 주입을 수행한다.

    - 스프링 컨테이너 사이의 계층 관계가 존재한다.

    - 자식 스프링 컨테이너는 루트 스프링 컨테이너에 있는 것을 주입이 가능하다.

    (반면, 루트 스프링 컨테이너는 자식 스프링 컨테이너에 있는 것을 가져오지 못한다.)

    - 루트 스프링 컨테이너는 어디에서나 접근할 수 있어야 되므로 ServletContext에 담겨있다.

    - DispatcherServlet과 Controller 사이에는 내부적으로 많은 것들이 존재한다.

     

    DispatcherServlet

    * HTTP 요청 접수

    * Controller 객체를 검색하고, 요청핸들러 메소드를 실행

    * 요청핸들러 메소드의 반환값을 분석해서 내부이동/재요청 URL 전송

     

    * HTTP 요청을 처리할 Controller 객체는 스프링 컨테이너에 포함되어 있다.

    * DispatcherServlet은 HTTP 요청을 분석해서 해당 요청을 처리할 Controller 객체를 스프링 컨테이너에서 가져온다. (getBean() 사용)

     

    Controller

    * Http 요청 처리

    * 요청파라미터값 처리

    * 폼 입력값 유효성 검증

    * 업무로직 메소드 실행 

    * 뷰에 표현할 데이터 담기

     

    * 뷰이름/재요청 URL 반환

     

    Service

    * 핵심 업무로직 수행

    * 업무로직 수행에 필요한 DB 엑세스 메소드 호출

    * 뷰에 표현할 데이터 반환

     

    Mapper 인스턴스

    * 데이터베이스 액세스 작업 정의/구현


    spring mvc의 주요 어노테이션

    @Controller

       - 클래스가 HTTP 요청을 처리하는 Controller 클래스임을 나타낸다.

       - <context:component-scan />으로 자동 스캔되어서 스프링 컨테이너의 빈으로 등록된다.

    @GetMapping

       - 요청 URI와 요청 핸들러 메소드를 매핑시킨다.

    /home이라는 URL이 오면 DispatcherServlet이 자기가 만들어놓은 Controller 중에서 매핑정보에 /home이 있는것을 찾는다.

    HomeController의 요청핸들러 메소드 중에서 "/home"과 매핑되어 있는 요청 핸들러 메소드(HTTP요청을 처리)를 실행한다.

    web-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:context="http://www.springframework.org/schema/context"
    	xmlns:mvc="http://www.springframework.org/schema/mvc"
    	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.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.3.xsd">
    
    	<!-- 
    		<mvc:annotaion-driven> 태그는
    			spring mvc 관련 어노테이션 감지/분석해서 적절한 작업을 수행하는 객체를 스프링의 빈으로 등록시킨다.
    	 -->
    
    	<mvc:annotation-driven></mvc:annotation-driven>
    	
    	<!-- 
    		<mv:view-resolvers/> 태그는
    			spring mvc가 지원하는 다양한 뷰-탬플릿기술(모델의 데이터를 표현하는 기술)에 대한 설정을 지원하는 태그다.
    	 -->
    	 <mvc:view-resolvers>
    	 	<!-- 
    	 		<mvc:jsp /> 태그는
    	 			Controller의 요청핸들러 메소드가 반환하는 뷰 이름("home")을 실제 JSP 경로에 맞게 맞추도록 
    	 			prefix="/WEB-INF/view/"와 suffix=".jsp"를 지정한다.
    	 			InternalResourceViewResolver 객체의 prefix와 suffix값을 설정한다.
    	 	 -->
    	 		<mvc:jsp prefix="/WEB-INF/views/" suffix=".jsp"/>
    	 </mvc:view-resolvers>
    	
    	<!-- 
    		<context:component-scan /> 태그는
    			com.sample.web 패키지에서 클래스를 스캔해서 스프링 컨테이너의 빈으로 등록시킨다.
    			이 애플리케이션에서 com.sample.web.controller 패키지에 모든 Controller 클래스를 스캔해서 스프링 컨테이너의 빈으로 등록시킨다.
    	 -->
    	<context:component-scan base-package="com.sample.web" />
    
    </beans>

    스프링이 Model이라는 객체를 만들어서 전달해준다. 

    JSP, Freemarker, Files, Thymeleaf 라는 기술들이 HTML형식의 데이터를 전해주는 용도로 사용된다. HTML 문서를 만들 때 사용되는 템플릿, 뷰 템플릿이라고 한다.

     

    모델 : 데이터를 가져올 저장소

    뷰 : 모델의 데이터를 특정 컨텐츠 타입으로 변환하는 객체

    뷰 템플릿 : JSP, Freemarker, Files, Thymeleaf (모델에 들어있는 값을 표현)

     

    제일 처음부터 request에 담으면 JSP만 사용가능하다.

    따라서, Controller가 보낸 데이터는 무조건 Model에 넣기로 한다.

    뷰가 Model에서 데이터를 가져온다. 모델에 있는 값을 바꿔준다.

    화면이 있는 것은 템플릿이 필요하다.

     

    Model

    - 컨트롤러가 비즈니스 로직 수행결과로 획득한 데이터는 다양한 형식의 컨텐츠로 변환되어 전달된다.

    - 다양한 형식 만큼 다양한 뷰 객체들이 존재한다.

    - 뷰 객체는 컨텐츠 형식이나 뷰 템플릿의 종류에 상관없이 일관되게 Model 객체에서 필요한 정보를 획득할 수 있게 한다.


    web.xml
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
    
    	<!-- 
    		Root WebApplicationContext 생성하기
    			* <context-param />태그에 spring bean configuration 파일의 경로 및 이름을 지정한다. (웹에 관련된 거 빼고 지정)
    			* <listener />태그에 ContextLoaderListener 클래스를 등록한다.
    			* ContextLoaderListener
    				* 리스너 클래스다.
    				* <context-param />태그에 contextConfigLocation으로 설정된 빈 설정정보를 읽어서 루트 스프링 컨테이너를 생성한다.
    				
    		* Listener
    			* Java Servlet API다.
    			* Java Servlet의 이벤트처리를 지원하는 인터페이스다.
    			* 리스너 인터페이스의 종류
    				ServletContextListener
    					ServletContext객체가 초기화될 때, 소멸될 때 실행할 작업을 구현하는 클래스는 이 인터페이스를 구현한다.
    					* Servletcontext는 웹서버가 실행될 때 초기화된다. -> 웹서버가 실행될 때 수행할 작업을 구현할 때 이 리스너를 구현한다.
    					* 스프링의 ContextLoaderListener은 이 인터페이스를 구현한 클래스이기 때문에
    					  웹서버가 실행될 때 수행할 작업(빈 설정파일 로드, 스프링 컨테이너 생성)이 구현되어 있다.
    				ServletContextAttributeListener
    					ServletContext객체에 속성이 추가/삭제/변경될 때 실행할 작업을 구현하는 클래스는 이 인터페이스를 구현한다.
    				HttpSessionListener 
    					HttpSession객체가 생성될 때, 소멸될 떄 실행할 작업을 구현하는 클래스는 이 인터페이스를 구현한다.
    				HttpSessionAttributeListener
    					HttpSession객체에 속성이 추가/삭제/변경될 때 실행할 작업을 구현하는 클래스는 이 인터페이스를 구현한다.
    				HttpletRequestListener
    				    HttpSession객체가 저장될 객체가 이 인터페이스를 구현하는 이 객체가 속성으로 추가/삭제될 때 실행할 작업을 구현할 수 있따.
    				ServletRequestListener
    					요청객체가 초기화될 때, 소멸될 때 실행할 작업을 구현하는 클래스는 이 인터페이스를 구현한다.
    				ServletRequestAttributeListener		
    					요청객체에 속성이 추가/삭제/변경될 때 실행할 작업을 구현하는 클래스는 이 인터페이스를 구현한다.
    	 -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>
             /WEB-INF/spring/database-context.xml
             /WEB-INF/spring/service-context.xml
          </param-value>
    	</context-param>
    
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    	<!-- 
    		한글 인코딩처리를 지원하는 필터를 설정한다. 필터는 서블릿 실행되기 전에 실행된다.
    	 -->
    	<filter>
    		<filter-name>encodingFilter</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>encodingFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    	<!-- 
    		DispatcherServlet은 spring mvc가 제공하는 FrontController이다.
    		* 모든 URL 요청에 대해서 (<url-pattern>/</url-pattern>) DispatcherServlet이 실행되도록 설정함
    		* 아래의 설정정보에 지정된 web-context.xml 파일을 읽어서 DispatcherServlet이 스프링 컨테이너를 생성하게 한다. 
    		  스프링 컨테이너에는 web-context.xml에 설정된 클래스들이 스프링 컨테이너의 빈으로 등록된다.
    		  스프링 컨테이너의 빈으로 등록된 객체들 중에는 HomeController, UserController, PostController 등 다양한 컨트롤러 객체가 포함되어 있다.
    		  DispatcherServlet은 요청이 접수되면 요청 URI에 해당하는 매핑정보가 포함된 컨트롤러 객체를 스프링 컨테이너에서 가져와서 실행시킨다.
    			<init-param>
    				<param-name>contextConfigLocation</param-name>
    				<param-value>/WEB-INF/spring/web-context.xml</param-value>
    			</init-param>
    			
    		* 웹서버가 실행될 때 DispatcherServlet 객체를 생성하고, 초기화시키기 
    			<load-on-startup>1</load-on-startup>
    			* 숫자 1은 우선순위를 나타낸다. 서블릿객체를 여러개 등록하는 경우 숫자가 낮을 수록 먼저 생성되고 초기화된다. 
    			* 웹서버가 켜질 때 DispatcherServlet 객체를 생성하고, 초기화 작업을 완료시키기 위해서 설정한다.
    			* DispatcherServlet 초기화 과정에서 <init-param />태그의 정보를 읽어서 Spring Container를 생성하고, 
    			  설정정보를 분석해서 필요한 객체를 생성하고, 조립한다.
    	 -->
    	<servlet>
    		<servlet-name>app</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>/WEB-INF/spring/web-context.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet-mapping>	
    		<servlet-name>app</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    	
    	<!-- 
    		모든 JSP의 첫부분에 /WEB-INF/views/commons/tags.jsp의 내용을 포함시킨다.
    	 -->
    	<jsp-config>
    		<jsp-property-group>
    			<url-pattern>*.jsp</url-pattern>
    			<include-prelude>/WEB-INF/views/common/tags.jsp</include-prelude>
    		</jsp-property-group>
    	</jsp-config>
    	
    </web-app>

    DispatcherSevelet이 요청을 받으면 HandlerMapping에게 요청 URI를 보낸다.

    그러면 HandlerMapping은 뭐를 실행해야 하는지 컨트롤러(요청핸들러 메소드)를 반환한다.

    즉, HandlerMapping의 역할은 요청 URI와 매핑된 컨트롤러를 반환하는 것이다. 

     

    또한, DispatcherSevelet은 HandlerAdapter에게 컨트롤러 실행을 위임한다. 

    HandlerAdapter 안에는 우리가 만들어놓은 HomeController가 들어있다.

     

    HandlerAdapter는 컨트롤러를 실행하기 위해 Model 객체를 만든다. 그리고 요청핸들러메소드에 model을 전달한다.

    Model 바깥에 있는 객체가 ModelAndView객체이다. Map계열의 객체이기 때문에 name:value 형식으로 값이 저장되어 있다. model이라는 변수 아래 Model객체가 들어있고, 

    View view 라는 변수와, String viewName 이라는 변수도 있다.

     

    HomeController가 실행하고나면 ModelAndView 객체가 생성된다.

    그리고 DispatcherServlet에게 ModelAndView를 반환한다.

     

    스프링 MVC에서는 기본 view객체가 정해져 있다. 

    그런데 view가 null이면,

    DispatcherServlet은 ViewResolver에게 뷰이름인 "home"을 보내면서 질의를 한다.

    ViewResolver에는 기본 ViewResolver 객체인 InternalResourceViewResolver를 사용한다.

    InternalResourceViewResolvers는 InternalResourceView, JstlView,  RedirectView라는 기본 View 객체 3가지를 갖고 있다.

    InternalResourceViewResolvers는 뷰이름이 redirect: 로 시작하면 RedirectView 객체를 반환한다. RedirectView에는 재요청할 URL이 포함되어 있다.

    뷰이름이 Redirect:로 시작하지 않으면 뷰이름의 앞에 "/WEB_INF/views/"를 붙이고, 뷰이름의 뒤에 ".jsp"를 추가하고, JstlView를 반환한다. JstlView에는 내부이동할 jsp 경로가 포함되어 있다. 

     

    ( HandlerMapping에도 RequestMappingHandlerMapping이라는 기본 핸들러매핑객체가 있다.

     

    HandlerAdaper에도 RequestMappingHandlerAdaper라는 기본 핸들러어댑터가 있다. )

     

    DispatcherServlet은 뷰(JstlView)를 실행시키는데 

    JstlView는 Model에 저장된 정보를 요청객체의 속성에 저장시킨다.

    /WEB-INF/views/home.jsp로 내부이동시킨다.

     

    그리고 우리가 만든 home.jsp가 EL, JSTL로 요청객체에 저장된 정보를 표현하고 사용자에게 html컨텐츠를 보낸다.

     


    [요약]

    spring mvc 프로젝트 생성하고, 홈페이지 연결하기


    1. 전자정부 표준 프레임워크 지원 이클립스에서 eGovframee web proejct 메뉴로 프로젝트를 생성한다.
    2. pom.xml에 의존성 정보를 추가한다.

    3. spring-webmvc용 Bean Configuration 파일 정의하기
         * src/main/webapp/WEB-INF 폴더에 spring 폴더를 추가한다.
         * spring 폴더에 spring bean configuration 파일을 추가한다. 파일명은 web-context.xml이다.
         * web-context.xml의 namespace 탭에서 context와 mvc를 체크한다.
         * spring-mvc 빈 설정하기
                  * spring mvc 어노테이션을 활성화시키는 빈을 등록시키는 태그를 추가한다.
                           <mvc:annotation-driven></mvc:annotation-driven>
                  * InternalResourceViewResolver의 prefix와 suffix값을 설정한다.
                           <mvc:view-resolvers>
                                         <mvc:jsp prefix="/WEB-INF/views/" suffix=".jsp"/>
                           </mvc:view-resolvers>
                  * Controller를 스캔해서 스프링 컨테이너의 빈으로 등록시키는 태그를 추가한다.
                           <context:component-scan base-package="com.sample.web" />
    4. web.xml 정의하기
        * src/main/webapp/WEB-INF 폴더에 web.xml 파일을 추가한다.
        * DispatcherServlet을 설정한다.

    5. jsp 정의하기
    * src/main/webapp/WEB-INF 폴더에 view 폴더를 추가한다.
    * views 폴더에 home.jsp를 추가한다.
    6. 컨트롤러 정의하기
    * src/main/java 소스 폴더에 com.sample.web.controller 패키지를 추가한다.
    * 생성한 패키지에 HomeController 자바클래스를 생성한다.
    * 예시
    package com.sample.web.controller;

    @Controller
    public class HomeController {

    @GetMapping("/home")
    public String home(Model model) {
    model.addAttribute("msg", "안녕하세요");
    return "home";
    }

    }
    7. 5번에서 정의한 home.jsp에 코드 추가하기
    <h1>애플리케이션 홈</h1>
    <p>${msg}</p>
    8. 브라우저에서 홈화면 요청하기
    * http://localhost:8080/spring-web/home

    댓글

Designed by Tistory.