티스토리 뷰

반응형

✏️ 커맨드 객체란?

Command 객체(혹은 Form 객체, DTO)는 클라이언트의 HTTP 요청 데이터를 Java 객체로 자동 바인딩해주는 패턴이다. Spring MVC에서는 Controller 메서드 파라미터로 선언만 하면 프레임워크가 알아서 값을 채워준다.

✏️ 기본 사용 예시

1. Command 객체 정의

public class CreateUserCommand {

    @NotBlank(message = "이름은 필수입니다")
    private String name;

    @Email(message = "올바른 이메일 형식이어야 합니다")
    private String email;

    @Min(value = 1, message = "나이는 1 이상이어야 합니다")
    private int age;

    // Getter / Setter (또는 @Getter @Setter with Lombok)
}

2. Controller에서 수신

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    @PostMapping
    public ResponseEntity<UserResponse> createUser(
            @RequestBody @Valid CreateUserCommand command,
            BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            throw new ValidationException("입력값이 올바르지 않습니다");
        }

        UserResponse response = userService.createUser(command);
        return ResponseEntity.ok(response);
    }
}

3. Service에서 Entity로 변환

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;

    public UserResponse createUser(CreateUserCommand command) {
        User user = User.builder()
                .name(command.getName())
                .email(command.getEmail())
                .age(command.getAge())
                .build();

        User saved = userRepository.save(user);
        return UserResponse.from(saved);
    }
}

 

✏️ Command 객체의 핵심 역할

역할 설명
데이터 바인딩 HTTP 파라미터 / JSON Body를 Java 객체에 자동 매핑
유효성 검사 @Valid + Bean Validation 어노테이션으로 검증
계층 분리 Entity를 외부에 노출하지 않고 DTO 계층을 유지
의도 명확화 CreateUserCommand, UpdatePasswordCommand 등 동작 의미를 이름에 담음

✏️ 요청 방식별 바인딩 차이

// JSON Body (POST, PUT) → @RequestBody 필요
@PostMapping
public void create(@RequestBody @Valid CreateOrderCommand command) { ... }

// Form 데이터 / Query String (GET) → 어노테이션 없이도 바인딩됨
@GetMapping("/search")
public void search(@Valid SearchCommand command) { ... }

 

✏️ 자주 쓰는 Bean Validation 어노테이션

public class ProductCommand {

    @NotNull                          // null 불가
    @NotBlank                         // null, 빈 문자열, 공백 불가
    @Size(min = 2, max = 50)          // 문자열 길이
    @Min(0) @Max(999999)              // 숫자 범위
    @Email                            // 이메일 형식
    @Pattern(regexp = "^[A-Z]{3}$")   // 정규식
    @Positive                         // 양수
    @Future                           // 미래 날짜

    private String ...;
}

✏️ 실전 팁

  • Command vs Response 분리
    • 요청용 Command 객체와 응답용 Response 객체는 반드시 분리한다. Entity를 직접 반환하면 순환 참조, 불필요한 필드 노출 등의 문제가 생긴다.
  • @ModelAttribute vs @RequestBody
    • HTML Form 전송이나 Query String은 @ModelAttribute(생략 가능), JSON은 @RequestBody를 쓴다. 혼동하면 바인딩이 안 된다.
  • BindingResult 위치
    • @Valid 파라미터 바로 뒤에 BindingResult를 붙이지 않으면 유효성 검사 실패 시 예외가 바로 터진다. 명시적으로 핸들링하려면 반드시 붙여줘야 한다.
  • Lombok 활용
    • @Getter, @Setter, @Builder, @NoArgsConstructor 조합으로 보일러플레이트를 줄인다. 단, @RequestBody로 받을 때는 역직렬화를 위해 기본 생성자(@NoArgsConstructor)가 필요하다.
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/07   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함