[Ace-T의 Spring강좌] Step 06. Spring @MVC 분석-03

2014. 5. 23. 11:32OpenSource/Spring 강좌

반응형

[Ace-T의 Spring강좌] Step 06. Spring @MVC 분석-03


저번 시간에는 spring context 구조 잡기, bootstrap 연동해보기 등등을 해보았네요!

이번 시간에는~! mvc구조를 한번 들어가보려고 합니다! ㅎㅎ두둥~

출처 : 토비의 스프링 3.2 / 토비형님 항상 감사합니다! 스프링책은 토비님 책이 짱짱맨!


아래의 소스링크가 안된다는 제보를 주셔서 소스는 아래의 github를 사용해주시면 감사하겠습니다.

제보주신 장땡땡님! 감사합니다^^

https://github.com/ace-t/rndStart/


우선 아래의 그림을 보시죵!~

차근차근 하나씩 MVC의 각 요소와 프론트 컨트롤러(DispatcherServlet)가 어떻게 협력해서 일하는지를 알아봅시다!

(1) DispatcherServlet의 HTTP 요청 접수

     Client에서 HTTP요청이 들어오면 web.xml의 url-pattern에 따라 DispatcherServlet에 할당된 것이라면

     HTTP 요청정보를 DispatcherServlet에 전달 해준다.


 URL이 / 로 시작하는 모든 요청을 DispatcherServlet에 할당해주는 것이다.^-^Good~

  위의 내용처럼 특정 폴더 아래의 내용을 매핑하는 방법도 가능하고, *.do와 같이 특정 확장자만을 매핑해주는 방법도 쓸 수 있다.


(2) DispatcherServlet에서 컨트롤러로 HTTP 요청 위임

     Controller를 선정하는 것은 DispatcherServlet의 핸들러 매핑 전략을 이용한다.

     핸들러 매핑 전략?? 이게 무슨말이냐하면..

     사용자(Client) 요청을 기준으로 어떤 컨트롤러/핸들러에게 작업을 위임할지를 결정 해준다는 것이다.

     그 다음으로는 해당 컨트롤러 오브젝트의 메소드를 호출해서 실제로 웹 요청을 처리하는 작업을 위임한다.

     또한 DispatcherServlet은 어떤 Controller라도 사용이 가능하다. 확장성이 좋다는 말이다.

     그렇다면 자바의 오브젝트 사이에 무엇인가 요청이 전달되려면 메소드를 호출할 수 있는 방법이 있어야 하지 않는가?

     어떻게 제각각 다른 메소드와 포맷을 가진 오브젝트를 Controller로 만들어놓고 DispatcherServlet이 이를 알아서

     호출하게 만들수 있을까? 

 

     바로! 전형적인 "어댑터 패턴"을 사용해서, 특정 Controller를 호출해야 할 때는 해당 Controller 타입을 지원하는 어댑터를

     중간에 껴서 호출하는 것이다. 그러면 DispatcherServlet은 항상 일정한 방식으로 Controller를 호출하고 결과를 

     받을수있다.

     

 아래의 그림처럼 DispatcherServlet은 Controller가 어떤 메소드를 가졌고 어떤 인터페이스를 구현했는지 전혀 알지 못한다.

 대신에 Controller종류에 따라 적절한 어댑터를 사용한다.

각 어댑터는 자신이 담당하는 Controller에 맞는 호출 방법을 이용해서 Controller에 작업을 요청하고 결과를 리턴받아서

 DispatcherServlet에게 다시 돌려주는 기능을 가지고 있다. WoW!


(Tip) DispatcherServlet이 핸들러 어댑터에 웹 요청을 전달할 때는 모든 웹 요청 정보가 담긴 HttpServletRequest 타입의 오브젝트를 전달해준다. 이를 어댑터가 적절히 변환해서 Controller의 메소드가 받을수 있는 파라미터로 변환해서 전달 해준다.

  

(3) Controller의 모델 생성과 정보 등록

     Controller가 하는 일은??

      1) 먼저 사용자 요청을 해석하는 것

      2) 그에 따라 실제 비즈니스 로직을 수행하도록 서비스 계층 오브젝트에게 작업을 위임하는 것

      3) 결과를 받아서 모델을 생성하는 것

      4) 어떤 뷰를 사용할지 결정하는 것


     특히 모델을 생성하고 모델에 정보를 넣어주는 작업은 매우 중요하다! Controller가 어떤식으로든 

     다시 DispatcherServlet에게 리턴해야 할 2가지 정보가 있는데, 그중 하나가 모델이고 다른 하나가 뷰이다.

     (Tip) 모델은 이름과 오브젝트 값의 쌍으로 만들어진다.(보통 맵에 담긴 정보라고 생각하면 된다.)


(4) Controller의 결과 리턴 : 모델과 뷰

     모델이 생성이 되었다면, 다음은 뷰를 결정할 차례이다.

     Controller가 뷰 오브젝트를 직접 리턴할 수도있지만, 보통은 뷰의 논리적인 이름을 리턴해주면 DispatcherServlet의

     전략인 뷰 리졸버가 이를 이용해 뷰 오브젝트를 생성해준다.(뷰를 사용하는 전략과 방법은 매우 다양하다!)

     결국 Controller가 리턴하는 것은 모델과 뷰 두가지이다.

     Spring에는 ModelAndView라는 이름의 오브젝트가 있는데, 이 ModelAndView가 DispatcherServlet에 

     어댑터를 통해 Controller로부터 돌려받는 오브젝트이다. 이름 그대로 모델과 뷰, 두가지 정보를 담고 있다.

     모델과 뷰를 넘기는 것으로 Controller의 책임은 끝이다. 다시 작업은 DispatcherServlet으로 넘어간다.


(5) DispatcherServlet의 뷰 호출과 (6) 모델 참조

     DispatcherServlet이 Controller로부터 모델과 뷰를 받은 뒤에 진행하는 작업은, 뷰 오브젝트에게 모델을 전달해주고 

     클라이언트에게 돌려줄 최종 결과물을 생성해달라고 요청하는 것이다.

     모델의 참조는 뷰에다가 데이터를 전달하는 것으로 보면 된다. 

     그리고 보통 브라우저를 통해 사용자가 결과를 본다고 하면 브라우저에 나타날 HTML을 생성하는 일이 가장 흔한 뷰의 작업이다.

     (Tip) 뷰 작업을 통한 최종 결과물은 HttpServletResponse Oject안에 담긴다. 


(7) HTTP 응답 돌려주기

     뷰 생성까지 모든 작업을 마쳤으면 DispatcherServlet은 등록된 후처리기가 있는지 확인하고, 있다면 후처리기에서 

     후속 작업을 진행한 뒤에 뷰가 만들어준 HttpServletResponse에 담긴 최종 결과를 서블릿 컨테이너에게 돌려준다.

     서블릿 컨테이너는 HttpServletResponse에 담긴 정보를 HTTP 응답으로 만들어 사용자의 브라우저나 클라이언트에게 

     전송하고 작업을 종료한다.






참고만 하세요! - 더 Detail하게는 좀 더 뒤에! ㅎㅎ

DispatcherServlet의 DI 가능한 전략

  "(2) DispatcherServlet에서 컨트롤러로 HTTP 요청 위임"에서의 전략에 대해서 알아보도록 하겠습니다~

  전략으로는 아래와 같이 Mapping과 Adapter가 있겠습니다~

  ㅇ HandlerMapping

      핸들러 매핑은 URL과 요청 정보를 기준으로 어떤 핸들러 오브젝트, 즉 Controller를 사용할 것인지를 결정하는 로직을 담당!

      default로 BeanNameUrlHandlerMapping과 DefaultAnnotaionHandlerMapping 두가지가 설정 되어있다.

      default 핸들러 매핑으로 충분하다면 추가로 핸들러 매핑을 등록하지 않아도 된다.

      

  ㅇ HandlerAdapter

      핸들러 매핑으로 선택한 Controller/핸들러를 DispatcherServlet이 호출할 때 사용하는 어댑터이다.

      Controller의 타입에는 제한이 없으며, Controller 호출 방법은 타입에 따라 다르기 때문에 Controller를 결정했다고

      해도 호출 방법은 DispatcherServlet이 알 길이 없다. 

      그래서 Controller 타입을 지원하는 HandlerAdpater가 필요하다.


  ㅇ ViewResolver

      뷰 리졸버는 Controller가 리턴한 뷰 이름을 참고해서 적절한 뷰 오브젝트를 찾아주는 로직을 가진 전략 오브젝트 이다.

      default로 등록된 InternalResourceViewResolver는 JSP나 서블릿 같이 RequestDispatcher에 의해 

      포워딩될 수 있는 리소스를 뷰로 사용하게 해준다.



어느정도 MVC를 알았보았으니 이론은 요정도까쥐만 해보고 재밌는 실습을 한번 해보도록 하겠습니다.

앞으로 우리가 할 것은 MVC를 구축해보는 것 입니다.

그렇다면 시나리오를 하나 생각해보죠!

현재 View는 있고..View에서 어떤것을 클릭! 같은 이벤트를 발생했을 때 즉, 클라이언트에서 요청을 하는 것 이겠죵~

중요한 것은 해당 컨트롤러를 찾게 되어지고 컨트롤러에서 받는 파라미터 처리, MVC처리 후 리턴 처리, View에서는 어떻게 처리가 되어지는지가 중요 할 것 같네요.


4번째 강좌를 보시면 컨트롤러 메소드 파라미에 대해서 간단히 설명을 하였습니다.

나중에 Jquery grid를 사용해야하니 Json통신을 한번 해보겠습니다.(조금 더 뒤에!)

그전에 가장 간단한 @RequestParam도 한번 써보겠습니다. ㅎㅎ 


개발은 검색 페이지 화면을 가지고 해보겠습니다.


결과적으로 검색어를 "박태하하하하하하"를 넣으시고 검색 버튼을 눌렀을 경우에..



아래와 같이 검색결과 페이지로 가는 내용 입니다. 킁; 한글이 깨지네요 ㅋㅋㅋㅋㅋㅋ;


암튼..한글깨짐은 우선 무시하고! 중요한 mvc를 알아보겠습니다. 하하^0^;


구조는 아래와 같습니다. controller를 하나 만들어주시고! jsp파일 또한 하나 만들어줍니다.




컨트롤러 소스는 아래와 같습니다.  


중요하게 봐야 할 부분은 @RequestParam쪽 입니다. 또한 Model~~~:D


간단히 설명을 하자면! 검색어를 넣고 버튼을 클릭 하였을 경우! Client 

즉, JSP단에서 값이 넘어오게 되어지며, 그 값은 searchInput인 String searchKeyword에 담기게 되어집니다.

그 값을 model에 담게 되죵! 그렇게 담긴 값은 searchResult.jsp에서 사용하게 되어집니다! 굳~!


어떤식으로 searchResult.jsp에서 가져다가 사용하는지 알아보겠습니다.

소스는 다음과 같습니다. 


 

위와 같이 ${searchKeyword}  방식으로 값을 가져올 수 있습니다.


다음으로는 ModelAndView객체로 한번 해볼까요? 이번에는 로그인을 가지고 한번 해보겠습니다.

결과는 다음과 같습니다. 아래와 같이 " Do you want to login? "이라는 문구를 login.jsp에 넘겨서 찍어보겠습니다.



우선 controller쪽을 보겠습니다. 아래와 같이 리턴을 ModelAndView로 넘겨줍니다.

위에 제대로 이해하셨다면 당근 DispacherServlet으로 넘겨준다는 것을 이해했을 것 입니다.

mv.setViewName("login"); 이녀석도 login.jsp임을 알수 있습니다.

mv.addObjet(""); 이녀석은 message에다가 해당 String값을 넣어주는 것 입니다. Good~



이제 UI쪽 소스를 보겠습니다. 위와 마찬가지로 ${ } 를 사용하여 찍어줍니다.






요기까지~~MVC에 대해서 알아보았습니다.

@ModelAttribute는 아래의 내용처럼 DTO(VO)의 프로퍼티에 요청 파라미터를 바인딩해서 사용한다고 합니다.


참고 : 2014/02/05 - [OpenSource/Spring 강좌] - [Ace-T의 Spring강좌] Step 04. Spring @MVC 분석-01  의 내용입니다.

요청 파라미터를 메소드 파라미터에서 1:1로 받으면 @RequestParam이고,

 도메인 오브젝트나 DTO, VO의 프로퍼티에 요청 파라미터를 바인딩해서 한번에 받으면 @ModelAttribute라고 볼 수 있다.

 ex) @RequestMapping("/acet/search")

         public String search(@ModelAttribute UserSearch  userSearch){

            List<User> list = userService.search(userSearch);

            model.addAttribute("userList", list);

              ..................

        }



다음 시간에는 @ModelAttribute와 Json 통신에 대해서 알아보도록 하겠습니다. 


Json 통신은 인기있다죠잉~



    - 일단 END -


<< 참고 링크 >>


2014/05/05 - [OpenSource/Spring 강좌] - [Ace-T의 Spring강좌] Step 05. Spring @MVC 분석-02


2014/02/05 - [OpenSource/Spring 강좌] - [Ace-T의 Spring강좌] Step 04. Spring @MVC 분석-01


2013/12/04 - [OpenSource/Spring 강좌] - [Ace-T의 Spring강좌] Step 03. Spring 환경 구축 하기(was)


2013/11/05 - [OpenSource/Spring 강좌] - [Ace-T의 Spring강좌] Step 02. Spring 환경 구축 하기(Maven+Spring Project)


2013/11/03 - [OpenSource/Spring 강좌] - [Ace-T의 Spring강좌] Step 01. Spring 환경 구축 하기(Eclipse+Jdk)

반응형