정리할 내용은 공식 문석에 더 자세한 내용이 있으니 필요하다면 한 번 살펴보시는 것을 추천드립니다.
DispatcherServlet의 동작 중에 RequestMappingHandler라는 특별한 Bean에 의해 요청을 처리할 Handler를 찾게 됩니다.
여기서 Handler는 개발자가 외부 요청을 어떻게 처리할 지에 대해 서술해놓은 것을 말합니다.
사용자의 요청이 어떤 Handler를 통해 처리해줘야할 지 정해지는 방식에는 여러가지 요소가 있습니다.
추가로 스프링에 의해 자동으로 처리되는 HEAD
와 OPTIONS
Method에 관한 내용도 있습니다.
@Controller
public class EventController {
// @RequestMapping("/hello", method=RequestMethod.GET)
@GetMapping("/hello")
@ResponseBody
public String events() {
return "Hello";
}
}
위와 같이 간단히 @Controller
속에 Handler를 정의하면 간단히 GET /events
에 대한 요청에 알맞는 웹페이지나 데이터를 응답으로 제공해줄 수 있습니다.
위와 같이 Handler를 만들고 제대로 의도한대로 테스트하기 위해서 Spring에서 제공해주는 MockMvc
Bean을 활용하면 편리하게 테스트가 가능합니다.
JUnit5 기준으로 아래와 같은 코드로 테스트를 할 수 있습니다.
@AutoConfigureMockMvc
를 적용해줘야지 MockMvc를 빈을 주입받을 수 있습니다.
@SpringBootTest
@AutoConfigureMockMvc
class HelloControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void test1() {
mockMvc.perform(get("/hello")
.andExpect(status().isOk())
.andExpect(content().string("Hello"));
}
}
MockMvc
는 작성한 Handler의 테스트를 위해 요청을 만들고 적절한 응답을 받는지, 적절한 Header값을 갖는지 등등 여러가지 테스트를 할 수 있습니다.
MockMvc에 대해 익숙해지면 손쉽게 Handler들을 테스트할 수 있습니다.
요청의 HTTP Method에 따라 Handler를 매핑할 수 있습니다.
앞서 보았듯이 @RequestMapping
를 이용하면 Handler를 정의할 수 있습니다.
Spring 에서는 Composite Annotation을 사용해서 @RequestMapping
를 확장한 각 HTTP Method에 대응하는 @GetMapping
,@PostMapping
, @PutMapping
, @DeleteMapping
, @DeleteMapping
, @PatchMapping
Annotation을 이용해서 간결하게 핸들러를 정의할 수 있습니다.
Handler 매핑의 가장 기준이 되는 그리고 URI 문자열을 토대로 매핑이 됩니다. Spring 에서는 다양한 문자열 패턴 매핑을 제공해줍니다.
/resources/ima?e.png
- match one character in a path segment
/resources/*.png
- match zero or more characters in a path segment
/resources/**
- match multiple path segments
/projects/{project}/versions
- match a path segment and capture it as a variable
/projects/{project:[a-z]+}/versions
- match and capture a variable with a regex
@PathVariable
어노테이션을 활용할면 URI속 값을 변수로 읽어들일 수 있습니다.
@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}
path 속 .../{owenerId}/...
을 argument의 이름(ownerId
)과 일치시켜서 원하는 타입의 형태로 얻어올 수 있습니다. 그리고 @PathVariable("ownerId") Long id
와 같이 직접 명시적으로 이름을 지정해서 가져올 수도 있습니다.
HTTP 요청에 대한 핸들러를 매핑할 때 주로 활용될 수 있는 Http Header 중에 Content-Type
과 Accept
가 있습니다.
요청하는 데이터의 타입을 나타내는 헤더입니다.
응답받을 데이터의 타입을 명시하는 헤더입니다.
Spring MVC에서는 위와 같이 요청하는 클라이언트에서 어떤 타입의 데이터를 보내고 어떤 타입의 응답을 받을 지를 표시하는 것을 통해 Handler 매핑을 할 수 있습니다.
@RequestMapping(value="/hello",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
속성값 consumes
는 받아들이는 Content-Type
에 해당하고 produces
는 응답을 나타내는 Accept
Header값에 해당합니다.
각 MediaType은 Spring에서 org.springframework.http
패키지를 통해 상수형태로 제공됩니다.
_VALUE
는 문자열을 나타냅니다.
아까 소개했던 MockMvc
를 활용해서 MediaType 헤더값도 테스트가 가능합니다.
mockMvc.perform(get("/hello")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk());
위와 같이 contentType과 accept를 붙여서 요청을 했을 때 알맞은 핸들러가 처리했는지 확인할 수 있습니다.
위와 같은 조건으로 Handler Mapping을 처리할 수 도 있습니다.
@GetMapping(path = "/pets/{petId}", params = "myParam=myValue")
public void findPet(@PathVariable String petId) {
// ...
}
@GetMapping(path = "/pets", headers = "myHeader=myValue")
public void findPet(@PathVariable String petId) {
// ...
}
HEAD
Http Method는 GET
Method의 핸들러를 정의했을 때 암묵적으로 스프링에 의해 자동으로 생성됩니다. HEAD 메소드는 GET핸들러에서 처리한 결과의 Header 만 제공하게됩니다.(Body 데이터는 제공x)
OPTIONS
HTTP Method는 @RequestMapping
어노테이션을 정의하면 매칭되는 URI 패턴의 Handler들읠 HTTP Method들을 Allow
Header에 담아보냅니다. CORS관련 처리에 사용되기때문에 알아두면 유용합니다.
아주 간단히 Spring MVC에서 요청 매핑에 관려하는 개념들을 알아봤습니다. 다음으로 요청 매핑 후 핸들러에서 사용되는 여러 Argument 타입과 리턴 타입과 관련된 기능을 알아보겠습니다.