[Spring boot] MVC 패턴(MVC구조/어노테이션)

예림·2024년 6월 5일
6

Spring boot

목록 보기
2/8
post-thumbnail

MVC 패턴이란

Model, View, Controller의 약자이다.

애플리케이션을 개발할 때 구성요소를 3가지의 역할로 구분한 것을 말한다.

Model

Model은 기능을 수행하는 서비스이자 비즈니스 로직이다.

View

View는 사용자에게 보여지는 화면이자 UI(사용자 인터페이스)를 의미한다.

Controller

Controller는 모델과 뷰의 중간 다리 역할을 하는 영역이다.

사용자의 요구사항을 처리해줄 서비스의 메서드(비즈니스 로직)를 호출하고, 그에 대한 실행 결과를 다시 화면으로 전달해주는 역할을 한다.


스프링 MVC 구조

Dispatcher Servelet

스프링 MVC의 프론트 컨트롤러이다.

가장 앞단에서 클라이언트의 요청을 처리하는 컨트롤러로 전반적인 처리과정을 관리한다.

DispacherServlet 도 부모 클래스에서 HttpServlet을 상속받아서 사용하고, 서블릿으로 동작한다.

Handler

Handler는 스프링 MVC에서 웹 요청을 처리하는 객체를 의미한다.

컨트롤러를 일종의 핸들러라 부를 수 있다.

핸들러는 DispatcherServlet가 전달해준 HTTP 요청을 처리하고 결과를 Model에 저장한다.

ModelAndView

컨트롤러 처리 결과 후 반환된 Model과 View가 담긴 객체이다.

viewResolver

ModelAndView를 처리하여 View를 반환한다.Model에 있는 데이터를 이용하여 View에 데이터 정보를 넘긴다.

  1. 핸들러 조회: 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회한다.
  2. 핸들러 어댑터 조회: 핸들러를 실행할 수 있는 핸들러 어댑터를 조회한다.
  3. 핸들러 어댑터 실행: 핸들러 어댑터를 실행한다.
  4. 핸들러 실행: 핸들러 어댑터가 실제 핸들러를 실행한다.
  5. ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환한다.
  6. viewResolver 호출: 뷰 리졸버를 찾고 실행한다. JSP의 경우: InternalResourceViewResolver 가 자동 등록되고, 사용된다.
  7. View 반환: 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 뷰 객체를 반환한다. JSP의 경우 InternalResourceView(JstlView)를 반환하는데, 내부에 forward() 로직이 있다.
  8. View 렌더링: 뷰를 통해서 뷰를 렌더링 한다.

클라이언트 서버의 비동기 통신

  • 비동기 통신을 위해서는 클라이언트에서 서버로 요청 메세지를 보낼 때, 본문에 데이터를 담아서 보내야함
  • 서버에서 클라이언트로 응답을 보낼 때에도 본문에 데이터를 담아 보내야함
  • 본문 = “body”
  • 요청 본문 = requestBody / 응답 본문 = responseBody

@요청/응답 어노테이션

  1. 요청 데이터
  • @RequestParam
    • 'HTTP 요청 파라미터'를 매개변수로 전달받는 어노테이션
    • HttpServletRequest의 request.getParameter() 기능과 동일
    • Http 요청 파라미터의 이름으로 바인딩하여 그 값을 변수에 저장한다.
    • Http 파라미터 이름이 변수 이름과 같으면 @RequestParam의 value를 생략 가능
    • String, int, Integer 등의 단순 타입이면 생략 가능
      @GetMapping("/check-username")
      public boolean checkUsername(@RequestParam String loginId) {
      				return service.checkLoginIdDuplicate(loginId);
      }
    • @RequestParam에 required 옵션을 주어 true일 경우는 필수, false일 경우는 필수가 아닌 것으로 설정 가능하다.
      @GetMapping("/check-username")
      public boolean checkUsername(@RequestParam(required = true) String username,
      														@RequestParam(required = false) Integer idx) {
      				return service.checkLoginIdDuplicate(username, idx);
      }
    • 요청 파라미터 값이 없는 경우 defalutValue 설정 가능
    • 이 경우 null 대신 1이 저장되어 int를 사용할 수 있다.
      @GetMapping("/check-username")
      public boolean checkUsername(@RequestParam(required = true, defaultValue = "test") String username,
      														@RequestParam(required = false, defaultValue = "1") Integer idx) {
      				return service.checkLoginIdDuplicate(username, idx);
      }
    • Map에 key, value형태로 파라미터와 파라미터 값이 저장된다.
    • 동일한 이름의 파라미터 값이 2개 이상이면 MultiVaueMap 사용
      @GetMapping("/check-username")
      public boolean UserMap(@RequestParam Map<String, Object> paramMap) {
      				return service.checkLoginIdDuplicate(paramMap);
      }
  • @RequestBody
    • 'HTTP 요청의 '본문(body)'을 매개변수로 전달받는 어노테이션
    • GET 통신에서는 @RequestParam을 사용하지만,
    • POST 통신에서는 @RequestBody를 사용
      @PostMapping("/users")
      public void createUser(@RequestBody UserVO userVO) {
      		log.info(userVO.getUserId() + "/" + userVO.getUserNm()); // 출력 결과 : test123 / 개발새발
      }
  • @PathVariable
    • REST API에서 URL의 값을 처리하기 위해 사용한다.
    • http://localhost:8080/user/info/userId
    • userId 값을 url을 통해 가져올 때 @PathVariable을 이용한다.
      @GetMapping("/user/info/{userId}")
      public String userInfo(@PathVariable String userId, Model model) {
              log.info("Fetching user info for userId: {}", userId);
              User user = service.getLoginUser(userId);
              if (user == null) {
                  log.warn("User not found for userId: {}", userId);
                  return "redirect:/login";
              }
              log.info("User found: {}", user);
              model.addAttribute("user", user);
              return "user/info";
      }
    • @PathVariable의 이름과 파라미터의 이름이 같으면 생략 가능
    • 다중 사용도 가능하다.
      @GetMapping("/user/info/{userId}/id/{idx}")
      public String userInfo(@PathVariable String userId, @PathVariable int idx) {
              log.info("Fetching user info for userId: {}, idx:{}", userId, idx);
              
              return "user/info";
      }
  • @ModelAttribute
    • HTTP 요청 파라미터를 받아 일일이 객체에 저장하는 과정을 자동화해준다.
    • 생략 가능
    • String , int , Integer 같은 단순 타입을 제외한 나머지에 적용
    • User는 객체이기 때문에 @ModelAttribute 적용 가능
      @GetMapping("/user/info/{userId}")
      public String userInfo(@ModelAttribute User user) {
              log.info("Fetching user info for userId: {}, username={}", user.getUserId(), user.getUsername());
              return "user/info";
      }

  1. 응답 데이터
  • @ResponseBody
    • HTTP 응답의 본문(body)을 생성하는 메서드에 적용하는 어노테이션
    • @Controller + @Responsebody를 합친 것이 @RestController
    • @ResponseBody가 붙은 파라미터가 있으면 HTTP요청의 미디어타입과 파라미터타입을 먼저 확인한다.
      @GetMapping("/data")
      public @ResponseBody List<String> getData() {
      		List<String> list = new ArrayList<>();
      		list.add("도레미");
      		list.add("파솔라");
      		list.add("시도");
      		
      		return list; 
      }
  • @ResponseStatus
    • HTTP 응답의 상태 코드를 지정하는 어노테이션
    • http 상태 코드는 HttpStatus 클래스에 따라 구체적으로 정의되고 있다.
      @GetMapping("/users/{id}")
      @ResponseStatus(HttpStatus.NOT_FOUND)
      	public void getUserById(@PathVariable String id) {
      }
profile
백엔드 개발하는 사람

0개의 댓글