본문 바로가기
Spring/스프링 MVC 기본

#5 스프링 MVC 구조 이해

by 히포파타마스 2021. 6. 30.

스프링 MVC 구조 이해

 

1. 스프링 MVC 전체 구조

스프링 MVC의 전체 구조는 기존에 서블릿으로 구현해봤던 MVC패턴과 같다.

 

 

[스프링 MVC 구조]

스프링 MVC에서 프론트 컨트롤러 역할은 DispatcherServlet이 담당한다.

 

스프링 MVC의 큰 강점은 DispatcherServlet 코드의 변경 없이, 원하는 기능을 변경하거나 확장할 수 있다는 점이다.

 

아래와 같은 주요 인터페이스만 구현해서 DispatcherServlet에 등록하면 나만의 컨트롤러도 만들 수 있다.

 

· 주요 인터페이스 목록

 - 핸들러 매핑 : org.springframework.web.servlet.HandlerMapping

 - 핸들러 어댑터 : org.springframework.web.servlet.HandlerAdapter

 - 뷰 리졸버 : org.springframework.web.servlet.ViewResolver

 - 뷰 : org.springframework.web.servlet.View

 

 

2. 핸들러 매핑과 핸들러 어댑터, 뷰 리졸버

스프링에는 필요한 핸들러 매핑과 핸들러 어댑터, 그리고 뷰 리졸버가 대부분 구현되어 있다.

 

스프링 부트가 자동 등록하는 핸들러 매핑과 핸들러 어댑터, 뷰 리졸버는 아래와 같다.

 

■ HandlerMapping

 

· RequestMappingHandlerMapping : 애노테이션 기반의 컨트롤러인 @RequestMapping에 사용

 

· BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러를 찾는다.

 

순서대로 매핑 우선순위가 높다.

 

■ HandlerAdapter

 

· RequestMappingHandlerAdapter : 애노테이션 기반의 컨트롤러인 @RequestMapping에 사용

 

· HttpRequesetHandlerAdapter : HttpRequestHandler 처리

 

· SimpleControllerHandlerAdapter : 스프링 구 버전 Controller 인터페이스 처리

 

순서대로 핸들러 조회 우선순위가 높다.

 

■ ViewResolver

 

· BeanNameViewResolver : 빈 이름으로 뷰를 찾아서 반환한다.

 

· InternalResourceViewResolver : JSP를 처리할 수 있는 뷰를 반환.

 - application.properties에 등록한 spring.mvc.view.prefix와 spring.mvc.view.suffix 설정 정보를 사용해 자동 등록

 - application.properties에 경로와 확장자 설정해줘야 함

 

 

[JSP 뷰 리졸버 설정 예제]

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

 

 

3. 스프링 MVC 시작

■ @RequestMapping

 

애노테이션 기반의 컨트롤러를 사용할 때 쓰이는 애노테이션이다.

 

스프링에서 가장 우선순위가 높은 핸들러 매핑과 핸들러 어댑터인 RequestMappingHandlerMapping과 RequestMappingHandlerAdapter를 사용한다.

 

@RequestMapping을 사용해서 컨트롤러를 만들어 보자.

 

 

[회원 등록 폼 - 스프링 MVC]

@Controller
public class SpringMemberFormControllerV1 {

    @RequestMapping("/springmvc/v1/members/new-form")
    public ModelAndView process() {
        return new ModelAndView("new-form");
    }
}

 

· @Controller

 - 스프링이 자동으로 스프링 빈으로 등록한다.

 - 스프링 MVC에서 애노테이션 기반 컨트롤러로 인식한다.

 

· @RequestMapping 

- 요청 정보를 매핑한다.

- 해당 URL이 호출되면 결과적으로 해당 메서드가 호출된다.

 

model과 View의 논리 이름이 저장된 ModelAndView를 반환 한다.

 

RequestMappingHandlerMapping은 스프링 빈 중에서 @RequestMapping 또는 @Controller가 클래스 레벨에 붙어 있는 경우에 매핑 정보로 인식한다.

 

@Controller을 사용하지 않고 직접 스프링 빈에 등록해도 된다. 단, 클래스 레벨에 @RequestMapping을 붙여주어야 매핑이 가능하다.

 

 

[회원 저장 폼 - 스프링 MVC]

@Controller
public class SpringMemberSaveControllerV1 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @RequestMapping("/springmvc/v1/members/save")
    public ModelAndView process(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));

        Member member = new Member(username, age);
        memberRepository.save(member);

        ModelAndView mv = new ModelAndView("save-result");
        mv.addObject("member", member);
        return mv;
    }
}

스프링이 제공하는 ModelAndView를 통해 model 데이터를 추가할 때는 addObject()를 사용하면 된다.

 

 

4. 컨트롤러 통합

매핑 정보를 제공하는 @RequestMapping은 클래스 단위가 아니라 메서드 단위에 적용된다.

 

따라서 컨트롤러 클래스를 유연하게 하나로 통합 할 수 있다.

 

 

[통합 컨트롤러 - 스프링 MVC]

@Controller
@RequestMapping("/springmvc/v2/members")
public class SpringMemberControllerV2 {

    private MemberRepository memberRepository = MemberRepository.getInstance();


    @RequestMapping("/new-form")
    public ModelAndView newform() {
        return new ModelAndView("new-form");
    }

    @RequestMapping("/save")
    public ModelAndView save(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));

        Member member = new Member(username, age);
        memberRepository.save(member);

        ModelAndView mv = new ModelAndView("save-result");
        mv.addObject("member", member);
        return mv;
    }
}

클래스 레벨에 @RequestMapping으로 상위 경로를 통합해서 나타낼 수 있다.

 

 

5. 실용적 방식의 컨트롤러

앞의 스프링을 사용한 컨트롤러는 ModelAndView를 직접 생성해야한다.

 

또한 서블릿으로 요청파라미터를 일일히 가공해야하는 불편함이 있다.

 

스프링 MVC는 개발자가 편리하게 개발할 수 있도록 수 많은 편의 기능을 제공한다.

 

 

[실용적인 컨트롤러 - 스프링 MVC]

@Controller
@RequestMapping("/springmvc/v3/members")
public class SpringMemberControllerV3 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @GetMapping("/new-form")
    public String newform() {
        return "new-form";
    }

    @PostMapping("/save")
    public String save(
            @RequestParam("username") String username,
            @RequestParam("age") int age,
            Model model) {

        Member member = new Member(username, age);
        memberRepository.save(member);

        model.addAttribute("member", member);
        return "save-result";
    }
}

· @GetMapping, @PostMapping

 - URL 매칭 뿐 아니라 HTTP Method도 함께 구분할 수 있다.

 

· Model 파라미터

 - ModelAndView를 반환하지 않고 Model을 매개변수로 받아 사용할 수 있고 View의 논리 이름을 반환한다.

 

· @RequestParam

 - HTTP 요청 파라미터를 @RequestParam으로 받을 수 있다.

 - @RequestParam("username")은 request.getParameter("username")과 거의 같은 코드라고 생각하면 된다.

 - GET 쿼리 파라미터, POST Form 방식 모두 지원한다.

'Spring > 스프링 MVC 기본' 카테고리의 다른 글

#7 스프링 MVC - 웹 페이지 만들기  (0) 2021.07.08
#6 스프링 MVC 기본 기능  (0) 2021.07.07
#4 MVC 프레임워크  (0) 2021.06.29
#3 JSP & MVC 패턴 적용  (0) 2021.06.28
#2 서블릿  (0) 2021.06.23

댓글