IT

DTO와 Entity, VO의 차이점, 개념, 그리고 분리의 목적

0and24 2024. 11. 16. 00:34

데이터베이스와 연동되는 애플리케이션을 개발할 때 EntityDTO는 필수적으로 등장하는 개념입니다. 이 외에도 자주 사용되는 VO(Value Object)Java의 record를 함께 알아보겠습니다. 이번 글에서는 이들 객체의 개념, 차이점, 그리고 분리해야 하는 이유를 쉽게 설명해보겠습니다.

1. Entity란?

Entity데이터베이스 테이블과 1:1로 매핑되는 클래스입니다. 데이터베이스의 한 행(row)을 의미하며, JPA와 같은 ORM(Object-Relational Mapping) 프레임워크를 통해 데이터베이스와 연결됩니다. 주로 비즈니스 로직을 포함할 수 있으며, 데이터베이스의 상태를 반영하는 역할을 합니다

//예시 코드
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private String email;

    // 비즈니스 로직 예시
    public boolean isEmailVerified() {
        // 이메일 검증 여부를 반환
    }

    // Getters and Setters
}

2. DTO란?

DTO(Data Transfer Object)데이터 전송을 위해 사용하는 객체로, 주로 컨트롤러와 서비스 간의 데이터를 전달하는 용도로 사용됩니다. DTO는 필요한 데이터만 담고 있으며 비즈니스 로직이 포함되지 않습니다. 클라이언트에 노출되는 데이터를 DTO로 관리하면 보안성을 강화할 수 있고, 불필요한 데이터를 제외해 효율성을 높일 수 있습니다.

//예제 DTO
public class UserDto {
    private String name;
    private String email;

    // 필요한 데이터만 포함
    public UserDto(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getters and Setters
}

3. VO란?

VO(Value Object)는 값 객체로, 주로 불변(immutable) 데이터 표현에 사용됩니다. 값 그 자체가 의미를 가지며, VO는 보통 ID가 필요하지 않고 값만으로 동일성을 판단합니다. VO는 금액, 좌표, 주소 등 여러 속성으로 이루어진 값을 표현할 때 적합하며, 값이 동일하면 동일한 객체로 간주됩니다.

//VO 예제
public class Address {
    private final String city;
    private final String district;
    private final String street;

    public Address(String city, String district, String street) {
        this.city = city;
        this.district = district;
        this.street = street;
    }

    // 불변 객체로 사용하기 위해 Getters만 제공
    public String getCity() { return city; }
    public String getDistrict() { return district; }
    public String getStreet() { return street; }

    // equals와 hashCode를 오버라이드하여 값 비교
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Address)) return false;
        Address address = (Address) o;
        return city.equals(address.city) && 
               district.equals(address.district) && 
               street.equals(address.street);
    }

    @Override
    public int hashCode() {
        return Objects.hash(city, district, street);
    }
}

4. Java의 record와 VO

Java의 record는 값 객체를 표현하는 데 적합한 새로운 데이터 타입으로, VO로 자주 사용됩니다. record는 불변성을 기본으로 하며, 값을 기반으로 동일성을 판단합니다. record는 필드 선언만으로 간결하게 불변 객체를 생성할 수 있어 VO를 간단히 구현하기에 유리합니다.

public record Address(String city, String district, String street) {}

이처럼 record를 사용하면 필드와 메서드를 자동으로 생성하여 VO를 간편하게 구현할 수 있습니다.

5. DTO와 Entity, VO의 차이와 분리의 목적

객체 타입역할 및 목적특징

Entity 데이터베이스와 매핑되는 객체 비즈니스 로직 포함 가능, 고유 ID 필요
DTO 데이터 전송을 위한 객체 필요한 데이터만 포함, 읽기 전용, 비즈니스 로직 없음
VO 값 표현을 위한 객체 값 자체로 동일성 판단, 불변성 유지, ID 필요 없음
record 불변 객체(주로 VO로 사용) 간결한 선언, 값 기반 비교와 불변성 제공

분리의 목적
Entity와 DTO를 분리하는 주된 이유는 안정성, 보안, 유연성입니다. Entity는 데이터베이스 구조와 직결되기 때문에 외부에 노출하면 보안상 위험이 있을 수 있습니다. DTO를 사용해 필요한 데이터만 전달하고, Entity는 내부 비즈니스 로직과 데이터베이스와의 연결을 안전하게 유지할 수 있습니다. VO는 값으로서의 동일성만 요구되는 데이터 구조에 적합하며, record는 불변성을 쉽게 제공해 VO로서 효율적으로 활용됩니다.


이처럼 DTO, Entity, VO, record의 개념과 차이, 사용 목적을 이해하면 데이터 구조와 보안성을 강화하고, 코드를 효율적으로 관리할 수 있습니다.