minOS

스프링 MVC - 구조 이해(4) 본문

TIL/김영한의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

스프링 MVC - 구조 이해(4)

minOE 2024. 7. 19. 18:11
728x90

스프링 MVC - 시작하기

@RequestMapping
https://onepunchprogram.tistory.com/89 참고
가장 우선순위가 높은 핸들러 매핑과 핸들러 어댑터는 RequestMappingHandlerMapping
RequestMappingHandlerAdapter이다. `@RequestMapping` 의 앞글자를 따서 만든 이름인데, 이것이 바로 지금 스프링에서 주로 사용하는 애노테이션 기반의 컨트롤러를 지원하는 핸들러 매핑과 어댑터이다. 실무에서는 99.9% 이 방식의 컨트롤러를 사용한다.

 

회원 등록 폼
 @Controller
public class SpringMemberFormControllerV1 {
    @RequestMapping("/springmvc/v1/members/new-form")
    public ModelAndView process(){
        return new ModelAndView("new-form");
    }
}

1. @Controller:
   - @Controller 애노테이션은 Spring의 컴포넌트 스캔을 통해 해당 클래스를 스프링 빈으로 등록한다.
   - 주로 MVC 패턴에서 컨트롤러로 사용되는 클래스에 붙인다.
   - 스프링 빈으로 등록된 후, 이 클래스는 요청을 처리하는 메소드들을 포함하게 된다.

2. @RequestMapping:
   - @RequestMapping 애노테이션은 클래스나 메소드에 붙여서 특정 URL 패턴을 해당 클래스나 메소드와 매핑한다.
   - 클래스 레벨에 붙으면, 해당 클래스 내의 모든 메소드에 공통적으로 적용되는 URL 패턴을 정의한다.
   - 메소드 레벨에 붙으면, 특정 HTTP 요청을 처리하기 위해 URL 패턴을 정의한다.

3. RequestMappingHandlerMapping:
   - 스프링의 핵심 컴포넌트 중 하나로, 핸들러 매핑 정보를 관리한다.
   - 애플리케이션 컨텍스트에서 스캔한 모든 스프링 빈 중 @RequestMapping이나 @Controller가 클래스 레벨에 붙어 있는 경우, 이 정보를 기반으로 요청 URL과 실제 처리 메소드를 매핑한다.
   - 특정 URL 패턴에 대해 어떤 컨트롤러의 메소드가 호출될지를 결정하는 역할을 한다.

4. ModelAndView:
   - ModelAndView는 Spring MVC에서 데이터와 뷰 정보를 함께 전달하기 위해 사용하는 객체이다.
   - 모델(Model)에는 뷰로 전달할 데이터가 포함되고, 뷰(View)는 데이터를 표시할 템플릿 이름을 포함한다.
   - 컨트롤러 메소드에서 ModelAndView 객체를 반환하면, Spring MVC는 모델 데이터를 설정하고 지정된 뷰를 사용하여 응답을 생성한다.

전체 흐름 설명:
1. 스프링 빈 등록:
   - @Controller 애노테이션이 붙은 클래스는 스프링의 컴포넌트 스캔에 의해 자동으로 스프링 빈으로 등록된다.

2. 매핑 정보 인식:
   - RequestMappingHandlerMapping은 스프링 컨텍스트 내에서 @Controller 또는 @RequestMapping이 붙은 클래스를 찾아 해당 클래스를 처리할 수 있는 메소드와 URL 패턴을 매핑 정보로 인식한다.

3. 요청 처리:
   - 클라이언트가 특정 URL로 HTTP 요청을 보내면, DispatcherServlet은 RequestMappingHandlerMapping을 사용해 해당 URL에 매핑된 컨트롤러 메소드를 찾고, 그 메소드를 호출하여 요청을 처리한다.

회원 저장
@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;

    }
}

회원 목록 조회
@Controller
public class SpringMemberListControllerV1 {
    private MemberRepository memberRepository = MemberRepository.getInstance();

    @RequestMapping("/springmvc/v1/members")
    public ModelAndView process() {
        List<Member> members = memberRepository.findAll();
        ModelAndView mv = new ModelAndView("members");
        mv.addObject("members", members);
        return mv;
    }
}


모든 코드가 같은 방식으로 만들어진 것을 알 수 있다.

 

 

스프링 MVC - 컨트롤러 통합

@RequestMapping을 잘 보면 클래스 단위가 아니라 메서드 단위에 적용된 것을 확인할 수 있다. 따라서 컨트롤러 클 래스를 유연하게 하나로 통합할 수 있다.
@Controller
@RequestMapping("/springmvc/v2/members") // v1 경로 중복 제거
public class SpringMemberControllerV2 {
    MemberRepository memberRepository = MemberRepository.getInstance();


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

    @RequestMapping
    public ModelAndView members() {
        List<Member> members = memberRepository.findAll();
        ModelAndView mv = new ModelAndView("members");
        mv.addObject("members", members);
        return mv;
    }

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

    }
}​

 

 

스프링 MVC - 실용적인 방식


/**
* v3
* Model 도입
* ViewName 직접 반환
* @RequestParam 사용
* @RequestMapping -> @GetMapping, @PostMapping */

@Controller
@RequestMapping(value = "/springmvc/v3/members")
public class SpringMemberControllerV3 {
    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
    public String members(Model model) {
        List<Member> members = memberRepository.findAll();
        model.addAttribute("members",members);
        return "members";
    }

}

SpringMemberControllerV2 방식

특징:

  1. @RequestMapping 애노테이션을 사용하여 모든 HTTP 메소드(GET, POST 등)를 처리할 수 있는 멀티 메소드 매핑을 한다.
  2. ModelAndView 객체를 사용하여 뷰와 모델을 함께 처리한다.
  3. HttpServletRequest 객체를 통해 요청 파라미터를 직접 추출하고 처리한다.

SpringMemberControllerV3 방식

특징:

  1. @GetMapping과 @PostMapping 애노테이션을 사용하여 각각 GET과 POST 요청을 명시적으로 처리한다.
  2. 반환 타입으로 뷰 이름을 직접 반환하고, Model 객체를 통해 모델 데이터를 설정한다.
  3. @RequestParam 애노테이션을 사용하여 메소드 파라미터로 직접 요청 파라미터를 바인딩한다.

비교 정리

  1. 요청 매핑 방식:
    • V2: @RequestMapping을 사용하여 모든 HTTP 메소드에 대한 요청을 처리한다.
    • V3: @GetMapping과 @PostMapping을 사용하여 HTTP 메소드별로 명시적으로 처리한다.
  2. 모델과 뷰 처리 방식:
    • V2: ModelAndView 객체를 사용하여 뷰와 모델을 함께 처리한다.
    • V3: 반환 타입으로 뷰 이름을 직접 반환하고, Model 객체를 통해 모델 데이터를 설정한다.
  3. 요청 파라미터 처리:
    • V2: HttpServletRequest 객체를 통해 요청 파라미터를 직접 추출한다.
    • V3: @RequestParam 애노테이션을 사용하여 메소드 파라미터로 직접 요청 파라미터를 바인딩한다.
  4. 코드 간결성 및 가독성:
    • V2: 코드가 다소 길어지고 복잡할 수 있다.
    • V3: 코드가 더 간결하고 가독성이 좋다.

 

728x90