[스프링&JPA 스터디] #13 스프링 MVC - 구조 이해

오예찬·2023년 7월 20일
0

spring&jpa 스터디

목록 보기
13/15

스프링 MVC 전체 구조

직접 만든 MVC 프레임워크 구조

SpringMVC 구조

동적 순서
1.핸들러 조회: 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회

2.핸들러 어댑터 조회: 핸들러를 실행할 수 있는 핸들러 어댑터를 조회

3.핸들러 어댑터 실행: 핸들러 어댑터를 실행

4.핸들러 실행: 핸들러 어댑터가 실제 핸들러를 실행

5.ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환

6.viewResolver 호출: 뷰 리졸버를 찾고 실행

7.View 반환: 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 뷰 객체를 반환

8.뷰 렌더링: 뷰를 통해서 뷰를 렌더링

스프링 MVC

스프링이 제공하는 컨트롤러는 애노테이션 기반으로 동작해서, 매우 유연하고 실용적이다.

@RequestMapping


예제 코드

package hello.servlet.web.springmvc.v1;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class SpringMemberFormControllerV1 {

 	@RequestMapping("/springmvc/v1/members/new-form")
 	public ModelAndView process() {
 		return new ModelAndView("new-form");
 	}
}
  • @Controller:
    • 스프링이 자동으로 스프링 빈으로 동록한다. (내부에 @Component애노테이션이 있어서 컴포넌트 스캔의 대상이 됨)
    • 스프링 MVC에서 애노테이션 기반 컨트롤러로 인식한다.
  • RequestMapping: 요청 정보를 매핑한다. 해당 URL이 호출되면 이 메서드가 호출된다. 애노테이션을 기반으로 동작하기 때문에, 메서드의 이름은 임의로 지으면 된다.
  • ModelAndView: 모델과 뷰 정보를 담아서 반환하면 된다.

컨트롤러 통합

@RequestMapping 을 잘 보면 클래스 단위가 아니라 메서드 단위에 적용된 것을 확인할 수 있다. 따라서 컨트롤러 클래스를 유연하게 하나로 통합할 수 있다

예제 코드

package hello.servlet.web.springmvc.v2;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

/**
 * 클래스 단위 -> 메서드 단위
 * @RequestMapping 클래스 레벨과 메서드 레벨 조합
 */
@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
    public ModelAndView members() {

        List<Member> members = memberRepository.findAll();

        ModelAndView mv = new ModelAndView("members");
        mv.getModel().put("members", members);
        return mv;
    }
}

실용적인 방식

아래는 실무에서 주로 사용하는 방식을 설명한다.

예제 코드

package hello.servlet.web.springmvc.v3;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * v3
 * Model 도입
 * ViewName 직접 반환
 * @RequestParam 사용
 * @RequestMapping -> @GetMapping, @PostMapping
 */
@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";
    }

    @PostMapping
    public String members(Model model) {

        List<Member> members = memberRepository.findAll();

        model.addAttribute("members", members);
        return "members";
    }

}

Model 파라미터
save(), members()를 보면 Model을 파라미터로 받는 것을 확인할 수 있다. 스프링 MVC도 이런 편의 기능을 제공한다.


ViewName 직접 반환
뷰의 논리 이름을 반환할 수 있다.

@RequestParam
스프링은 HTTP 요청 파라미터를 @RequestParam 으로 받을 수 있다

@RequestMapping @GetMapping, @PostMapping
@RequestMapping은 URL만 매칭하는 것이 아니라, HTTP Method도 함께 구분할 수 있다. 예를 들어서 URL이 /new-form이고, HTTP Method가 GET인 경우를 모두 만족하는 매핑을 하려면 다름과 같이 처리 하면 된다.

@RequestMapping(value = "/new-form", method = RequestMethod.GET)
  • 이것을 @GetMapping, @PostMapping으로 더 편리하게 사용할 수 있다. Get, Post, Put, Delete, Patch 모두 애노테이션이 준비되어 있다.



참고

profile
안녕하세요. 반갑습니다.

1개의 댓글

comment-user-thumbnail
2023년 7월 20일

글이 많은 도움이 되었습니다, 감사합니다.

답글 달기