카카오 테크 캠퍼스 6주차

boseung·2023년 5월 25일
0

Annotation

어노테이션에 대해 배워서 기본적인 스프링의 어노테이션에 대해 정리해보려고 한다.

@RestController

@Controller의 경우 반환 값이 String이면 뷰 이름으로 인식한다. 그래서 뷰를 찾고 뷰가 랜더링된다.

반면에 @RestContoller의 반환 값으로 뷰를 찾는게 아니라 Http 메시지 바디에 바로 입력한다.

@RestController
public class MappingController{
    @RequestMapping("/mapping")
    public String mappingMethod(){
        return "ok"; // Http 메시지 바디에 입력
    }
}

@RequestMapping

@RequestMapping은 URL 매핑에 사용되는 어노테이션이다.

method 속성에 Http 메서드를 지정하지 않으면 GET, POST, PUT 등 모든 Http 메서드가 허용된다.(좋은 설계는 아님)

@RequestMapping("/mapping") // 모든 Http 메서드 허용
    public String mappingMethod(){
        return "ok"; 
    }
@RequestMapping(value = "/mapping2", method = RequestMethod.GET) // GET 메서드만 허용
    public String mappingMethod(){
        return "ok";
    }

REST API 설계를 위해서 스프링에서 다음과 같은 Http 메서드 매핑을 지원하고 있다.

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

사실 Http 메서드 어노테이션을 뜯어보면 다음과 같다.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET) // 쨘
public @interface GetMapping {
...
}

@GetMapping에서 @RequestMapping(method = RequestMethod.GET)을 찾아볼 수 있다!

@PathVariable

@RequestMapping은 URL 경로를 템플릿화할 수 있는데, @PathVariable을 함께 사용하면 매칭되는 부분을 편리하게 조회할 수 있다.

만약 http://localhost:8080/mapping/users/userA/orders/10 이라면

@GetMapping("/mapping/users/{userId}/orders/{orderId}")에서 userId: users, orderId: 10에 매핑된다.

여기에 @PathVariable을 사용하면 변수에 매핑해서 사용할 수 있다.

@GetMapping("/mapping/users/{userId}/orders/{orderId}")
//public String mappingPath(@PathVariable("userId") String userId, @PathVariable("orderId") Long orderId)
// 변수명 같으면 생략가능
public String mappingPath(@PathVariable String userId, @PathVariable Long orderId) {
 log.info("mappingPath userId={}, orderId={}", userId, orderId);
 return "ok";
}

@RequestParam

HTML 테스트용 Form은 다음과 같다.

<form action="/request-param" method="post">
		 username: <input type="text" name="username" />
		 age: <input type="text" name="age" />
		 <button type="submit">전송</button>
 </form>

위의 HTML Form으로 http://localhost:8080/request-param?username=value1&age=value2 URL를 얻을 수 있다.

파라미터의 값을 @RequestParam을 통해 변수에 매핑시킬 수 있다.

여기서도 변수명이랑 같으면 생략 가능하다.

@ResponseBody //@ResponseBody에 return 값을 바로 적어준다.(@RestController와 비슷)
@RequestMapping("/request-param")
public String requestParamV2(
// @RequestParam("username") String username,
// @RequestParam("age") int age) {
// 생략 가능
@RequestParam String username,
@RequestParam("age") int age) {
 log.info("username={}, age={}", username, age);
 return "ok";
}

여기서 @RequestParam도 생략할 수 있는데, 가독성을 위해서 남겨두는 것도 좋다.

@RequestParam은 required 속성은 기본값이 true이다.

만약 required 속성을 false로 준다면 기본형(primitive)에 null이 입력될 수 있기 때문에 주의해야한다.

이런 경우를 방지하기 위해서 Integer 같은 Wrapper 클래스를 사용하거나 defaultValue 속성을 제공해야한다.

@ResponseBody
@RequestMapping("/request-param-default")
public String requestParamDefault(
 @RequestParam(required = true, defaultValue = "guest") String username,
 @RequestParam(required = false, defaultValue = "-1") int age) {
 log.info("username={}, age={}", username, age);
 return "ok";
}

defaultValue 속성을 주면 required 속성은 의미가 없어지기 때문에 빼도 관계 없다.

파라미터를 Map, MultiValueMap으로 조회할 수도 있

@ResponseBody
@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String, Object> paramMap) {
 log.info("username={}, age={}", paramMap.get("username"),
paramMap.get("age"));
 return "ok";
}

파라미터의 값이 확실하면 Map을 사용해도 되지만, 그렇지 않다면 MultiValueMap을 사용하면 된다.

@ModelAttribute

보통 Controller에서 파라미터로 받은 값을 객체를 생성한 후 그 객체에 값을 넣어주어 데이터를 다루게 된다.

예를 들어

@Data // Getter, Setter.. 생성해주는 Lombok 라이브러리
public class HelloData {
 private String username;
 private int age;
}

이렇게 파라미터의 값을 보관할 객체를 위한 클래스를 만들어주고


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

	log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
 return "ok";
}

이렇게 객체를 생성하고 그 객체에 파라미터의 값을 보관한 후 사용한다.

하지만 @ModelAttribute를 사용하면 이런 객체를 생성하고 set 메서드로 값을 저장하는 흐름을 자동으로 해준다.

*/
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
 log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
 return "ok";
}

@ModelAttribute도 아예 생략 가능한데, 이렇게 하면 @requestParam과 헷갈릴 수 있다.

스프링의 경우 String이나 int, Integer 같은 단순한 타입은 @requestParam이 적용되고, 직접 만든 객체 타입의 경우 @ModelAttribute이 적용된다.

profile
Dev Log

0개의 댓글

관련 채용 정보