스프링 MVC 1편 - 6. 스프링 MVC - 기본 기능
Updated:
김영한님의 인프런 강의 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
위 강의를 정리한 내용입니다.
I. 로깅 알아보기
- 실제 운영 시스템에서는
System.out.println()
과 같은 콘솔로 출력하는 행위는 사용하지 않는다. - 로깅 라이브러리를 사용하자.
- 수많은 라이브러리들을 통합해서 인터페이스로 제공하는 것이
SLF4J
이고, 구현체로 보통은LOGBACK
을 사용한다.
선언
private final Logger log = LoggerFactory.getLogger(getClass());
Lombok
의 기능을 통해@Slf4j
어노테이션으로 대체할 수 있다.
주요 기능
log.trace("trace log={}", name);
log.debug("debug log={}", name);
log.info(" info log={}", name);
log.warn(" warn log={}", name);
log.error("error log={}", name);
- 심각도 별로 레벨을 나누어 로그를 찍을 수 있다.
application.properties
에서logging.level.패키지명=?
과 같은 식으로 어느 레벨부터 보고싶은지 지정할 수 있다.log.trace("trace log=" + name)
과 같은 형식으로 사용하면, 설령 출력하지 않더라도 자바 특성상 두 문자를 더하는 연산이 일어나므로 메모리 낭비가 생긴다.
II. HTTP 요청
매핑
@RequestMapping
- 대부분의 속성을 배열로 제공하여 다중 설정이 가능하다.
{"/hello-basic", "/hello-go"}
- HTTP메서드를 따로 지정하지 않으면 메서드와 무관하게 호출된다.
PathVariable
,경로 변수
사용 가능
@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String data) {
log.info("mappingPath userId={}", data);
return "ok";
}
- 그 외에도 헤더, 파라미터, 미디어 타입 등을 조건으로 설정할 수 있다.
기본, 헤더 조회
HttpServletRequest request
HttpServletResponse response
HttpMethod httpMethod //HTTP메서드 조회
Locale locale //Locale 정보 조회
@RequestHeader MultiValueMap<String, String> headerMap // 모든 HTTP 헤더를 MultiValueMap 형식으로 조회
@RequestHeader("host") String host // 특정 HTTP헤더를 조회
@CookieValue(value = "myCookie", required = false) String cookie // 특정 쿠키를 조회
요청 파라미터 - 쿼리 파라미터, HTML Form
- 기존 배웠던 방식과 동일
public void requestParamV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
log.info("username={}, age={}", username, age);
response.getWriter().write("ok");
}
요청 파라미터 - @RequestParam
public String requestParamV2(
@RequestParam("username") String memberName,
@RequestParam("age") int memberAge)
public String requestParamV3(
@RequestParam String username,
@RequestParam int age)
public String requestParamV4(String username, int age)
- 모두 같은코드
- 단, 실제 넘어오는 파라미터 이름과 변수 이름이 같아야 한다.
- 단순 타입의 경우에는
@RequestParam
도 생략할 수 있다. @RequestParam
이 있으면 명확하게 요청 파라미터에서 데이터를 읽는다는 것을 알 수 있다. -> 생략이 꼭 좋은것만은 아니다.
required
@RequestParam(requried = false)
- 기본값은
true
이다. true
일 경우, 해당 파라미터가 주어지지 않으면Bad Request
를 반환한다.
defaultValue
@RequestParam(defaultValue = “guest”)
- 해당 파라미터가 주어지지 않았을 경우, 기본값을 갖게 된다.
파라미터를 Map으로 조회
@RequestParam Map<String, Object> paramMap
- 파라미터를
Map
으로 일괄조회할 수 있다. - 파라미터의 값이 1개가 확실하다면
Map
을 사용해도 되지만, 그렇지 않다면MultiValueMap
을 사용하자.
요청 파라미터 - @ModelAttribute
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
- 객체가 생성되고, 요청 파라미터의 값이 모두 자동으로 들어간다.
- 알아서 객체의
setter
를 호출하여 값을 채워넣는다.
- 알아서 객체의
@ModelAttribute
마저도 생략할 수 있다.- 단순 타입은
@RequestParam
, 나머지는@ModelAttribute
를 생략한 것으로 본다. - 몇몇은
argument resolver
로 지정되어 제외된다.
- 단순 타입은
요청 메세지 - 단순 텍스트
HttpEntity
: HTTP header, body정보를 편리하게 조회- 응답에도 사용 가능
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("ok");
}
@RequestBody
를 통해 메세지바디를 직접 받아올 수도 있다.
@RequestBody String messageBody
요청 메세지 - JSON
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
@RequestBody
에 직접 만든 객체를 지정할 수 있다.- HTTP 메세지 컨버터가 대신 문자열처리를 해준다.
@RequestBody
는 생략할 수 없다. (@ModelAttribute
로 인식하게 된다)@ResponseBody
를 사용하면 객체를 HTTP 메세지 바디에 직접 넣어 응답할 수 있다.
III. HTTP 응답
정적 리소스, 뷰 템플릿
- 정적 리소스
- 웹 브라우저에 정적인 HTML, css, js를 제공할 때
- 뷰 템플릿
- 웹 브라우저에 동적인 HTML을 제공할 때
- HTTP 메세지 사용
- HTTP API를 사용하는 경우
정적 리소스
src/main/resources
에 리소스를 보관하면 스트링 부트가 정적 리소스로서 서비스를 제공한다.src/main/resources/static/basic/hello-form.html
->http://localhost:8080/basic/hello-form.html
뷰 템플릿
src/main/resources/templates
를 기본 뷰 템플릿 경로로 제공한다.- String을 반환하는 경우
@ResponseBody
가 없으면response/hello
로 뷰 리졸버가 실행되어서 뷰를 찾고 렌더링한다.@ResponseBody
가 있다면 뷰 리졸버를 실행하지 않고 HTTP 메세지 바디에response/hello
가 입력된다.
- Void를 반환하는 경우
- 권장하지 않는다.
IV. HTTP 메세지 컨버터
@ResponseBody
를 사용하면,viewResolver
대싱HttpMessageConverter
가 동작- 스프링 MVC는 다음의 경우에 HTTP 메세지 컨버터를 적용
- HTTP 요청 :
@RequestBody
,HttpEntity(RequestEntity)
- HTTP 응답 :
@ResponseBody
,HttpEntity(ResponseEntity)
- HTTP 요청 :
HttpMessageConverter
는 인터페이스다.canRead()
,canWrite()
메서드를 통하여 메세지 컨버터가 해당 클래스, 미디어타입을 지원하는지 체크한다.
0 = ByteArrayHttpMessageConverter
1 = StringHttpMessageConverter
2 = MappingJackson2HttpMessageConverter
ByteArrayHttpMessageConverter
:byte[]
데이터를 처리한다.- 클래스 타입:
byte[]
, 미디어타입:*/*
- 요청 예)
@RequestBody byte[] data
- 응답 예)
@ResponseBody return byte[]
쓰기 미디어타입application/octet-stream
- 클래스 타입:
StringHttpMessageConverter
:String
문자로 데이터를 처리한다.- 클래스 타입:
String
, 미디어타입:*/*
- 요청 예)
@RequestBody String data
- 응답 예)
@ResponseBody return "ok"
쓰기 미디어타입text/plain
- 클래스 타입:
MappingJackson2HttpMessageConverter
:application/json
- 클래스 타입: 객체 또는
HashMap
, 미디어타입application/json
관련 - 요청 예)
@RequestBody HelloData data
- 응답 예)
@ResponseBody return helloData
쓰기 미디어타입application/json
관련
- 클래스 타입: 객체 또는
HTTP 요청 데이터 읽기
- 컨트롤러에서
@RequestBody
,HttpEntity
파라미터를 사용하는지 확인 - 메세지 컨버터가 읽을 수 있는지 확인하기 위해
canRead()
호출- 대상 클래스 타입을 지원하는가?
- HTTP 요청의 Content-Type 미디어 타입을 지원하는가?
canRead()
를 만족하면read()
를 호출해서 객체생성, 반환
HTTP 응답 데이터 생성
- 컨트롤러에서
@ResponseBody
,HttpEntity
로 값이 반환 - 메세지 컨버터가 메세지를 쓸 수 있는지 확인하기 위해
canWrite()
호출- 대상 클래스 타입을 지원하는가?
- HTTP 요청의 Accept 미디어 타입을 지원하는가?
canWrite()
를 만족하면write()
를 호출해서 HTTP 응답 메세지 바디에 데이터 생성
V. 요청 매핑 핸들러 어댑터 구조
ArgumentResolver
- 어노테이션기반의 컨트롤러는 다양한 파라미터를 사용할 수 있다.
ArgumentResolver
가 그 역할을 한다.- 어노테이션 기반 컨트롤러를 처리하는
RequestMappingHandlerAdaptor
는ArgumentResolver
를 호출해서 컨트롤러가 필요로 하는 다양한 파라미터값을 생성한다. 그리고 이렇게 파라미터의 값이 모두 준비되면 컨트롤러를 호출하면서 값을 넘겨준다.
동작 방식
ArgumentResolver
의 supportsParameter()
를 호출해서 해당 파라미터를 지원하는지 체크하고, 지원하면 resolveArgument()
를 호출해서 실제 객체를 생성한다. 이 객체가 컨트롤러 호출 시 반환된다.
ReturnValueHandler
ArgumentResolver
와 유사하게, 응답 값을 변환하고 처리한다.
Leave a comment