Spring MVC 기본 기능

김두현·2023년 8월 3일
2

Spring

목록 보기
12/13
post-thumbnail

❕@Controller

컨트롤러 클래스를 지정함으로써, 요청과 관련된 메서드를 처리할 수 있게된다.

메서드의 반환 값이 String일 경우, view 이름으로 인식하여 view가 렌더링 된다.

@Controller
public class MappingController {

    @RequestMapping("/hello-basic")
    public String helloBasic() {
        //hello-basic 이라는 이름의 view를 찾아 반환한다.
        return "hello-basic";
    }

❕@RestController

@Controller와 같은 기능을 제공한다. 다만, 차이점이 존재한다.

반환 값이 String일 경우, view를 찾는 것이 아닌 HTTP message body에 바로 입력된다.

@RestController
public class MappingController {

    @RequestMapping("/hello-basic")
    public String helloBasic() {
        return "ok";
    }
  • 실행 결과

❕@RequestMapping

특정 URL로 요청이 들어왔을 때, 처리할 메서드를 지정한다.

@RequestMapping은 두 가지 방식으로 지정할 수 있다.

  • Class 수준에서의 적용
    • 해당 Class에 속한 모든 메서드에 대한 URL 경로를 지정한다.
@RestController
@RequestMapping("/mapping/users")
public class MappingClassController
  • Method 수준에서의 적용
    • 해당 메서드에 대한 URL 경로를 지정한다.
@RequestMapping("/hello-basic")
public String helloBasic() {
    return "ok";
}

기본적으로 @RequestMapping모든 HTTP 메서드가 허용된다.
(GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE)

@RequestMapping(value = "/users", method = RequestMethod.GET)
위와 같이 method 속성을 통해 특정 HTTP 메서드를 지정할 수 있으나,
Spring은 아래와 같은 축약 annotation을 지원한다.

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

이들 또한 @RequestMapping과 동일한 방식으로 URL 경로를 지정하여 사용한다.


❕@PathVariable

만일 localhost:8080/users/{userId} localhost:8080/orders/{orderId}
와 같이 URL 경로에 변수를 사용하고 싶다면 어떻게 해야할까?

@PathVariable을 통해 URL의 일부를 메서드의 파라미터로 전달한다.
즉, URL 경로에 있는 변수 값을 메서드에서 활용할 수 있다.

@GetMapping("/{userId}")
public String findUser(@PathVariable("userId") String userId) {
    return "get userId = " + userId;
}

이때, @PathVariable의 이름과 parameter의 이름이 같으면 생략 가능하다.

@GetMapping("/{userId}")
public String findUser(String userId) {
    return "get userId = " + userId;
}

❕서버로 데이터를 전달하는 방식

클라이언트에서 서버로 데이터를 전달하는 방식은 주로 다음 3가지 방법을 사용한다.

  • GET 쿼리 파라미터 형식
    • URL에 데이터를 포함하여 전달
    • 검색, 필터링, 페이징 등에서 주로 사용한다.
/url?username=kdh&age=8
  • POST HTML form 형식
    • HTTP message body에 쿼리 파라미터 형식으로 담아서 전달
    • 회원 가입, 주문 등 민감한 정보를 다룰 때 주로 사용한다.
POST /html-form ...
Content-Type : application/x-www-form-urlencoded

username=kdh&age=8
  • HTTP message body에 데이터를 직접 담는 형식
    • 주로 HTTP API에서 사용하여, JSON 형식을 사용하다.
POST /body-json ...
Content-Type : application/json

{
	"username" : "kdh",
    "age" : "20"
}

GET 쿼리 파라미터POST HTML form은 데이터의 형식이 같으므로, 구분없이 조회할 수 있다.
이를 요청 파라미터(request param) 조회라고 한다.

요청 파라미터 조회 방식은 상황에 따라
@RequestParam @ModelAttribute 중 하나를 사용한다.

HTTP message body를 통해 데이터가 직접 넘어오는 경우요청 메시지라고 한다.

요청 메시지 조회 방식은 @RequestBody를 사용한다.

세 가지 annotation을 하나씩 알아보자.


❕@RequestParam

단일 요청 파라미터의 값을 메서드의 변수에 바인딩 할 때 사용한다.

이때 기본 타입은 int Long String LocalDateTime List<> 등을 포함한다.

@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(@RequestParam("username") String username, 
                             @RequestParam("age") Integer age) {
    log.info("username={}, age={}", username, age);

    return "ok";
}

이때, 파라미터의 이름과 메서드 변수의 이름이 동일하면,
아래와 같이 파라미터의 이름은 생략 가능하다.

@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(@RequestParam String username, 
                             @RequestParam Integer age) {
    log.info("username={}, age={}", username, age);

    return "ok";
}

이때, 변수의 type이 int Long String LocalDateTime List<> 등의
기본 타입인 경우 @RequestParam 또한 생략 가능하다.
다만, 명료성이 떨어지는 이유로 추천하지 않는 방법이다.


❕@ModelAttribute

우리는 개발을 할 때, 요청 파라미터의 값을 어떠한 객체에 바인딩 해야한다.
앞선 @RequestParam을 통해 다음과 같이 작성할 수 있다.

@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@RequestParam String username, 
                               @RequestParam Integer age) {
    HelloData data = new HelloData();
    data.setUsername(username);
    data.setAge(age);

    return "ok";
}

그러나, 이 과정을 완전히 자동화해주는 괴물이 있다.

@ModelAttribute객체를 생성하고, 요청 파라미터 값을 객체의 필드에 바인딩할 때 사용한다.

@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV1(@ModelAttribute HelloData data) {
    log.info("data={}", data);

    return "ok";
}

이때, 변수의 type이 기본 타입이나 argument resolver로 지정해둔 타입이 아닌 경우, @ModelAttribute또한 생략 가능하다.
그러나 @RequestParam과 같은 이유로 추천하지 않는다.


❕@RequestBody

HTTP message body를 직접 조회하여 객체를 생성하고, 요청 메시지를 객체의 필드에 바인딩할 때 사용한다.

@ResponseBody
@PostMapping("request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData data) {
    log.info("username={}, age={}", data.getUsername(), data.getAge());

    return data;
}

앞서 살펴본 @ModelAttribute와 다루는 데이터의 형식이 다를 뿐,
매우 유사하게 동작한다는 것을 알 수 있다.


❕@ResponseBody

앞선 예시 코드에서 계속 등장한 @ResponseBody의 역할은 무엇일까?

해당 메서드의 반환값을 HTTP message body에 넣는다.

위에서 살펴본 @RestController가 클래스 수준에서 사용되었다면,
@ResponseBody는 메서드 수준에 적용된다는 차이를 지닌다.

참고 자료

https://www.inflearn.com/course/스프링-mvc-1


💕오류 지적 및 피드백은 언제든 환영입니다. 복제시 출처 남겨주세요!💕
💕좋아요와 댓글은 큰 힘이 됩니다.💕
profile
I AM WHO I AM

1개의 댓글

comment-user-thumbnail
2023년 9월 2일

우와아

답글 달기