간단히 설명하면, 스프링 MVC는 뷰가 서버 렌더링된 웹페이지로 제공된다는 가정하에, 데이터와 데이터를 전송하는 부분과 데이터를 표현하는 부분을 분리해 생성한다. 이러한 MVC의 여러 부분을 연결하는 데 @Controller 어노테이션을 사용한다. @Controller는 @Component의 스테레오타입이다. 따라서 애플리케이션 실행시, 스프링 빈(애플리케이션 내 객체로서 스프링 IoC 컨테이너에 의해 생성되고 관리됨) @Controller 어노테이션이 붙은 클래스로부터 생성된다. @Controller가 붙은 클래스는 Model 객체를 받는다. Model 객체로 표현 계층에 모델 기반 데이터를 제공한다. 또, ViewResolver와 함께 작동해 애플리케이션 뷰 기술에 의해 렌더링된 특정 뷰를 표시하게 한다.
간단히 @ResponseBody를 클래스나 메서드에 추가해서 JSON이나 XML 같은 데이터 형식처럼 형식화된 응답을 반환하도록 Controller 클래스에 지시할 수도 있습니다(기본적으로 JSON을 사용함). 이렇게 하면 메서드의 객체 반환값이 웹 응답의 전체 바디가 된다. 모델의 일부로 반환되지 않는다. @RestController 어노테이션은 @Controller와 @ResponseBody를 하나의 어노테이션으로 합쳐 쓴 것이다. 결합에 하나의 어노테이션을 사용함으로써 코드를 단순하게 만들고 의도를 더욱 명확하게 표현하게 된다. 클래스에 @RestController로 어노테이션을 달아서 REST API를 만들 수 있다.
REST API
rest api는 객체를 다룬다. 객체는 하나이거나 그룹이다. 예를 들면 모든 커피를 조회하거나, 식별자를 통해 특정 커피를 조회하는 프로젝트가 있다고 하자. 하나 이상의 인스턴스를 조회해야 한다면 여러 메서드를 만드는 편이 낫다.
먼저 아래 코드에서 정의한 기본 클래스는 여러 커피 객체를 반환하는 메서드를 지원하기 위해 커피 객체 목록을 만든다. 커피 그룹은 커피 객체의 List 형태로 정의한다. 멤버 변수 타입을 최상위 인터페이스인 제네릭 List로 만들었지만, RestApiDemonController 클래스 내에서는 비어 있는 ArrayList를 할당해 사용하겠다.
@RestController
class RestApiDemoController {
private List<Coffee> coffees = new ArrayList<>();
}
항상 코드가 예상대로 동작하는지 확인할 데이터가 있는 것이 좋다. 다음 코드에서 REstApiDemoControoler 클래스에 대한 생성자를 마들어 객체 생성 시 커피 목록을 채우는 코드를 추가한다.
@RestController
class RestApiDemoController {
private List<Coffee> coffees = new ArrayList<>();
public RestApiDemoController(){
coffees.addAll(List.of(
new Coffee("Cafe Cereza"),
new Coffee("Cafe Ganador"),
new Coffee("Cafe Lareno"),
new Coffee("Cafe Tres Pontas"),
new Coffee("Ice americano")
));
}
}
다음 코드를 보면, RestApiDemoController 클래스에 iterable한 커피의 그룹을 멤버 변수인 coffees로 반환하는 메서드를 만든다. Iterable<Coffee>를 사요하는 이유는 모든 iterable 유형이 이 API의 원하는 기능을 충분히 제공할 것이기 때문이다. 아래 코드에서는 @RequestMapping 어노테이션으로 커피 목록을 가져온다.
@RestController
class RestApiDemoController {
private List<Coffee> coffees = new ArrayList<>();
public RestApiDemoController(){
coffees.addAll(List.of(
new Coffee("Cafe Cereza"),
new Coffee("Cafe Ganador"),
new Coffee("Cafe Lareno"),
new Coffee("Cafe Tres Pontas"),
new Coffee("Ice americano")
));
}
// @GetMapping("/coffees")
@RequestMapping(value="/coffees", method = RequestMethod.GET)
Iterable<Coffee> getCoffees(){
return coffees;
}
}
@RequestMapping에 대한 유용한 힌트
- @GetMaaping
- @PostMapping
- @PutMapping
- @PatchMapping
- @DeleteMapping
위와 같은 매핑 어노테이션은 클래스나 메서드 수준에서 적용하며 URL 경로를 추가로 적어주면 된다.