반응형

출처: http://blessldk.blogspot.kr/2015/01/spring-framework-dao.html


DTO 와 DAO

DAO(Data Access Object)는 DB를 사용해 데이터를 조화하거나 조작하는 기능을
전담하도록 만든 오브젝트를 말한다.

 사용자는 자신이 필요한 Interface를 DAO에게 던지고 DAO는 이 인터페이스를
구현한 객체를 사용자에게 편리하게 사용 할 수 있도록 반환해줍니다.

 DB에 대한 접근을 DAO가 담당하도록 하여 데이터베이스 엑세스를 DAO에서만
하게 되면 다수의 원격호출을 통한 오버헤드를 VO나 DTO를 통해 줄일 수 있고
다수의 DB 호출문제를 해결할 수 있습니다. 또한 단순히 읽기만 하는 연산이므로
트랜잭션 간의 오버헤드를 감소할 수 있습니다.


DTO(Data Transfer Object)는 VO(Value Object)로 바꿔 말할 수 있는데
계층간 데이터 교환을 위한 자바빈즈를 말한다. 여기서 말하는 계층간의
컨트롤러, 뷰, 비즈니스 계층, 퍼시스턴스 계층을 말하며 각 계층간 데이터 교환을
위한 객체를 DTO 또는 VO라고 부른다.

대표적인 DTO로는 폼데이터빈, 데이터베이스 테이블빈 등이 있으며, 각 폼요소나,
데이터베이스 레코드의 데이터를 매핑하기 위한 데이터 객체를 말한다. 즉 폼 필드들의 
이름을 그대로 가지고 있는 자바빈 객체를 폼 필드와 그대로 매핑하여 비즈니스 계층으로
보낼 때 사용하나다. 이런 객체를 DTO라고 부르며 VO(Value Object) 패턴이라고도 한다.
VO 패턴은 데이터 전달을 위한 가장 효율적인 방법이지만, 클래스 선언을 위해 많은 
코드가 필요하다는 단점이 있다.

일반적인 DTO는 로직을 갖고 있지 않다. 순수한 데이터 객체이며 속상과 그 속성에
접근하기 위한 getter, setter 메소드만 가진 클래스를 말한다. 여기에 추가적으로 
toString(), equals(), 등의 Object 클래스 메소드를 작성할 수 있다.

즉, 계층 간의 데이터 전달에 사용하는 데이터 객체들을 말한다.

1. DTO 클래스 예제

public class DTOBean {

private String name;

private int value;

private String data;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}

public String getData() {
return data;
}

public void setData(String data) {
this.data = data;
}
}

2. DAO 클래스 예제



//DB와 연결할 Connection을 가져온다.
//어떤 DB를 사용할 것이며, 어떤 드라이브와 로그인 정보를 사용할 것인가.
//작업이 끝나면 사용한 리소스를 시스템에 돌려준다.
public class TestDao {

public void add(DTOBean dto) throws ClassNotFoundException, SQLException{
Class.forName("com.mysql.jdbc.Driver");
Connection c= DriverManager.getConnection("jdbc:mysql://localhost/springbook", "spring", "book");
PreparedStatement ps = c.prepareStatement("insert into users(id,name,password) value(?,?,?)");
ps.setString(1,  dto.getName());
ps.setInt(2,  dto.getValue());
ps.setString(3,  dto.getData());
ps.executeUpdate();
ps.close();
c.close();
}
}



반응형
반응형

출처: https://kisukpark.wordpress.com/2013/08/29/spring-mvc-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90/


Spring의 등장 배경

Java는 처음 Enterprise용 소프트웨어를 목적으로 개발되었다. 그래서 자바로 만들어지는 소프트웨어들은 개인이 만드는 것 보다 크고 복잡했으며 또한 무거웠다. 이러한 자바 프로그램의 복잡도를 줄이고자 Spring 프레임워크가 등장하였다.

Spring

Spring은 Java 기반의 프레임워크로서 여러 모듈로 구성되어있다. 하지만 Spring은 단순 프레임워크를 넘어 자신만의 철학을 지닌다. 즉, 프레임워크와 철학을 합쳐 Spring이라 부른다.

Spring은 일종의 Container 역할을 하는 프레임워크로 사용자가 필요한 모듈을 꽂아 사용할 수 있게 해준다. “틀이 되어 주겠다.”

  • Spring은 Java 객체를 담고 있는 경량 컨테이너이다. 이들 Java 객체의 생성, 소멸과 같은 라이프 사이클을 관리하고 Spring으로 부터 필요한 객체를 가져와 사용 할 수 있다.

Spring의 철학

철학설명
IoC(Inversion of Control)‘제어의 역전’으로서 기존에 어플리케이션이 프레임워크의 서비스를 콜하는 대신에 프레임워크가 어플리케이션의 각 컴포넌트들을 부르는 형태이다. 제어이 어플리케이션 그 자체에서 프레임워크로 넘어갔다고 하여 제어의 역전이라 한다.
DI(Dependency Injection)IoC를 실제로 구현하는 방법으로서 의존성있는 커포넌트들 간의 관계를 개발자가 직접 코드로 명시하지 않고 컨테이너인 Spring이 런타임에 찾아서 연결해주게 하는 것이다.

Spring IoC, DI 예제

Spring MVC Module

Spring 의 여러 module 중에서 웹에도 기존 소프트웨어에서 사용되는 MVC 패턴을 적용해 웹 어플리케이션을 만들고자 등장한게 Spring MVC module 이다.

기존에 servlet 원래의 spec에 맞춰 servlet을 개발하려고 하면, doGet(), doPost() 등의 함수를 생성해 주는 등의 공통적이고 반복적인 작업을 많이 해야했다.

그리하여 개발자가 직접 모든 웹 컴포넌트를 부르는 대신 그것보다 상위의 framework 가 있어 이러한 컴포넌트들을 자동으로 불러주고, 반복적인 작업을 줄여주기위해 Spring MVC Module이 등장하였다. Spring MVC Module 로 만들어진 프로그램들은 그 Spring MVC Module 내부에 Servlet(Dispatcher Servlet)을 포함하고 개발시 이전에는 일일이 해야했던 공통된 부분을 따로 하지 않아도 자동으로 되었다. 즉, Spring MVC을 통해 만들어진 프로그램은 그 내부에 Servlet을 포함하고 그 자체가 Tomcat과 같은 Servlet Container 위에 올라가 동작하는 Servlet 역할을 한다.

왜 Spring MVC가 필요한가?

ex) http://kisukworld.com/notice 라는 URL이 서버에 요청되었을 때

MVC가 적용되기 전의 웹 코드
package mypkg;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloServlet extends HttpServlet {
    /* DB에 접근할 Data Access Object(DAO) */
    NoticeDB db = new NoticeDB();

    @Override
    public void doGet(HttpServletRequest request, 
                      HttpServletResponse response)
        throws IOException, ServletException {

        //response.setContentType("text/html;charset=UTF-8");
        //PrintWriter out = response.getWriter();

	/* db 라는 DAO를 직접 사용해 데이터를 가져온다. */
	List<Notice> notices = new List<Notice>;
	notices = db.getNotices();

	/* URL 마다 분기점을 만들어 처리해 주어야 한다. */
  	if (request.getRequestURL().equals("/notices") {
   	    try {
		/* 직접 View 코드를 만들어 준다. */
		out.println("<!DOCTYPE html>");
   	        out.println("<html>");
   	        out.println("<body>");
       	  	out.println("<h1>Hello, world!</h1>");
       		out.println("</body>");
       		out.println("</html>");
	    } 
            finally {
		out.close();
    	    }
	}
    }
}

문제)

  • URL 마다 분기 점을 만들어 줘야 하므로 처리가 느리다.
  • 직접 NoticeDB 클래스의 객체를 사용하기 때문에 DB가 바뀌거나 하면 수정이 어렵다.
  • Model, View, Controller가 다 섞여 있다. -> 유지 보수가 어렵다.
Spring MVC가 적용된 웹 코드
// NoticeDAO.java

public interface NoticeDAO
{
    public List<Notice> getNotices();
}
  • NoticeDAO 라는 interface를 만들어 준다.
  • DAO를 interface로 만드는 이유는 DB마다 공통된 인터페이스를 적용하고 유지 보수를 쉽게 하기 위해서이다.
//NoticeDAOImpl.java

@Repository
public class NoticeDAOImpl implements NoticeDAO
{
    public List<Notice> getNotices()
    {
	//some code
    }
}
  • @Repository : 이 클래스는 DAO를 구현한 클래스임을 나타내는 Annotation.
//NoticeController1.java

public class NoticeController1()
{
    @Autowired
    private NoticeDAO noticeDAO;

    @RequestMapping("/notice")
    public List<Notice> getNotice()
    {
	List<Notice> notices = new List<Notice>;
	notices = noticeDAO.getNotices();

	//...

	return notices;
    }
}
  • @Autowired : 특정 클래스를 명시하지 않아도 Spring이 자동으로 NoticeDAO를 구현한 클래스를 연결해 준다.
  • @RequestMapping : 통해 분기문 없이 특정 URL의 요청이 왔을 때 Spring이 자동으로 이 메소드를 호출해준다. 통상적으로 한 URL에 대해 RequestMapping된 메소드는 한 개.
  • 메소드 안에서는 noticeDAO라는 객체에 대해 알 필요없이 interface가 제공하는 메소드를 사용하면된다.
//NoticeController2.java

public class noticeController2()
{
    @Autowired
    private NoticeDAO noticeDAO;

    @RequestMapping("/notice/{user_id}")
    public List<Notice> getNotice(
        @RequestParam("key1")String val1, 
        @PathVariable("user_id")Integer id)
    {

    }

    /* Notice에 관심있는 다른 메소드 */
    public void removeNotice(String title)
    {

    }
}
@RequestMapping(“/notice”) , @RequestMapping(“/notice/{user_id}”)  에서 두개의 URL은 다른 것이므로 각각이 붙은 메소드가 동시에 존재 가능하다. 동일한 URL을 다른 메소드에 매핑한다면 매핑된 모든 메소드가 실행된다. 단, 순서는 랜덤(비추)

Spring MVC Servlet 이 포함된 웹 서버의 구동방식

Image

Spring MVC가 없는 Servlet과 비교해서 원래의 Servlet 위치에 Spring MVC Module을 이용해 만들어진 프로그램이 하나 이상의 Servlet으로 위치해 있다. 아래의 그림은 두 개의 서블릿(Dispatcher Servlet)이 있고 Servlet Container(ex. Tomcat) 가 URL에 맞게 각 서블릿으로 요청을 보내는 것을 보여준다.

Image

일단 Servlet Container가 URL 요청에 맞게 Dispatcher Servlet을 골라 요청을 보내준 후(“/notice”는 위쪽 서블릿으로, “/board”는 아랫 쪽 서블릿으로) 에는 Spring Container 내부에서 아래의 작업이 진행된다.

Spring MVC module 내부의 작동

  1. 서블릿이 요청을 받는다(앞에서 Servlet Container가 적절한 서블릿으로 보낸준 것)
  2. Handler Mapping 을 통해서 요청을 처리할 Controller를 찾는다.
  3. 해당 Controller로 요청을 보낸다.
  4. Controller 로 부터 ModelAndView를 반환 받는다.
  5. 반환받은 View Name 으로 View Resolver를 통해 View를 찾는다.
  6. 찾은 View 파일에 Controller가 만들었던 Model을 주어 View를 완성하게 한다.
  7. 이 완성된 뷰가 Response가 되어 Client로 전해 진다.

Spring Container(=Application Container) 의 역할

  • Singleton 의 bean들을 관리한다.(Handler Mapper, Controller, View Resolver, View) : 요청 마다 매번 새로 객체를 만드는 것 보다 Singleton으로 하나 만들어 두고 재 사용하는게 성능에 도움이 된다.
  • 개발자가 직접 Dispatcher Servlet과 각 bean 들 사이의 의존성을 명시적으로 코드로 나타내지 않아도 Dependency Injection(DI) 으로 각 컴포넌트 사이의 연결을 만들어 준다.


반응형
반응형

출처: http://namocom.tistory.com/26


브라우저 관점

철처하게 스프링프레임워크를 떠나서 브라우저 관점에서 보자.
지난 시간에 봤던 아래 페이지는 웹브라우저의 주소로 부터 시작한다.


HTTP GET ( 호스트 - localhost / 포트 - 8080 / 경로 - /HelloWorld/ )

- 클라이언트(브라우저) 요청

GET /HelloWorld/ HTTP/1.1

Accept: text/html, application/xhtml+xml, */*

Accept-Language: ko

User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)

Accept-Encoding: gzip, deflate

Host: 10.17.29.20:8080

Connection: Keep-Alive

- 서버 응답

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Content-Type: text/html;charset=UTF-8

Content-Language: ko

Content-Length: 183

Date: Thu, 13 Sep 2012 02:46:54 GMT


<html>

<head>

<title>Home</title>

</head>

<body>

<h1>

Hello world!

</h1>


<P> The time on the server is 2012년 9월 13일 (목) 오후 3시 52분 28초. </P>

</body>

</html>


서버관점

브라우저 관점에서는 서버란 HTML 페이지를 반환해주는 웹서버(TCP 서버)일 뿐이다.

이제 서버, 스프링 프레임워크에서 어떻게 요청을 처리하는지 따라가보자.

기본적으로 자바의 서블릿에 대해서는 알고 있는 것이 이해하기 편할 것이다.


웹 설정 파일(Web Configuration file)

서블릿은 기본적으로 web.xml 이라는 설정파일을 가지고 있다.

참고로 src/main/webapp/WEB-INF/web.xml 에 위치한다.


열어보면 아래와 같은 부분이 있을 것이다.

<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>

서블릿 이름은 appServlet이고, 서블릿 클래스가 'org.springframework.web.servlet.DispatcherServlet'로 지정이 되어 있다.


디스패처 서블릿(Dispatcher Servlet)

디스패처 서블릿은 클라이언트 요청을 핸들링하기 위해 앞단에서 컨트롤 하기 위해 존재한다.
클라이언트로 부터 오는 URL이 무엇이되던, 이 서블릿은 컨트롤러에 요청 객체로 넘겨주기 전에 클라이언트의 요청을 가로챌 것이다. 참고로 DispatcherServlet은 스프링라이브러리인 spring-webmvc-3.1.0.RELEASE.jar 안에 있다.

이 클래스는 아래와 같은 시그너처로 되어 있다.

public class DispatcherServlet extends FrameworkServlet

* FrameworkServlet - org.springframework.web.servlet.FrameworkServlet : 스프링의 웹 프레임워크를 위한 기본 서블릿이다. 전 솔루션에 걸쳐 자바빈 기반의 스프링 애플리케이션 컨텍스트를 이용하여 통합을 제공한다.


초기화 파라메터(init-param; initial parameter)

init-param은 초기화 파라메터를 설정하는 부분인데, 컨텍스트 설정 위치가 '/WEB-INF/spring/appServlet/servlet-context.xml'로 되어 있음을 알 수 있다.


servlet-context.xml

<annotation-driven />

<resources mapping="/resources/**" location="/resources/" />

<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>

맨위의 annotation-driven은 어노테이션 기반을 사용하겠다고 설정하는 것이다. 컨트롤러 작성을 xml 상에 일일이 <bean> 태그를 이용해서 스프링 빈으로 등록할 수 있으나 클래스에 @Controller 어노테이션을 붙이면 해당 클래스를 웹 요청을 처리하는 컨트롤러로 사용할 수 있다. (스프링 2.5부터 지원)


resources 태그는 HTTP GET으로 들어온 /resources/~ 형태의 요청(보통 정적 파일)을 웹어플리케이션루트/resources 디렉토리로 지정을 하겠다는 것이다.


웹 페이지에서 최종형태는 HTML 같은(PDF나 엑셀파일이 될 수 도 있다)형태의 뷰이다. 기본적으로 템플릿에는 jsp 페이지로 되어 있다. 컨트롤러는 ViewResolver를 통해 View 객체를 리턴하게 되는데 위에서는 'InternalResourceViewResolver'가 지정되어 있다.


접기

리스너(Listener)

web.xml 상 아래와 같이 되어 있다.

<listener>

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

</listener>

ContextLoaderListener는 스프링라이브러리인 spring-web-3.1.0.RELEASE.jar 형태의 이름안에 있다.

이 클래스는 아래와 같은 시그너처로 되어 있다.

public class ContextLoaderListener extends ContextLoader implements ServletContextListener

* ContextLoader - org.springframework.web.context.ContextLoader (클래스)

  ServletContextListener - javax.servlet.ServletContextListener (인터페이스)

그 외

root-context.xml 도 web.xml에 설정이 되어 있으나 실제로는 기본 템플릿에서 비어있기 때문에 넘어간다.

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/spring/root-context.xml</param-value>

</context-param>


접기

/HelloWorld/ 요청은 어디로?

앞에서 브라우저 주소에 입력한 'http://localhost:8080/HelloWorld/'는 
localhost의 8080포트로 GET /HelloWorld/ HTTP/1.1 요청을 한다고 봤다.
서블릿은  /HelloWorld를 보고 HellowWorld쪽으로 넘기고 HelloWorld 프로젝트 관점에서는 / 라는 리소스의 요청이 있는 것이다. 이 요청은 HomeController 클래스가 담당하도록 템플릿이 만들어준다.



코드는 아래와 같다. (로거부분은 제외 시켰다.)

@Controller

public class HomeController {

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

        public String home(Locale locale, Model model) {

               Date date = new Date();

               DateFormat dateFormat = DateFormat.getDateTimeInstance(
                                                    DateFormat.LONG, DateFormat.LONG, locale);

               String formattedDate = dateFormat.format(date);

               model.addAttribute("serverTime", formattedDate );

               return "home";

        }

}

servlet-context.xml에서 annotation-driven에서 언급되었듯이 HomeController 클래스에 @Controller라는 어노테이션이 붙어있다. 어노테이션이 붙어있으면 서버가 시작할 때 RequestMappingHandlerMapping에 의해서 자동으로 등록이 된다.

INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.tistory.namocom.HomeController.home(java.util.Locale,org.springframework.ui.Model)


HomeController에는 home이라는 메소드가 있는데 @RequestMapping이라는 어노테이션이 붙어있다. 요청처리를 매핑하기 위한 어노테이션인데, HTTP GET으로 "/"에 대한 처리를 담당한다고 보면 된다.


브라우저에서 요청한 http://localhost:8080/HelloWorld/는 결국 HomeController.home 이라는 메소드로 들어오게 되는 것이다.

이 home 메소드에서 해주는 일은 단순하다.
 - java.text.DateFormat 클래스에서 현재 날짜와 시간을 해당 로케일에 맞게 가져온 후에

 - 문자열로 만들어서

 - serverTime라는 속성에 넣은 후

 - home 이라는 뷰에 넘기게 되어 있다.


그럼 home은 어디로 넘어가는가?

아까 servlet-context.xml에서 InternalResourceViewResolver 가 지정되어 있음을 기억해보자.

prefix(접두사)가 /WEB-INF/views/ 였고, suffix(접미사)가 .jsp 였다.

결국 home이라는 뷰 이름은 /WEB-INF/views/home.jsp 으로 바뀌게 된다.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<html>

<head>

        <title>Home</title>

</head>

<body>

<h1>

        Hello world! 

</h1>

 

<P>  The time on the server is ${serverTime}. </P>

</body>

</html>


JSP는 HTML을 만들기 위한 템플릿일 뿐이다.

결국은 아래와 같은 HTML이 동적으로 만들어진다. 어디가 차이인지 알겠는가?
바로 ${serverTime} 부분이 2012년 9월 13일 (목) 오후 3시 52분 28초 와 같은 문자열로 대체가 된 것이다.

컨트롤러에서 model.addAttribute("serverTime", formattedDate ); 에서 모델의 애트리뷰트 이름이 serverTime이었다.

<html>

<head>

        <title>Home</title>

</head>

<body>

<h1>

        Hello world! 

</h1>

 

<P>  The time on the server is 2012 9 13 (오후 3 52 28</P>

</body>

</html>


전체적인 그림

웹브라우저에서 시작된 요청부터, 결과까지 개념적으로 그림으로 만들어보았다.



지난번에 깨졌던 한글은?

이번에 보면 한글이 다 잘 나오고 있는데 어떻게 해결을 한 것일까?

결론은 간단하다. jsp에서 페이지 인코딩을 UTF-8로 하도록 조정을 해주었다.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ page session="false" pageEncoding="UTF-8"%>

<html>

<head>

        <title>Home</title>

</head>

<body>

<h1>

        Hello world! 

</h1>

 

<P>  The time on the server is ${serverTime}. </P>

</body>

</html>

참고로 본인은 개인적으로 프로젝트의 인코딩 형식을 UTF-8로 하고 있다. 다국어 지원을 위해서 말이다.
스프링에서도 기본적으로 다국어 지원을 위한 로케일을 지원하고 있지 않은가?

 - 위에서 home 메소드에 첫 번째 인자가 Locale locale 이다!


이상으로 HelloWorld 예제 분석을 마쳐본다.

스프링에 대해 더 자세히 알고 싶으면 스프링 홈페이지에서 Document를 읽거나 Introduction to Spring MVC Framework를 읽어보면 도움이 될 것 같다.

반응형
반응형

출처:http://saurus2.tistory.com/entry/Java-Spring-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91-%ED%95%98%EC%A7%80-Hello-World-%EC%9D%98-%EC%9B%90%EB%A6%AC


자바 스프링의 구현 원리를 공부하기 전에 

MVC 패턴에 대해서 먼저 공부해보자. 모델-뷰-컨트롤러(Model-View-Controller, MVC)는 소프트웨어 공학에서 사용되는 아키텍처 패턴이다. 


* 아키텍처 패턴 


아키택처 패턴전에 아키텍처를 알아보자, 

아키텍처의 영문 어원은 Architecture = archi(fisrt, cheif, govern) + tect(build)이다. 건물을 구출할 때 전체적인 구조를 관리하는 의미이다. 

 

 소프트웨어 아키텍처는 무엇인가? 


'소프트웨어 시스템을 구성하는 서브시스템과 컴포넌트, 그리고 그것들의 관계를 나타내는 용어이다.'

- Pattern-Oriented Software Architecture, Volume 1: A System of Patterns


'아키텍처는 컴포넌트로 구체화된 시스템의 기본적인 조직이며 환경에 대한 관계이고 디자인과 진화를 이끄는 원리이다.'

- IEEE1471



 소프트웨어 아키택처를 지칭하는 말들을 정리하면 시스템 즉 프로그램을 구성하는 구성요소(서브시스템, 컴포넌트)와 그들(구성요소) 간의 관계를 나타낸다. 건축을 할때 처럼 기초 토목 공사에서 건물의 외장까지 이르런 설계가 매우 중요한 것처럼, 프로그램을 제작할때 , 시스템을 구성할때 소프트웨어 아키택처가 필요하다. 프로그램의 점점 규모가 커져 복잡해지면 아키텍처의 존재는 불가결하다. 


아키텍처 패턴


 디자인 패턴과 마찬가지로 특정 문제를 해결하기 위해 반복되어 사용되는 솔루션을 문서화한 것이다. 아키텍처 패턴은 소프트웨어 시스템의 구조를 체계적으로 구성하기 위한 기본적인 스키마를 제시한다. 미리 정의된 패턴간의 책임을 명시하여 규칙과 가이드라인을 제시한다. 


아키택처 패턴의 장점 :

1. 검증

2. 시뮬레이션

3. 쉬운 이해


*MVC 패턴이란? 


대표적인 아키택처 패턴의 하나로 시스템 전체를 Model과 View, Controller 세 개의 컴포넌트(더 큰 프로그램이나 구조물에서 식별 가능한 "일부분") 로 나뉘어 있다. 


* Model : 핵심 데이터와 기능을 캡슐화 [ 상태의 변화가 있을때 컨트롤러와 뷰에 이를 통보함, 통보를 통해 뷰는 최신의 결과를 출력, 컨트롤러는 모델의 변화에 따른 적용 가능한 명령을 추가,제거,수정할 수 있다. ]

* View : 사용자에게 정보를 Display, 각뷰마다 컴포넌트 하나씩 연결된다. 사용자는 오직 컨트롤러를 통해서만 시스템과 상호작용한다.  [ 모델로 부터 결과물을 생성한다. ]

* Controller : 데이터와 비즈니스 로직 사이의 상호동작을 관리 [ 모델에 명령을 보내 모델의 상태를 변경할 수 있다. ]





* 실선은 직접적인 관계를 , 점선은 간접적인 관계를 나타낸다. 


MVC 의 개념을 웹에 적용한 예


1. 사용자가 웹사이트에 접속 [controller 사용]

2. Controller 는 사용자가 요청한 웹페이지를 서비스 하기 위해서 모델을 호출해야한다. 

3. 모델은 데이터베이스나 파일과 같은 데이터 소스를 제어한 후 그 결과를 리턴한다. 

4. Controller 는 Model 이 리턴한 결과를 View 에 반영한다. 

5. 데이터가 반영된 View 는 사용자에게 보여진다.



Hello World 동작 원리

1. 클라이언트 요청 

2. web.xml 에서 디스패처 서블릿(Dispatcher Servlet) 클라이언트 요청을 핸들링

3. servlet-context.xml 에서 해당 클래스의 웹요청을 처리하는 컨트롤러를 사용 [HanderMapping으로 Controller 검색]

4. 해당 Controller 가 요청 처리 후, Home (View) 로 리턴 [뷰의 이름은 /WEB-INF/views/home.jsp 로 바뀐다.

5. View 에 출력





* 디스패처 서블릿(Dispatcher Servlet)


 디스패처 서블릿은 클라이언트의 요청을 앞단에서 컨트롤 하기 위해 존재한다. 

컨트롤러에 요청을 객체로 넘겨주기 전에 클라이언트의 요청을 받아 Controller 를 검색하고 , Controller 의 처리 결과를 전달 받아 View를 출력해주는 역할을 한다. 요청을 처리할 Contorller 를 만들어 처리한 결과를 출력해 줄 View 가 필요한다. 


'/Hello/src/main/webapp/WEB-INF/web.xml'


서블릿의 이름은 appServlet 이고, 서블릿 클래스가 'org.springframework.web.servlet.DispatcherServlet' 으로 지정 되어있다.


초기화 파라메터(init-param; initial parameter 

<init-param> 으로 contextConfigLocation 을 설정해 준다. init-param 은 초기화 파라메터를 설정하는 부분이다.

컨텍스트의 위치는 WEB-INF/spring/appServlet/servlet-context.xml 로 되어있다. 아래의 servlet-context.xml 파일을 보자.



/Hello/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml


 맨위의 annotation-driven 은 어노테이션 기반을 사용하겠다고 설정하는 것이다. 컨트롤러 작성을 클래스에 @Controller 어노테이션을 붙여 해당 클래스를 웹 요청 처리를 하는 컨트롤러로 사용할 수 있다. (스프링 2.5부터)


 resources 태그는 HTTP GET 으로 들어온 /resources/~ 형태의 요청(보통 정적 파일)을 웹어플리케이션루트/resouces 디렉토리로 지정을 하겠다는 것이다. 


 웹 페이지에서 최종형태는 HTML 같은 형태의 뷰인데, 기본적으로 템플릿에는 jsp 페이지로 되어 있다. 컨트롤러는 ViewResovler 를 통해 View 객체를 리턴한다. 위의 파일의 'InternalResourceViewResolver' 가 리졸버로 지정되어 있다. 


 아래에서 설명할 View 리턴은 , prefix 가 /WEB-INF/views/ 이고 , suffix 가 .jsp 로 생성된다. 결국 /WEB-INF/views/home.jsp 로 바뀐다.


/hello/ 요청


localhost 의 8080포트로 GET /hello/HTTP/1.1 요청을 하면 서블릿은 /hello 를 보고 hello 쪽으로 넘기고 hello 프로젝트 관점에서는 / 라는 리소스의 요청이 있다. 이 요청은 HomeController 클래스가 담당하도록 템플릿이 만들어준다. 



/Hello/src/main/java/com/hellowolrd/hello/HomeController.java


@Controller 라는 어노테이션이 붙어 있으면 서버가 시작할때 RequestMappingHandlerMapping 에 의해서 자동으로 등록이 된다. HomeController 에는 home 이라는 메소드에 @RequestMapping 이라는 어노테이션이 붙어있다. 요청처리를 매핑하기 위한 어노테이션인데, HTTP GET 으로 '/' 에 대한 처리를 담당 한다. 


 브라우저에서 요청한 http://localhost:8080/hello/ 는 Homecontroller.home 이라는 메소드로 돌아온다. 

home 메소드는 java.text.DataFormat 클래스에서 현재 날짜와 시간을 해당 로케일에 맞게 가져온 후에 문자열로 만들어 serverTime 이라는 속성에 넣어 home 이라는 뷰에 넘긴다

 


 Home 이라는 뷰이름은 /WEB-INF/views/home.jsp 로 바뀐다. 


/Hello/src/main/webapp/WEB-INF/views/home.jsp


 jsp 는 html 을 만들기 위한 템플릿이며 결국은 아래와 같은 HTML 이 동적으로 만들어 진다. ${serverTIme} 이라는 부분이 리턴한 값으로 대체가 된다. 컨트롤러에서 model.addAttribute("serverTime", formattedDate); 에서 모델의 애트리뷰트 이름이 serverTime 이다. 



[출처]

https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC -출처 위키백과

https://opentutorials.org/course/697/3828 - 출처 생활코딩

http://www.zdnet.co.kr/news/news_view.asp?artice_id=20090623150606&type=det&re= - 출처 지디넷 코리아 

http://egloos.zum.com/pelican7/v/2586302 - 출처 가시고기의 바깥 세상 둘러보기



반응형

+ Recent posts