티스토리 뷰
728x90
반응형
Spring MVC에서 HTTP 요청의 데이터를 객체로 바인딩할 때 사용하는 어노테이션입니다.
- 주로 폼 데이터를 DTO(또는 VO) 객체로 매핑할 때 사용됩니다.
- 컨트롤러 메서드의 매개변수나 모델에 추가할 객체에 적용할 수 있습니다.
- HTTP 요청의 parameter(쿼리 스트링, 폼 데이터)를 자동으로 객체에 바인딩함.
- GET/POST 요청 모두 지원.
- 내부적으로 setName(), setAge() 같은 setter 메서드를 사용하여 값을 할당함.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class UserController {
@PostMapping("/user")
public String submitForm(@ModelAttribute UserForm userForm) {
System.out.println("이름: " + userForm.getName());
System.out.println("나이: " + userForm.getAge());
return "success"; // 성공 페이지 반환
}
}
@ModelAttribute 생략 가능
@PostMapping("/user")
public String submitForm(UserForm userForm) { // 생략 가능
return "success";
}
기본값 설정하기
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UserForm {
private String name = "기본 이름";
private int age = 20;
}
@ModelAttribute로 일부 필드만 바인딩 제외
특정 필드를 바인딩에서 제외하려면 @JsonIgnore 또는 @Transient를 사용
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UserForm {
private String name;
private int age;
@JsonIgnore // 이 필드는 요청 데이터에서 매핑되지 않음
private String hiddenField;
}
@ModelAttribute로 바인딩하는 객체에 데이터를 매핑하는 방식
Setter 방식 (기본 동작)
Spring은 기본적으로 기본 생성자로 객체를 만든 후, setter 메서드를 사용하여 필드 값을 설정합니다.
@Getter
@Setter
public class UserForm {
private String name;
private int age;
}
생성자 바인딩 (@AllArgsConstructor)
@AllArgsConstructor를 사용하면 모든 필드를 포함하는 생성자로 바인딩할 수 있습니다.
@AllArgsConstructor와 함께 필드를 final로 선언하면 setter 없이도 값이 주입됩니다.
@Getter
@AllArgsConstructor
public class UserForm {
private final String name;
private final int age;
}
Record 사용 (Java 14+)
record는 불변 객체이며, Spring이 자동으로 생성자를 사용하여 값을 주입합니다.
public record UserForm(String name, int age) {}
@AllArgsConstructor나 record를 사용할 때는 모든 필드가 필수값으로 요청
데이터 바인딩 방식이 생성자를 통해 값을 주입할 때, 모든 매개변수가 필요하기 때문입니다.
@AllArgsConstructor 사용 시 기본값 설정
기본값 설정
@Getter
public class UserForm {
private final String name;
private final int age;
public UserForm(String name, Integer age) {
this.name = name;
this.age = (age != null) ? age : 20; // 기본값 20 설정
}
}
Optional 활용
public UserForm(String name, Optional<Integer> age) {
this.name = name;
this.age = age.orElse(20);
}
record 사용 시 기본값 설정
기본값이 있는 보조 생성자 사용
nullable 필드는 Integer 타입으로 변경
record는 불변 객체이므로, Optional<Integer> age 같은 방식은 사용 불가
public record UserForm(String name, Integer age) {
public UserForm(String name, Integer age) {
this.name = name;
this.age = (age != null) ? age : 20;
}
}
바인딩 객체 검증
@Valid를 사용한 DTO 객체 검증
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
@Getter
@Setter
public class UserForm {
@NotBlank(message = "이름은 필수 입력 값입니다.")
private String name;
@Min(value = 18, message = "나이는 18세 이상이어야 합니다.")
private int age;
}
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class UserController {
@PostMapping("/user")
public String submitForm(@Valid @ModelAttribute UserForm userForm, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "userForm"; // 에러 발생 시 다시 폼 페이지로 이동
}
System.out.println("이름: " + userForm.getName());
System.out.println("나이: " + userForm.getAge());
return "success"; // 성공 페이지 반환
}
}
@Valid를 사용한 record객체 검증
public record UserForm(
@NotBlank(message = "이름은 필수 입력 값입니다.") String name,
@Max(value = 40, message = "나이는 40세 이하이어야 합니다.") Integer age
) {
public UserForm(String name, Integer age) {
this.name = name;
this.age = (age != null) ? age : 20; // 기본값 20 설정
}
}
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class UserApiController {
@PostMapping("/user")
public ResponseEntity<?> submitForm(@Valid @RequestBody UserForm userForm, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
Map<String, String> errors = new HashMap<>();
for (FieldError error : bindingResult.getFieldErrors()) {
errors.put(error.getField(), error.getDefaultMessage());
}
return ResponseEntity.badRequest().body(errors);
}
return ResponseEntity.ok("User created successfully");
}
}
728x90
반응형
'Spring' 카테고리의 다른 글
[Spring Boot] OpenFeign 쿼리스트링 객체 매핑 (0) | 2025.02.24 |
---|---|
[Spring Boot] Spring Boot 2.7 이후 MustacheEnvironmentCollector deprecated (0) | 2024.03.11 |
[Spring] Swagger Fail to load remote configuration 접속 불가 (0) | 2024.02.19 |
[Spring Boot] @ExceptionHandler 에서 동일한 Exception을 구분해서 처리하는 방법 (0) | 2023.11.24 |
[Spring Boot] No spring.config.import property has been defined (1) | 2023.11.23 |
반응형
300x250