minOS

스프링 MVC 기본 기능 - 요청 매핑 본문

TIL/김영한의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

스프링 MVC 기본 기능 - 요청 매핑

minOE 2024. 7. 21. 17:10
728x90

@Controller   vs @RestController

@Controller
역할 및 기능
- @Controller는 Spring MVC의 기본적인 컨트롤러 어노테이션이다.
- 주로 웹 애플리케이션의 뷰를 반환하는 역할을 한다.
동작 방식
- @Controller가 붙은 클래스의 메서드는 반환 타입에 따라 동작이 달라진다.
- 반환 값이 String인 경우, 이는 뷰의 이름으로 간주된다.
- Spring MVC는 이 뷰 이름을 가지고 적절한 뷰를 찾아 렌더링한다.
- 예를 들어, 메서드가 "home"을 반환하면, Spring MVC는 home.jsp 또는 home.html과 같은 뷰를 찾아 클라이언트에게 전달한다.

@RestController
역할 및 기능:
-@RestController는 RESTful 웹 서비스를 만들기 위해 사용되는 어노테이션이다.
-주로 JSON, XML 등의 데이터를 반환하는 역할을 한다.
동작 방식:
- @RestController는 @Controller와 @ResponseBody를 합친 형태이다.
- 메서드의 반환 값은 뷰 이름이 아닌, HTTP 응답의 바디로 직접 입력된다.
- 따라서, 데이터는 JSON이나 XML 형태로 클라이언트에게 바로 전달된다.

주요 차이점
  1. 뷰 처리:
    • @Controller는 반환 값을 뷰 이름으로 간주하여, 해당 이름의 뷰를 렌더링한다.
    • @RestController는 반환 값을 뷰 이름으로 처리하지 않고, HTTP 응답의 바디로 직접 반환한다.
  2. 사용 목적:
    • @Controller는 주로 서버 사이드 렌더링을 통한 웹 페이지를 반환할 때 사용된다.
    • @RestController는 RESTful API를 구축할 때 사용되어, JSON, XML 등의 데이터를 반환한다.
  3. 어노테이션 구성:
    • @Controller는 단독으로 사용되며, 필요시 @ResponseBody와 함께 사용할 수 있다.
    • @RestController는 @Controller와 @ResponseBody를 합친 형태로, 둘을 따로 사용할 필요가 없다.

결론

  • @Controller는 주로 뷰 이름을 반환하여 뷰를 렌더링하고, @RestController는 데이터를 반환하여 HTTP 응답 바디에 직접 입력한다. 사용 목적과 반환 방식에 따라 적절한 어노테이션을 선택하여 사용하면 된다.


@RestController //@RestController 예시
public class MappingController  {
    private Logger log = LoggerFactory.getLogger(getClass());

    /**
     * 기본 요청
     * 둘다 허용 /hello-basic, /hello-basic/
     * HTTP 메서드 모두 허용 GET, HEAD, POST, PUT, PATCH, DELETE */

    @RequestMapping( "/hello-basic")
    public String helloBasic() {
        log.info( "helloBasic");
        return "ok";
    }


 

 

요청 매핑


HTTP 메서드 매핑 x
`@RequestMapping` 에 `method` 속성으로 HTTP 메서드를 지정하지 않으면 HTTP 메서드와 무관하게 호출된다. 모두 허용 GET, HEAD, POST, PUT, PATCH, DELETE
    /**
     * 기본 요청
     * 둘다 허용 /hello-basic, /hello-basic/
     * HTTP 메서드 모두 허용 GET, HEAD, POST, PUT, PATCH, DELETE */

    @RequestMapping( "/hello-basic")
    public String helloBasic() {
        log.info( "helloBasic");
        return "ok";
    }​
메서드와 상관없이 호출 성공한다.


HTTP 메서드 매핑
/**
* method 특정 HTTP 메서드 요청만 허용
* GET, HEAD, POST, PUT, PATCH, DELETE */    
    
    @RequestMapping(value = "/mapping-get-v1",method = RequestMethod.GET)
        public String mappingGetV1() {
            log.info( "mappingGetV1");
            return "ok";
        }

 GET 요청 의외에는  스프링 MVCHTTP 405 상태코드(Method Not Allowed)를 반환한다.

 


HTTP 메서드 매핑 축약
/**
* 편리한 축약 애노테이션 
* @GetMapping
* @PostMapping
* @PutMapping
* @DeleteMapping
* @PatchMapping
*/
 @GetMapping(value = "/mapping-get-v2")
 public String mappingGetV2() {
     log.info("mapping-get-v2");
return "ok";
}

위의 코드를 축약한 것이다.
HTTP 메서드를 축약한 애노테이션을 사용하는 것이 더 직관적이다. 코드를 보면 내부에서 `@RequestMapping` 과 `method` 를 지정해서 사용하는 것을 확인할 수 있다.


PathVariable(경로 변수) 사용
/**
* PathVariable 사용
* 변수명이 같으면 생략 가능
* @PathVariable("userId") String userId -> @PathVariable String userId */
 @GetMapping("/mapping/{userId}")
 public String mappingPath(@PathVariable("userId") String data) {
     log.info("mappingPath userId={}", data);
     return "ok";
 }

 

http://localhost:8080/mapping/userA 실행하면
경로 변수가 로그가 찍히는 것을 볼 수 있다.


PathVariable 사용 - 다중
/**
* PathVariable 사용 다중 */
 @GetMapping("/mapping/users/{userId}/orders/{orderId}")
 public String mappingPath(@PathVariable String userId, @PathVariable Long
 orderId) {
     log.info("mappingPath userId={}, orderId={}", userId, orderId);
return "ok";
}
http://localhost:8080/mapping/users/userA/orders/100을 실행하면
위와 같이 나온다.


특정 헤더 조건 매핑
/**
* 특정 헤더로 추가 매핑
* headers="mode",
* headers="!mode"
* headers="mode=debug"
* headers="mode!=debug" (! = ) */
 @GetMapping(value = "/mapping-header", headers = "mode=debug")
 public String mappingHeader() {
     log.info("mappingHeader");
return "ok";
}

헤더에 직접 key, value 를 넣어 테스트 할 수 있다.


미디어 타입 조건 매핑 - HTTP 요청 Content-Type, consume
/**
* Content-Type 헤더 기반 추가 매핑 Media Type * consumes="application/json"
* consumes="!application/json"
* consumes="application/*"
* consumes="*\/*"
* MediaType.APPLICATION_JSON_VALUE
*/
 @PostMapping(value = "/mapping-consume", consumes = "application/json")
 public String mappingConsumes() {
     log.info("mappingConsumes");
     return "ok";
 }




미디어 타입 조건 매핑 - HTTP 요청 Accept, produce
    /**
     * Accept 헤더 기반 Media Type * produces = "text/html"
     * produces = "!text/html"
     * produces = "text/*"
     * produces = "*\/*"
     */
    @PostMapping(value = "/mapping-produce", produces = "text/html")

    public String mappingProduces() {
        log.info("mappingProduces");
        return "ok";

    }

 

produces = "text/html"로 설정된 경우, 클라이언트가 Accept: text/html 또는 Accept: */*로 요청하면 서버는 text/html 타입의 응답을 반환한다.
왜냐하면 클라이언트가 Accept: */*로 요청하면, 이는 모든 타입의 응답을 허용한다는 의미한다. 따라서 서버는 produces 속성에 설정된 text/html 타입의 응답을 반환할 수 있다.

 

728x90