Model

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

 

@ModelAttribute 어노테이션은 스프링 MVC에서 모델 객체를 생성하거나 초기화하는 데 사용됩니다. 모델은 뷰에 데이터를 전달하기 위한 컨테이너로, 주로 HTML 템플릿과 함께 사용되지만, 비동기 응답에서도 데이터를 처리하는 데 사용될 수 있습니다.

@ModelAttribute는 크게 세 가지 경우에 사용됩니다:

  1. 컨트롤러 메서드의 파라미터에 사용: 요청과 함께 전달된 데이터를 모델 객체에 바인딩합니다.
  2. 메서드 레벨에서 사용: 모델을 초기화하거나 데이터를 추가하기 위한 메서드로, 주로 뷰에서 필요한 데이터를 미리 설정해둡니다.
  3. 리턴값을 모델 속성으로 추가: 메서드의 리턴값을 모델에 속성으로 추가할 수 있으며, 이를 통해 모델 데이터를 뷰에 전달할 수 있습니다.

@ModelAttribute의 주요 용도

  1. 메서드 파라미터에 사용: 요청에서 전달된 값을 바탕으로 모델 객체를 생성하고 이를 요청 바인딩과 함께 사용할 수 있습니다.
  2. 메서드 레벨에서 사용: 컨트롤러 메서드가 실행되기 전에 모델에 데이터를 추가합니다. 이는 공통적인 데이터(예: 메뉴, 사용자 정보 등)를 모든 뷰에 추가할 때 유용합니다.
  3. 리턴값을 모델 속성으로 추가: 메서드의 리값을 모델에 자동으로 추가할 수 있습니다. 이를 통해 모델 데이터를 뷰에 전달할 수 있습니다.

1. 메서드 파라미터에 @ModelAttribute 사용

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

@Controller
public class AccountController {

    @PostMapping("/accounts")
    public String handleAccount(@ModelAttribute Account account) {
        // 요청에서 전달된 데이터를 Account 객체로 바인딩
        System.out.println("Account Name: " + account.getName());
        return "accountView";
    }
}

코드 설명:

  • @ModelAttribute Account account: 요청에서 전달된 데이터를 Account 객체로 바인딩합니다. 예를 들어, 폼에서 전달된 값들이 Account 객체의 필드에 자동으로 매핑됩니다.
  • 모델 객체 사용: Account 객체는 요청 파라미터로부터 생성되며, 이를 통해 폼 데이터를 처리할 수 있습니다.

2. 메서드 레벨에 @ModelAttribute 사용

메서드 레벨에서 @ModelAttribute를 사용하면, 해당 컨트롤러의 모든 메서드에 공통적으로 모델 데이터를 추가할 수 있습니다.

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ControllerAdvice;

@ControllerAdvice
public class GlobalControllerAdvice {

    @ModelAttribute
    public void addGlobalAttributes(Model model) {
        // 모든 뷰에 추가될 공통 데이터
        model.addAttribute("globalMessage", "Welcome to our website!");
    }
}

코드 설명:

  • @ModelAttribute 메서드: 모든 요청에 대해 이 메서드가 실행되며, 모델에 데이터를 추가합니다. 여기서는 "globalMessage"라는 속성이 모든 뷰에 전달됩니다.
  • @ControllerAdvice: 이 클래스는 모든 컨트롤러에 적용되는 전역적인 모델 속성을 정의합니다.

3. 리턴값을 모델 속성으로 추가

@ModelAttribute를 메서드에 적용하여 메서드의 리턴값을 모델에 자동으로 추가할 수 있습니다. 이 방식은 리턴된 객체를 특정 이름으로 모델에 저장할 때 유용합니다.

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

@Controller
public class AccountController {

    @GetMapping("/accounts/{id}")
    @ModelAttribute("myAccount")  // 리턴되는 Account 객체를 "myAccount"라는 이름으로 모델에 저장
    public Account getAccount(@PathVariable String id) {
        Account account = new Account(id, "John Doe");
        return account;  // 리턴된 Account 객체가 모델에 저장됩니다.
    }
}

코드 설명:

  • @ModelAttribute("myAccount"): 이 메서드는 Account 객체를 리턴하며, 리턴된 객체는 "myAccount"라는 이름으로 모델에 저장됩니다.
  • Account 객체: 리된 Account 객체는 뷰에서 "myAccount"라는 이름으로 접근할 수 있습니다.

4. 프로그램적으로 모델 초기화

모델을 프로그래밍 방식으로 초기화할 수 있습니다. 이 방식은 컨트롤러에서 메서드가 실행되기 전에 공통 데이터를 모델에 추가하는 데 유용합니다.

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.stereotype.Controller;

@Controller
public class AccountController {

    @ModelAttribute
    public void populateModel(@RequestParam String number, Model model) {
        // 요청 파라미터로부터 데이터를 모델에 추가
        Account account = accountRepository.findAccount(number);
        model.addAttribute("account", account);
    }

    @GetMapping("/account")
    public String getAccountView() {
        return "accountView";  // 뷰에서 "account"라는 모델 속성에 접근 가능
    }
}

코드 설명:

  • @ModelAttribute 메서드: 이 메서드는 @RequestParam으로 전달된 number 값을 사용해 Account 객체를 조회한 후, 이를 모델에 추가합니다.
  • 모델 초기화: 이 메서드는 다른 컨트롤러 메서드가 실행되기 전에 호출되므로, 모든 뷰에 account 속성이 추가됩니다.

Reactive 스택에서의 @ModelAttribute 사용

Spring WebFlux 같은 Reactive 스택에서도 유사한 방식으로 모델 데이터를 초기화하거나 관리할 수 있습니다. Reactive 방식에서는 주로 비동기 데이터 흐름을 지원하는 객체를 모델에 바인딩합니다.

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

@Controller
public class ReactiveAccountController {

    @GetMapping("/accounts/{id}")
    @ModelAttribute("myAccount")
    public Mono<Account> getAccount(@PathVariable String id) {
        return findAccountById(id);  // 비동기적으로 Account 객체 리턴
    }

    private Mono<Account> findAccountById(String id) {
        // 가상의 비동기 데이터베이스 조회
        Account account = new Account(id, "John Doe");
        return Mono.just(account);
    }
}

코드 설명:

  • Reactive 방식: Mono<Account>는 비동기적으로 Account 객체를 리하며, 이는 myAccount라는 이름으로 모델에 저장됩니다.

요약

  • @ModelAttribute는 모델 객체를 생성하고, 이를 뷰에 전달하기 위해 사용됩니다.
  • 메서드 파라미터로 사용하면 요청 파라미터를 객체로 바인딩하고, 메서드 레벨에서 사용하면 모델을 초기화하거나 데이터를 미리 설정할 수 있습니다.
  • @ControllerAdvice를 사용하면 전역적으로 모델에 데이터를 추가할 수 있으며, 여러 컨트롤러에서 공통적으로 사용되는 데이터를 쉽게 관리할 수 있습니다.
  • Reactive 스택에서도 유사한 방식으로 모델을 초기화하거나 관리할 수 있으며, 비동기 데이터 흐름을 지원합니다.

이 방식은 모델 데이터를 효과적으로 관리하고, 뷰에서 필요한 데이터를 미리 설정할 수 있어 매우 유용합니다.


참고 : [https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-modelattrib-methods.html]

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

Validation  (0) 2024.10.09
@InitBinder  (0) 2024.10.09
Handler Method : Jackson JSON  (0) 2024.10.09
Handler Method : ResponseEntity  (1) 2024.10.09
Handler Method : @ResponseBody  (0) 2024.10.09