Backend/Spring Framework

[Spring Boot] Model, View, Controller 완전 정복

mopil 2022. 1. 26. 09:15
반응형

# 모델, 뷰, 컨트롤러의 역할

모델

데이터를 담는 일종의 박스

 

사용자에게 보여질 페이지를 렌더링

 

컨트롤러

사용자의 요청(URL)을 받아서 처리할 로직을 확인한 뒤, View를 반환(or HTTP 응답)하는 역할

(실질적인 비즈니스 로직은 서비스에서 처리)

 

 

# 웹 요청 처리의 전반적인 흐름도

  1. 클라이언트가 요청
  2. DispatcherServlet이 해당 URL요청을 제일 먼저 받음 (문지기 역할)
  3. HandlerMapping : 해당 URL를 처리할 수 있는 컨트롤러를 탐색
  4. 컨트롤러 호출 : URL 처리 및 ModelAndView를 받아옴
  5. 컨트롤러 실행 결과를 뷰 리졸버에게 전달
  6. 뷰 렌더링 (응답 출력)

 

컨트롤러 내부에서 모델에 데이터를 설정하고 뷰로 보내면, 뷰에서 해당 데이터를 사용할 수 있다

@GetMapping("/member")
public String getMember(Model model) {
    model.addAttribute("member", member1);
    return "/member/data";
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Document</title>
    </head>
    <body>
        <p th:text="${member.name}"></p>
        <p th:text="${member.age}"></p>
    </body>
</html>

(타임리프 예시)

 

# 컨트롤러 리턴 후보군

*컨트롤러의 리턴은 뷰 리졸버가 처리해준다

뷰 템플릿

- String : 해당 논리 주소의 뷰(템플릿)를 찾아감

- void : 호출하는 URI와 동일한 이름의 뷰를 찾아감 (비권장)

- ModelAndView

 

@ResponseBody (@RestController)

*API 서버를 만들때 사용

- String : HTTP 응답 바디에 텍스트를 찍는다.

- 객체 : 스프링 메시지 컨버터가 해당 객체를 JSON 형태로 변환해서 HTTP 응답으로 내려줌

 

 

 

# 컨트롤러 파라미터 후보군

Model

- 뷰로 데이터를 넘기고 싶을 때

@RequestMapping("/model")
public String 모델넘겨주기(Model model) {
	Member member = new Member("삽질맨", 25);
	model.addAttribute("member", member);
    return "아무경로";
}

 

HttpServletRequest

@RequestMapping("/request")
public String 요청그대로받기(HttpServletRequest request) {
    String name = request.getParameter("a");
    Integer age = request.getParameter("b");

    log.info("name = {}, age = {}", name, age);
    return "아무경로";
}

 

@ReqeustParam

- 요청 파라미터를 1:1로 받기

@RequestMapping( "/param")
public String 일대일로받기(@RequestParam("name") String name, @RequestParam("age") int age) {
    log.info("name = {}, age = {}", name, age);
    return "아무경로";
}

 

@ModelAttribute

- 요청 파라미터를 객체로 한번에 받기

@RequestMapping("/object")
public String 객체로받기(@ModelAttribute Member member) {
	log.info("name = {}, age = {}", member.name, member.age);
	return "아무경로";
}

 

@PathVariable

- URL로 넘어온 쿼리 파라미터를 받아서 변수에 넣는다

@RequestMapping("/path/{name}/{age}")
	String 아무이름(@PathVariable("name") String name, @PathVariable("age") int age){
		log.info("name = {}, age = {}", name, age);
		return "아무경로";
	}

 

*컨트롤러의 파라미터는 도대체 누가 넣어주는 걸까?

=> @RequestMapping으로 핸들러 매핑 + 어댑터가 호출되면서 Argument Resolver라는 녀석을 호출하는데, 얘가 컨트롤러에 들어가는 모든 파라미터를 자기가 처리한 뒤, 컨트롤러 파라미터로 전달하면서 컨트롤러를 호출한다

 

HTTP Request

클라이언트에서 서버로 요청 데이터를 전달할 때는 주로 다음 3가지 방법을 사용한다

 

1. GET - 쿼리 파라미터

  • /url?username=hello&age=20
  • 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
  • 예) 검색, 필터, 페이징 등에서 많이 사용하는 방식

2. POST - HTML Form

  • content-type : application/x-www-form-urlencoded
  • 메시지 바디에 쿼리 파리미터 형식으로 전달 username=hello&age=20
  • 예) 회원 가입, 상품 주문, HTML Form 사용

3. HTTP 메시지 바디에 데이터를 직접 담아서 요청

  • HTTP API 에서 주로 사용, JSON, XML, TEXT
  • 데이터 형식은 주로 JSON 사용
  • POST, PUT, PATCH

 

1,2번 방식은 URL로 요청 파리미터가 넘어오는 방식이고 3번은 HTTP 바디에 데이터를 포함해서 넘어오는 방식으로써 서로 조회하는 방법이 다르다

 

[1,2번 경우]

@RequestParam : 요청 파라미터를 담을 변수 하나하나 앞에 적어주고 컨트롤러 파라미터로 넣어서 사용

@ModelAttribute : 요청 파라미터 구조와 동일한 객체가 존재하면 이 어노테이션과 객체 타입을 파리미터로 넣어서 사용해도 됨

 

둘 다 어노테이션을 생략할 수 있는데, 둘 다 그러면 헷갈리니까 명시해주자

만약, 둘 다 생략시 스프링이 알아서 넣어준다.

String, int, Integer와 같이 단순한 타입 => @RequestParam

나머지 => @ModelAttribute

 

[3번의 경우]

1,2번과 다르므로 위 어노테이션들은 사용할 수 없다

@RequestBody : 이 어노테이션을 적고 객체 타입을 컨트롤러 파라미터로 넘긴다

@ResponseBody : 해당 컨트롤러 return 값을 그대로 HTTP 메시지 바디에 넣어서 보낸다

 

 

<정리>

요청 파라미터를 조회하는 기능 : @RequestParam, @ModelAttribute

HTTP 메시지 바디를 직접 조회하는 기능 : @RequestBody

 

 

HTTP Response

서버(스프링)에서 응답 데이터를 만드는 방법은 크게 3가지 이다

 

1. 정적 리소스

  • 예) 웹 브라우저에 정적인 HTML, css, js을 제공할 때는, 정적 리소스를 사용한다

2. 뷰 템플릿 사용

  • 예) 웹 브라우저에 동적인 HTML을 제공할 때는 뷰 템플릿을 사용한다

3. HTTP 메시지 사용

  • HTTP API를 제공하는 경우에는 HTML이 아니라 데이터를 전달해야 하므로, HTTP 메시지 바디에 JSON 같은 형식으로 데이터를 실어 보낸다
반응형