@ModelAttribute

코딩냥이·2024년 9월 10일

Annotation

목록 보기
30/34

@ModelAttribute

@ModelAttribute는 스프링 MVC에서 모델 데이터를 바인딩하고 처리하는 데 사용되는 어노테이션입니다. 이는 컨트롤러 메소드의 파라미터나 메소드 레벨에서 사용될 수 있습니다.

기능

  1. 요청 파라미터를 모델 객체에 바인딩합니다.
  2. 모델에 자동으로 속성을 추가합니다.
  3. 메소드 레벨에서 사용 시 여러 핸들러 메소드에서 공통으로 사용할 모델 속성을 정의할 수 있습니다.

사용 방법

기본적인 사용 방법은 다음과 같습니다:

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

@Controller
public class UserController {

    @PostMapping("/users")
    public String createUser(@ModelAttribute User user) {
        // user 객체는 이미 요청 파라미터로 채워진 상태
        userService.createUser(user);
        return "userCreated";
    }

    @ModelAttribute("countries")
    public List<String> getCountries() {
        return Arrays.asList("USA", "UK", "France", "Germany");
    }
}

주요 특징

  1. 자동 바인딩: HTTP 요청 파라미터를 모델 객체의 필드에 자동으로 바인딩합니다.
  2. 모델 속성 추가: 메소드 레벨에서 사용 시, 반환 값을 자동으로 모델에 추가합니다.
  3. 유연성: 폼 데이터 처리, 데이터 준비, 데이터 변환 등 다양한 상황에서 활용 가능합니다.
  4. 이름 지정: 모델 속성의 이름을 명시적으로 지정할 수 있습니다.

고급 사용법

1. 명시적 이름 지정

@PostMapping("/users")
public String createUser(@ModelAttribute("newUser") User user) {
    // 모델에 'newUser'라는 이름으로 추가됨
    return "userCreated";
}

2. 메소드 레벨에서 사용

@ModelAttribute("globalAttr")
public String globalAttribute() {
    return "This is a global attribute";
}

3. 다중 @ModelAttribute 메소드

@ModelAttribute
public void populateModel(@RequestParam String username, Model model) {
    model.addAttribute("username", username);
    model.addAttribute("userType", determineUserType(username));
}

4. 중첩 객체 처리

public class User {
    private String name;
    private Address address;
    // getters and setters
}

@PostMapping("/users")
public String createUser(@ModelAttribute User user) {
    // 중첩된 address 객체도 자동으로 바인딩됨
    return "userCreated";
}

@ModelAttribute@RequestBody의 차이

  • @ModelAttribute: 주로 폼 제출 처리에 사용되며, 개별 필드를 바인딩합니다.
  • @RequestBody: JSON/XML 등의 요청 본문을 객체로 변환할 때 사용됩니다.

유효성 검사

@ModelAttribute@Valid를 함께 사용하여 모델 객체의 유효성을 검사할 수 있습니다:

@PostMapping("/users")
public String createUser(@Valid @ModelAttribute User user, BindingResult result) {
    if (result.hasErrors()) {
        return "userForm";
    }
    userService.createUser(user);
    return "userCreated";
}

테스트

@ModelAttribute가 적용된 컨트롤러를 테스트할 때:

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void testCreateUser() throws Exception {
        mockMvc.perform(post("/users")
                .param("name", "John Doe")
                .param("email", "john@example.com"))
                .andExpect(status().isOk())
                .andExpect(model().attributeExists("newUser"));
    }
}

주의사항

  1. 오버바인딩: 모든 요청 파라미터를 무분별하게 바인딩하면 보안 문제가 발생할 수 있습니다.
  2. 성능: 대량의 데이터나 복잡한 객체 그래프를 바인딩할 때 성능에 영향을 줄 수 있습니다.
  3. 타입 불일치: 요청 파라미터의 타입과 모델 객체의 필드 타입이 일치하지 않으면 바인딩 오류가 발생할 수 있습니다.

베스트 프랙티스

  1. 필요한 필드만 바인딩: @InitBinder를 사용하여 허용할 필드를 명시적으로 지정하세요.
  2. 데이터 검증: @Valid와 함께 사용하여 입력 데이터의 유효성을 검사하세요.
  3. 명확한 이름 사용: 모델 속성에 명확하고 의미 있는 이름을 사용하세요.
  4. 공통 데이터 처리: 여러 뷰에서 공통으로 사용되는 데이터는 메소드 레벨 @ModelAttribute로 처리하세요.
  5. 타입 안전성: 가능한 한 타입 안전한 방식으로 데이터를 처리하세요.

결론

@ModelAttribute는 스프링 MVC에서 모델 데이터를 효과적으로 처리할 수 있게 해주는 강력한 도구입니다. 이를 통해 HTTP 요청 데이터를 자바 객체로 쉽게 변환하고, 공통 데이터를 여러 뷰에 제공할 수 있습니다. 폼 처리, 데이터 준비, 모델 채우기 등 다양한 시나리오에서 유용하게 사용될 수 있습니다. 다만, 보안과 성능 측면에서 주의가 필요하며, 적절한 검증과 함께 사용해야 합니다.

연관 포스팅

@RequestBody
@Valid
@InitBinder
@Controller
@RequestParam

profile
HelloMeow~!

0개의 댓글