Annotated Controllers[3] - @ModelAttribute

2024. 10. 9. 12:12Spring Framework/Web on Servlet Stack

https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.html


@ModelAttribute 어노테이션은 HTTP 요청의 파라미터를 객체에 바인딩하는 데 사용되는 스프링 MVC의 기능입니다. 이를 통해 클라이언트가 전송한 폼 데이터나 쿼리 스트링 파라미터를 자동으로 객체에 매핑할 수 있습니다. 또한, 이 객체는 뷰에서 사용될 모델에 추가될 수 있습니다. 스프링은 여러 방식으로 @ModelAttribute에 해당하는 객체를 생성하고 바인딩할 수 있으며, 유효성 검사 및 데이터 바인딩 과정에서의 오류 처리도 가능합니다.

기본 개념

@ModelAttribute는 주로 컨트롤러 메서드의 아규먼트로 사용되어, 요청 파라미터를 자동으로 특정 객체에 바인딩합니다.

예시 상황:

클라이언트가 아래와 같은 HTTP 요청을 통해 데이터를 전송했다고 가정합니다.

POST /owners/1/pets/2/edit
Content-Type: application/x-www-form-urlencoded

name=Max&age=5&species=dog

이 요청에서 name, age, species와 같은 파라미터를 Pet 객체로 매핑하고 싶다면, @ModelAttribute를 사용하여 이를 자동으로 처리할 수 있습니다.

예시 코드 (Java)

import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.stereotype.Controller;

@Controller
public class PetController {

    @PostMapping("/owners/{ownerId}/pets/{petId}/edit")
    public String processSubmit(@ModelAttribute Pet pet) {
        System.out.println("Pet Name: " + pet.getName());
        System.out.println("Pet Age: " + pet.getAge());
        System.out.println("Pet Species: " + pet.getSpecies());
        return "petDetails";
    }
}

코드 설명:

  • @ModelAttribute Pet pet: Pet 객체에 클라이언트로부터 전달된 요청 파라미터를 바인딩합니다. name, age, species 파라미터는 Pet 객체의 필드로 자동으로 매핑됩니다.
  • 메서드 아규먼트Pet 객체가 선언되었기 때문에, 스프링은 이를 자동으로 바인딩하고, 그 결과로 생성된 Pet 객체를 메서드 내에서 사용할 수 있습니다.

객체 생성 방식

  1. 기본 생성자: @ModelAttribute로 지정된 객체는 기본적으로 해당 클래스의 기본 생성자를 통해 생성됩니다.
  2. 요청 파라미터 매핑: 생성된 객체의 필드에 요청 파라미터가 자동으로 매핑됩니다. 이 과정에서 스프링은 파라미터 이름과 객체의 필드 이름을 일치시키려고 합니다.
  3. 컨버터 사용: 만약 요청 파라미터가 객체로 변환되기 위해서 특별한 변환이 필요하다면, Converter<String, T>를 구현하여 변환 과정을 추가할 수 있습니다.

예시 (경로 변수와의 매핑)

@PutMapping("/accounts/{account}")
public String save(@ModelAttribute("account") Account account) { 
    //...
}

이 예시에서 account 경로 변수가 Account 객체로 바인딩됩니다. 스프링은 요청에서 account라는 경로 변수를 찾아, 그것을 Account 객체로 변환합니다. 이 과정에서 Converter<String, Account>가 필요할 수 있으며, 이를 통해 데이터베이스에서 Account 객체를 가져오거나 적절한 변환을 수행할 수 있습니다.

유효성 검사 및 바인딩 오류 처리

@ModelAttribute는 데이터를 바인딩하는 과정에서 발생하는 오류를 처리할 수 있습니다. 이를 위해 BindingResult아규먼트로 추가할 수 있습니다. 유효성 검사를 자동으로 적용하고 싶다면 @Valid 또는 @Validated 어노테이션을 추가할 수 있습니다.

예시 코드 (유효성 검사 및 오류 처리)

import org.springframework.validation.BindingResult;
import jakarta.validation.Valid;

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) {
    if (result.hasErrors()) {
        return "petForm";
    }
    // 데이터 처리 로직...
    return "petDetails";
}

코드 설명:

  • @Valid: Pet 객체의 필드에 대해 유효성 검사를 수행합니다. 이 검사는 Pet 클래스의 필드에 정의된 제약 조건(예: @NotNull, @Size)을 바탕으로 이루어집니다.
  • BindingResult: 유효성 검사 결과나 데이터 바인딩 과정에서의 오류를 저장합니다. 오류가 있을 경우 이를 처리할 수 있습니다.

데이터 바인딩 없이 모델에 값 추가

@ModelAttribute는 데이터 바인딩 없이도 단순히 모델에 객체를 추가할 수 있습니다. 예를 들어, binding=false 옵션을 사용하면 바인딩을 하지 않고 객체를 모델에 추가할 수 있습니다.

예시 코드 (바인딩 없이 모델에 추가)

@ModelAttribute
public AccountForm setUpForm() {
    return new AccountForm();
}

@PostMapping("/update")
public String update(@ModelAttribute(binding=false) Account account, AccountForm form) {
    // 여기서 Account는 바인딩되지 않음
    return "accountDetails";
}

Reactive 스택에서의 사용 (Spring WebFlux)

Spring WebFlux에서도 유사하게 @ModelAttribute와 같은 방식으로 요청 파라미터를 객체에 바인딩할 수 있습니다. 다만, WebFlux는 비동기 처리를 지원하기 때문에 Mono 또는 Flux로 데이터를 처리하게 됩니다.

Reactive 예시 코드

import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.stereotype.Controller;
import reactor.core.publisher.Mono;

@Controller
public class ReactivePetController {

    @PostMapping("/reactive-pets/edit")
    public Mono<String> processSubmit(@ModelAttribute Pet pet) {
        return Mono.just("Processed pet: " + pet.getName());
    }
}

코드 설명:

  • Mono<String>을 통해 비동기 방식으로 결과를 반환합니다.
  • @ModelAttribute는 Spring WebFlux에서도 기존 MVC 방식과 동일하게 요청 파라미터를 객체에 바인딩합니다.

요약

  • @ModelAttribute는 요청 파라미터를 객체에 자동으로 바인딩하는 어노테이션입니다.
  • 유효성 검사, 오류 처리, 모델에 객체 추가 등의 다양한 기능을 제공합니다.
  • WebFlux에서도 유사한 방식으로 사용 가능하며, 비동기 처리를 지원합니다.

'Spring Framework > Web on Servlet Stack' 카테고리의 다른 글

Handler Method : @SessionAttribute  (0) 2024.10.09
Handler Method : @SessionAttributes  (6) 2024.10.09
Annotated Controllers[3] - @CookieValue  (0) 2024.10.09
@RequestHeader  (0) 2024.10.09
Annotated Controllers[1]  (1) 2024.10.06