[Spring Boot] Form 데이터를 위한 객체 설계 VO vs DTO, 무엇을 선택할까?
Spring Boot로 웹 애플리케이션을 개발할 때, 사용자가 입력한 Form 데이터를 처리하기 위한 객체를 설계하면서 "VO(Value Object)와 DTO(Data Transfer Object) 중 무엇이 적합할까?"라는 고민을 많이 합니다.
VO (Value Object)
정의: VO는 도메인에서 특정 값을 표현하는 객체로, 주로 불변성을 유지하며 동등성(equality) 기반 비교를 지원합니다.
특징
불변 객체로 설계(Immutable)
동일한 값이면 같은 객체로 간주
사용 목적
도메인 내에서 값의 동등성을 비교하거나, 특정 값을 의미 있게 표현할 때 활용
DTO (Data Transfer Object)
정의: DTO는 계층 간 데이터를 전송하기 위해 사용되는 객체로, 주로 클라이언트-서버 간 데이터 교환에 사용됩니다.
특징
일반적으로 getter와 setter가 포함
직렬화 가능
값이 가변(Mutable)하도록 설계
사용 목적
데이터를 입력받거나, 서비스 간 데이터 전송을 위해 활용
Form 데이터와 API 응답 데이터를 주고받는 데 중점
Spring Boot에서 Form 데이터를 위한 객체 설계
Form 데이터의 특성과 요구사항
Spring Boot에서 Form 데이터 처리는 다음과 같은 특성을 가집니다.
사용자 입력 데이터를 서버로 전달.
데이터가 가변적이며 검증(validation)이 필요.
클라이언트-서버 간 전송 목적.
이러한 요구사항은 DTO의 특징과 일치합니다. 따라서 Form 데이터를 위한 객체로는 DTO 사용이 적합합니다.
DTO를 사용하는 이유
데이터 전달 목적에 부합
Form 데이터는 주로 데이터를 서버에 전달하거나 저장 및 처리 전 데이터를 변환하는 데 사용됩니다. 이는 DTO의 주된 목적과 같습니다.
가변성(Mutability)
VO는 일반적으로 불변 객체로 설계되지만, Form 데이터는 사용자의 입력에 따라 값이 변경됩니다. 따라서 변경 가능한 DTO가 적합합니다.
데이터 검증 및 변환 용이
DTO는 컨트롤러 계층에서 데이터를 검증하고 비즈니스 로직에 전달하기 전에 필요한 가공 및 변환 작업을 수행하기 쉽습니다.
Spring Boot에서 DTO 사용 방법
DTO 클래스 설계
Form 데이터를 수집하기 위한 DTO 클래스는 다음과 같이 정의할 수 있습니다.
public class UserFormDTO {
private String username;
private String email;
private String password;
// Getters and Setters
}컨트롤러에서 DTO로 데이터 받기
Spring Boot의 컨트롤러에서 DTO 객체를 활용해 Form 데이터를 처리하는 예제
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import jakarta.validation.Valid;
@Controller
public class UserController {
@PostMapping("/register")
public String registerUser(@Valid @ModelAttribute("userForm") UserFormDTO userForm, BindingResult result) {
if (result.hasErrors()) {
return "register"; // 유효성 검증 실패 시 다시 Form 페이지로 리턴
}
// Form 데이터 처리 로직 (e.g., 서비스 호출)
return "redirect:/success"; // 성공 시 리다이렉트
}
}VO와 DTO의 역할 분리 전략
DTO 사용이 적합한 경우
클라이언트-서버 간 데이터를 전송할 때.
Form 데이터를 받아 서버에 전달하거나, 비즈니스 로직 처리 전 데이터를 검증할 때.
컨트롤러 계층에서 데이터를 처리할 때.
VO 사용이 적합한 경우
도메인 계층에서 특정 값을 불변 객체로 표현해야 할 때.
값 자체가 비즈니스 의미를 가지며, 동등성 비교가 중요한 경우.
실무 데이터 흐름 예시
컨트롤러 계층: Form 데이터를 DTO로 받음.
서비스 계층: DTO를 처리하거나 VO/엔티티로 변환.
리포지토리 계층: 엔티티(Entity)를 통해 데이터베이스와 상호작용
@Service
public class UserService {
public void registerUser(UserFormDTO userFormDTO) {
User user = new User();
user.setName(userFormDTO.getUsername());
user.setEmail(userFormDTO.getEmail());
user.setPassword(userFormDTO.getPassword());
userRepository.save(user); // Entity 저장
}
}특징 | VO | DTO |
|---|---|---|
주요 목적 | 도메인 값 표현 | 데이터 전송 및 검증 |
설계 방식 | 불변 객체(Immutable) | 가변 객체(Mutable) |
적용 계층 | 도메인 계층 | 컨트롤러, 서비스 계층 |
적용 사례 |
| Form 데이터, API 요청/응답 데이터 |