프로젝트 개발에서 데이터를 다루기 위해 사용되는 개념들인 DTO, VO, Entity에 대해 정리하려고 한다.
Entity는 실제 DB 테이블에 매칭될 수 있는 클래스이다. 이 Entity의 가장 큰 특징은 식별자를 가진다는 것이다. 식별자가 있기 때문에, 식별자 이외의 데이터가 변경된다고 해서 그 객체가 다른 객체가 되는 것이 아니다.
ORM 혹은 ODM 등과 같이 DB의 row(document)를 객체에 매핑시켜주는 기술에서 Entity가 주로 사용된다고 볼 수 있다. ORM, ODM의 개념의 핵심은 결국 데이터베이스의 데이터를 객체를 통해 다루겠다는 것이기에, DB의 데이터와 매핑될 식별자를 가지고 있어야 하기 때문이다.
Entity는 식별자 덕분에 Setter를 이용하여 가변 객체로서 사용할 수 있다. 식별자만 변하지 않는다면, 같은 객체를 표현하는 것이기 때문에 해당 객체의 값을 변경한다는 의미에서 가변 객체로 활용할 수 있는 것이다.
VO(Value Object)는 값 그 자체를 표현하는 객체이다. VO는 Entity와는 달리 식별자를 가지지 않는데, 그래서 단 하나의 데이터라도 변경되면 다른 객체가 된다. 그 때문에 같은 객체임을 확실하게 보장하기 위해, VO는 일반적으로 불변 객체로서 사용한다.
Spring의 MyBatis를 사용할 때 주로 VO를 사용한다. 그 이유로는 MyBatis는 SQL-Mapper이기에, 가져온 데이터는 그저 값일 뿐 실제 DB의 테이블과 매핑되는 것이 아니다.
VO는 불변 객체이기 때문에 Setter를 구현하지 않는다. 만약 기존 객체의 데이터를 변경하고 싶다면, 변경된 데이터로 아예 새로운 객체를 만들어야 한다.
그리고 VO는 값 그 자체를 표현하기에, 서로 다른 인스턴스이더라도 값이 같으면 같은 객체이다. 그래서 Java에서는 VO를 표현할 때, equals와 hashCode를 구현하여 같은 객체인지 판별한다.
DTO(Data Transfer Object)는 데이터 교환을 위한 객체이다. 데이터 교환만을 위해 사용되기에, 로직을 갖지 않으며 Getter/Setter만을 가진다.
Entity와 VO, DTO에 대한 개념은 비교적 간단하지만, 실제 사용하는 것에 대해서는 의견이 많다. Layered Architecture에서 계층의 역할 분리 및 종속성 감소를 위해 Entity(VO)와 DTO를 분리하여 사용한다. 특정 계층까지는 Entity를 사용하고 나머지는 DTO로 변환하여 통신하는 것이 주된 사용법인데, 어떤 계층까지 Entity를 사용해야 하는가에 대해 말이 많다.
어느 측 의견이든 나름대로의 논리가 있고 장단점이 있다고 생각한다. 결국 중요한건 자신 혹은 단체에서 장단점을 잘 생각해보고, 통일된 규칙으로 적용하는 것이 좋다고 생각한다.