Spring 08 - Spring Annotations Part 2


Spring Annotations

Spring Annotations Part 1에 이어 나머지 주요 스프링 어노테이션들을 본다.

@RestController

RESTful 웹 서비스의 Controller를 지정하는 어노테이션이다. @Controller와 다른 점은 @Controller는 내부 메서드가 반환하는 것이 View 이름이라면, @RestController는 내부 메서드가 반환하는 것이 JSON 또는 XML의 형식을 가진 데이터를 반환하는 것이다. = “이 클래스는 RESTful 컨트롤러 입니다.”

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }
}

@RestController을 자세히 까보면 내부에 @Controller와 @ResponseBody가 선언되어 있다. 이는 @RestController가 @Controller를 하는 역할과 동시에 추후 설명할 @ResponseBody 역할(HTTP 요청의 본문(body)에 담긴 데이터를 자바 객체로 변환하여 메서드 파라미터로 전달하는 역할)을 맡는다고 할 수 있다.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

@RequestMapping

HTTP 요청을 특정 컨트롤러 클래스나 메서드와 매핑하기 위한 역할을 하는 어노테이션이다. 즉, 특정 URL 요청이 들어올 때 이와 매핑된 클래스 또는 메서드가 이 요청을 처리하는 담당이 된다.
= “위 URL에 대한 요청 처리를 맡아주시오!”

@RequestMapping(value = "/users", method = RequestMethod.GET)
public List<User> getAllUsers() {
    // GET 요청만 처리
    return userService.findAll();
}

@RequestMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
    // @PathVariable로 매개변수를 받아 id에 대한 동적 경로 처리
    return userService.findById(id);
}

@RequestMapping(value = "/users", params = "active=true")
public List<User> getActiveUsers() {
    // 특정 요청 파라미터가 있는 경우에만 처리
    return userService.findActiveUsers();
}

@RequestMapping(value = "/users", headers = "content-type=application/json")
public List<User> getUsersWithJsonHeader() {
    // 특정 HTTP 헤더가 포함된 요청에 경우에만 처리
    return userService.findAll();
}

스프링 4.3 이후 버전에서는 @RequestMapping을 더 세분화한 어노테이션들이 도입이 되었고 이는 아래와 같다.

  • @GetMapping: GET 요청을 처리
  • @PostMapping: POST 요청을 처리
  • @PutMapping: PUT 요청을 처리
  • @DeleteMapping: DELETE 요청을 처리
  • @PatchMapping: PATCH 요청을 처리

이들을 활용하여 아래 코드와 같이 @RequestMapping을 클래스 수준에서 사용하여 기본적인 URL 패턴을 설정하고, 내부 메서드에서 세분화된 어노테이션을 사용하여 처리하는 방법이 있다.

@Controller
@RequestMapping("/boards")
public class BoardController {

    private final BoardService boardService;

    public BoardController(BoardService boardService) {
        this.boardService = boardService;
    }

    @GetMapping
    public String list(Model model) {
        //경로가 없는 경우 상위 클래스의 URL의 GET 요청으로 인식된다. 
        //여기선 "/boards"로 GET요청이 들어오면 처리한다.
        List<Board> boards = boardService.findAll();
        model.addAttribute("boards", boards);
        return "board/list";
    }

    @GetMapping("/new")
    public String createForm(Model model) {
        model.addAttribute("board", new Board());
        return "board/create";
    }

    @PostMapping
    public String create(Board board) {
        //경로가 없는 경우 상위 클래스의 URL의 POST 요청으로 인식된다. 
        //여기선 "/boards"로 POST요청이 들어오면 처리한다.
        boardService.save(board);
        return "redirect:/boards";
    }

    @GetMapping("/{id}")
    public String detail(@PathVariable Long id, Model model) {
        Board board = boardService.findById(id);
        model.addAttribute("board", board);
        return "board/detail";
    }

    @GetMapping("/{id}/edit")
    public String editForm(@PathVariable Long id, Model model) {
        Board board = boardService.findById(id);
        model.addAttribute("board", board);
        return "board/edit";
    }

    @PostMapping("/{id}")
    public String update(@PathVariable Long id, Board board) {
        board.setId(id);
        boardService.update(board);
        return "redirect:/boards/" + id;
    }

    @DeleteMapping("/{id}")
    public String delete(@PathVariable Long id) {
        boardService.deleteById(id);
        return "redirect:/boards";
    }

}

@GetMapping

특정 경로의 HTTP GET 요청을 처리하는 메서드에 사용되는 어노테이션이다. GET 요청은 주로 서버에서 데이터를 조회할 때 사용되는 요청이다.
= “이 메서드는 경로에 해당하는 GET요청을 처리하세요.”

@@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
    return userService.findById(id);
}

@PostMapping

특정 경로의 HTTP POST 요청을 처리하는 메서드에 사용되는 어노테이션이다. POST 요청은 주로 서버로 데이터를 전송하여 새로 생성할 때 사용되는 요청이다.
= “이 메서드는 경로에 해당하는 POST요청을 처리하세요.”

@PostMapping("/users")
public User createUser(@RequestBody User user) {
    return userService.save(user);
}

@PutMapping

특정 경로의 HTTP PUT 요청을 처리하는 메서드에 사용되는 어노테이션이다. PUT 요청은 주로 서버에 데이터를 전송하여 전체 수정할 때 사용되는 요청이다. = “이 메서드는 경로에 해당하는 PUT요청을 처리하세요.”

@PutMapping("/users/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
    return userService.update(id, user);
}

@DeleteMapping

특정 경로의 HTTP DELETE 요청을 처리하는 메서드에 사용되는 어노테이션이다. DELETE 요청은 주로 서버에서 데이터를 삭제할 때 사용되는 요청이다. = “이 메서드는 경로에 해당하는 DELETE요청을 처리하세요.”

@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
    userService.deleteById(id);
}

@PatchMapping

특정 경로의 HTTP PATCH 요청을 처리하는 메서드에 사용되는 어노테이션이다. PATCH 요청은 주로 서버에 데이터를 전송하여 전체가 아닌 일부만 수정할 때 사용되는 요청이다. = “이 메서드는 경로에 해당하는 PATCH요청을 처리하세요.”

@PatchMapping("/users/{id}")
public User updatePartialUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
    return userService.updatePartial(id, updates);
}

@RequestParam

HTTP 요청에서 쿼리 파라미터, 폼 데이터, 또는 URL 매개변수를 메서드 파라미터에 바인딩하는 데 사용하는 어노테이션. 주로 GET 요청에서 URL에 포함된 파라미터를 가져오거나, POST 요청에서 폼 데이터를 처리할 때 사용
= “URL 파라미터에 대응하는 매개변수”

@GetMapping("/search")
public String search(@RequestParam String keyword, @RequestParam(defaultValue = "1") int page) {
    // /search?keyword=spring&page=2에서 ?이후로 넘어온 파라미터들 처리
    return "Searching for: " + keyword + " on page " + page;
}

@RequestBody

HTTP 요청의 본문(body)에 있는 데이터를 자바 객체로 변환해 메서드 파라미터로 전달하는 데 사용하는 어노테이션. 주로 POST, PUT과 같은 요청에서 JSON 또는 XML 데이터를 서버로 전송할 때 사용
= “요청 바디에 대응하는 매개변수”

@PostMapping("/users")
public User createUser(@RequestBody User user) {
    // user 등록 후 /users로 Post요청하는 바디에 있는 등록한 JSON 데이터를 User 객체로 변환
    return userService.save(user);
}

@PathVariable

URL 경로의 일부를 메서드 파라미터로 받아올 때 사용 사용하는 어노테이션. 동적인 URL 경로에서 변수를 추출하여 해당 값을 메서드에 매핑하는 데 사용
= “URL에 일부 동적 부분에 대응하는 매개변수”

@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
    // /users/{id}의 {id}를 받아와 Long형 id로 사용 
    return userService.findById(id);
}

@ResponseBody

메서드가 반환하는 값을 HTTP 응답의 본문으로 직접 반환하도록 지정하는 어노테이션. 주로 RESTful API에서 사용되며, 반환되는 데이터는 JSON이나 XML 형식으로 변환됨.
= “요청이 들어오면 반환하는 객체를 JSON형식으로 보내기”

@GetMapping("/users/{id}")
@ResponseBody
public User getUser(@PathVariable Long id) {
    // /users/{id} GET 요청으로 들어올 때 User객체를 JSON형식으로 반환
    return userService.findById(id);
}

@ResponseStatus

메서드나 예외 클래스에 적용하여, HTTP 응답의 상태 코드를 설정하는 데 사용하는 어노테이션. 기본적으로 스프링은 200(OK) 상태 코드를 반환하지만, 이 어노테이션을 사용해 404(Not Found) 또는 201(Created) 같은 상태 코드를 반환할 수 있고, 특정 예외에 대한 상태 코드도 설정할 수 있다.
= “요청이 들어오면 반환하는 객체를 JSON형식으로 보내기”

@PostMapping("/users")
@ResponseStatus(HttpStatus.CREATED)
public User createUser(@RequestBody User user) {
    // 서버의 응답코드는 201(HttpStatus.CREATED)로 보내기
    return userService.save(user);
}

@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
    // UserNotFoundException이 발생하면, 서버의 응답코드는 404(Not Found)를 반환
    public UserNotFoundException(String message) {
        super(message);
    }
}