02.MVC
Last updated
Last updated
Model
View 에 출력할 데이터를 담는 역할(View 는 화면 렌더링에만 집중)
View
Model 에 담겨있는 데이터를 사용해서 화면(HTML)을 그리는 역할
Controller
HTTP 요청을 받아서 파라미터를 검증하고, 비즈니스 로직을 실행하는 역할
전달할 데이터를 조회해서 Model 을 통해 View 로 전달
DispacherServlet
DispatcherServlet ➜ FrameworkServlet ➜ HttpServletBean ➜ HttpServlet
스프링 부트는 DispacherServlet 을 서블릿으로 자동으로 등록하고, 모든 경로(urlPatterns="/")를 매핑
DispacherServlet.doDispatch() 참고
핸들러 조회 : 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회
핸들러 어댑터 조회 : 핸들러를 실행할 수 있는 핸들러 어댑터를 조회
핸들러 어댑터 실행 : 핸들러 어댑터를 실행
핸들러 실행 : 핸들러 어댑터가 실제 핸들러를 실행
ModelAndView 반환 : 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환
viewResolver 호출 : viewResolver를 찾고 실행 (JSP의 경우 InternalResourceViewResolver 가 자동 등록&사용)
View 반환 : viewResolver는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 뷰 객체 반환 (JSP의 경우 InternalResourceView(JstlView) 를 반환하는데, 내부에 forward() 로직 존재)
뷰 렌더링 : 뷰를 통해서 뷰를 렌더링
주요 인터페이스
HandlerMapping
, HandlerAdapter
, ViewResolver
, View
컨트롤러 호출 과정
(1) 핸들러 매핑으로 핸들러 조회
HandlerMapping 을 순서대로 실행해서, 핸들러 찾기
RequestMappingHandlerMapping : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러를 찾는다.
빈 이름으로 핸들러를 찾을 경우, 빈 이름으로 핸들러를 찾아주는 BeanNameUrlHandlerMapping 가 실행에 성공하고 핸들러인 Controller 를 반환
(2) 핸들러 어댑터 조회
HandlerAdapter 의 supports() 를 순서대로 호출
RequestMappingHandlerAdapter : 애노테이션 기반의 컨트롤러인 @RequestMapping에서사용
HttpRequestHandlerAdapter : HttpRequestHandler 처리
SimpleControllerHandlerAdapter : Controller 인터페이스 (애노테이션X, 과거에 사용) 처리
SimpleControllerHandlerAdapter 가 Controller 인터페이스를 지원하므로 대상이 된다.
(3) 핸들러 어댑터 실행
디스패처 서블릿이 조회한 SimpleControllerHandlerAdapter 를 실행하면서 핸들러 정보도 함께 넘겨준다.
SimpleControllerHandlerAdapter 는 핸들러인 Controller 를 내부에서 실행하고, 그 결과를 반환
ViewResolver 호출 과정
(1) 핸들러 어댑터 호출
핸들러 어댑터를 통해 논리 뷰 이름을 획득
(2) ViewResolver 호출
논리 뷰 이름으로 viewResolver를 순서대로 호출
BeanNameViewResolver : 빈 이름으로 뷰를 찾아서 반환
InternalResourceViewResolver : JSP를 처리할 수 있는 뷰를 반환
논리 뷰 이름의 스프링 빈으로 등록된 뷰가 없다면 InternalResourceViewResolver 가 호출
(3)InternalResourceViewResolver
InternalResourceView 를 반환
(4) 뷰 - InternalResourceView
InternalResourceView 는 JSP처럼 포워드 forward() 를 호출해서 처리할 수 있는 경우에 사용
(5) view.render() view.render() 가 호출되고 InternalResourceView 는 forward() 를 사용해서 JSP를 실행
프로젝트 설정
Jar 사용 시 항상 내장 서버(tomcat..)를 사용 (내장 서버 최적화)
War 사용 시 주로 외부 서버에 배포하는 목적으로 사용
SpringBoot 가 기본으로 제공하는 Logback 을 대부분 사용
SLF4J interface 의 구현체인 Logback
로그 레벨 설정
application.properties 에서 log level 설정 가능
TRACE > DEBUG > INFO > WARN > ERROR
보통 개발 서버는 debug, 운영 서버는 info level
로그 선언
Lombok 사용 시
java 코드로 선언 시
로그 호출
Controller Annotation
@Controller : 반환 값이 String 이면 뷰 이름으로 인식(뷰를 찾고 랜더링)
@RestController : 반환 값으로 뷰를 찾는 것이 아니라, HTTP 메시지 바디에 바로 입력
축약 Annotation
@PathVariable : 최근 HTTP API는 리소스 경로에 식별자를 넣는 스타일을 선호
특정 파라미터/헤더로 추가 매핑
파라미터의 경우 params, 헤더의 경우 headers
params = {"mode=debug","data=good"}
Content-Type 헤더 기반 추가 매핑 Media Type
Server 입장에서 특정 Media Type만 받을 수 있다고 요청 헤더의 Content-Type으로 전달
Accept 헤더 기반 Media Type
Client 입장에서 특정 Media Type만 받을 수 있다고 요청 헤더의 Accept로 전달
HttpServletRequest request
HttpServletResponse response
HttpMethod httpMethod
HTTP 메서드를 조회 (org.springframework.http.HttpMethod)
Locale locale
Locale 정보를 조회
@RequestHeader MultiValueMap<String, String> headerMap
모든 HTTP 헤더를 MultiValueMap 형식으로 조회
@RequestHeader("host") String host
특정 HTTP 헤더를 조회
속성 (required, defaultValue)
@CookieValue(value = "myCookie", required = false) String cookie
특정 쿠키를 조회
속성 (required, defaultValue)
클라이언트에서 서버로 데이터를 전달하는 방법
GET - Query Parameter
/url?username=hello&age=20
URL Query Parameter에 데이터를 포함해서 전달
ex) 검색, 필터, 페이징 등
POST - HTML Form
content-type: application/x-www-form-urlencoded
Message Body에 Query Parameter 형식으로 전달 (username=hello&age=20)
ex) 회원 가입, 상품 주문, HTML Form
HTTP message body에 데이터를 직접 담아서 요청
HTTP API에서 주로 사용, JSON, XML, TEXT
POST, PUT, PATCH
Get, Post 방식의 Query Parameter binding
파라미터 이름으로 바인딩
request.getParameter("name") 와 동일한 효과
생략
HTTP 파라미터 이름이 변수 이름과 같으면 value name 생략 가능
String, int 등 단순 타입이면 @RequestParam 생략 가능
required
파라미터 필수 여부 (default = true )
defaultValue
기본 값 적용 (빈 문자도 기본 값으로 처리)
requestParamMap
모든 요청 파라미터 받기
@RequestParam Map<String, Object> paramMap
paramMap.get("username")
파라미터 값이 여러개라면 MultiValueMap 사용
@ResponseBody
String return 시 View 조회를 무시하고, HTTP message body에 직접 해당 내용 입력
@ModelAttribute
바인딩할 객체 생성
요청 파라미터의 이름으로 바인딩 객체의 프로퍼티를 찾고, 해당 프로퍼티의 setter를 호출해서 파라미터의 값을 입력(바인딩)
ex) 파라미터 이름이 username 이면 setUsername() 메서드를 찾아 호출하면서 값을 입력
HTTP Message Body Data 를 InputStream 을 사용해서 직접 읽을 수도 있지만, Spring MVC는 HttpEntity 지원
HttpEntity를 상속받은 RequestEntity, ResponseEntity
RequestEntity : HttpMethod, url 정보 등 추가 정보 제공
ResponseEntity : HTTP 상태 코드 설정 가능
@RequestBody 사용
header 가 필요하다면 @RequestHeader
@RequestBody
생략 불가능(생략 시 @ModelAttribute 적용)
HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter
content-type: application/json
응답의 경우에도 @ResponseBody 를 사용하면 해당 객체를 HTTP 메시지 바디에 직접 넣어줄 수 있음
@RequestBody 요청 : JSON 요청 -> HttpMessageConverter(JSON) -> 객체
contenttype: application/json
@ResponseBody 응답 : 객체 -> HttpMessageConverter(JSON) -> JSON 응답
Accept: application/json
Spring Response Data 생성 방법
정적 리소스
HTML, css, js 제공
기본 경로 : src/main/resources/static
Path : src/main/resources/static/basic/hello-form.html
URI : http://localhost:8080/basic/hello-form.html
View Template 사용
동적인 HTML 제공
기본 경로 : src/main/resources/templates
Path : src/main/resources/templates/response/hello.html
HTTP Message 사용
HTTP API - HTTP Message Body에 데이터를 담아 제공
ResponseBody
ResponseEntity
응답코드를 동적으로 변경 시 사용
ResponseBody
ResponseEntity
응답코드를 동적으로 변경 시 사용
HTTP Message Converter 적용 시기
HTTP 요청: @RequestBody, HttpEntity(RequestEntity)
HTTP 응답: @ResponseBody, HttpEntity(ResponseEntity)
Spring Boot Base Message Converter
0_ ByteArrayHttpMessageConverter
byte[] 데이터를 처리
클래스 타입: byte[] , content-type: */*
요청 ex) @RequestBody byte[] data
응답 ex) @ResponseBody return byte[] 쓰기 content-type application/octet-stream
1_ StringHttpMessageConverter
String 문자로 데이터를 처리한다.
클래스 타입: String , content-type: */*
요청 ex) @RequestBody String data
응답 ex) @ResponseBody return "ok" 쓰기 content-type text/plain
2_ MappingJackson2HttpMessageConverter
application/json
클래스 타입: 객체 또는 HashMap, content-type: application/json 관련
요청 ex) @RequestBody HelloData data
응답 ex) @ResponseBody return helloData 쓰기 content-type application/json 관련
HTTP Message Converter 는 RequestMappingHandlerAdapter -> ArgumentResolver, Handler -> ReturnValueHandler 에서 사용되어 필요한 객체를 생성
ArgumentResolver
파라미터를 유연하게 처리
애노테이션 기반 컨트롤러를 처리하는 HandlerMethodArgumentResolver 는 supportsParameter() 를 호출해서 해당 파라미터를 지원하는지 체크
지원하면 resolveArgument() 를 호출해서 핸들러가 필요로 하는 다양한 값(객체)을 생성
이렇게 생성된 객체가 핸들러(컨트롤러) 호출 시 넘어 감
ReturnValueHandler
HandlerMethodReturnValueHandler 는 ArgumentResolver 와 비슷한 방식으로 응답값을 변환 및 처리
등록을 완료하고 웹 브라우저를 새로고침 시 중복 등록되는 오류 해결
상품 등록 폼 이동
상품 저장 및 삼품 상세 페이지로 redirect
상품 상세페이지 이동