DAO / DTO / VO

2coconut·2025년 7월 10일

DAO (Data Access Object)

DAO란?

DAO(Data Access Object)는 데이터베이스 접근을 담당하는 객체다. 비즈니스 로직과 데이터 접근 로직을 분리하여 코드의 유지보수성과 재사용성을 높이는 것이 주요 목적이다.

DAO의 특징

  • 데이터베이스 CRUD(Create, Read, Update, Delete) 연산 전담
  • 비즈니스 로직과 데이터 접근 로직의 분리
  • 데이터베이스 종류가 변경되어도 비즈니스 로직에 아에 영향이 없진 않음
  • 보통 인터페이스와 구현체로 구성

DTO (Data Transfer Object)

DTO란?

DTO(Data Transfer Object)는 계층 간 데이터 전송을 위한 객체다. 주로 Controller와 Service, Service와 Repository 사이에서 데이터를 주고받을 때 사용한다.

DTO의 특징

  • 순수하게 데이터 전송만을 목적으로 함
  • 일반적으로 비즈니스 로직을 포함하지 않음
  • getter/setter 메서드가 주요 구성 요소
  • Entity 클래스를 외부에 직접 노출하지 않기 위해 사용
  • 네트워크를 통한 데이터 전송 시 직렬화 가능해야 함

Entity 대신 DTO를 사용하는 이유

우선 Entity는 데이터베이스 테이블과 직접 매핑되는 클래스로, 데이터베이스의 구조를 그대로 반영한다.
Entity 클래스를 직접 Controller에서 사용하면 여러 문제가 발생할 수 있다

1. 보안 문제
Entity에는 외부에 노출되면 안 되는 민감한 정보(패스워드, 내부 ID 등)가 포함될 수 있다. DTO를 사용하면 필요한 데이터만 선별해서 전송할 수 있다.

2. 성능 문제
Entity는 연관관계 매핑으로 인해 불필요한 데이터까지 함께 조회될 수 있다. DTO는 정말 필요한 데이터만 담아서 네트워크 비용을 줄일 수 있다.

3. 유지보수 문제
Entity 구조가 변경되면 API 스펙도 함께 변경되어 클라이언트에 영향을 줄 수 있다. DTO는 API 스펙을 안정적으로 유지하는 완충 역할을 한다.

가변 vs 불변 DTO

DTO는 구현 방식에 따라 가변 객체 또는 불변 객체로 만들 수 있다:

가변 DTO

  • 기본 생성자 + setter를 통해 값 설정
  • Jackson 라이브러리와 같은 직렬화/역직렬화 도구와 호환성이 좋음
  • 프레임워크에서 객체 바인딩 시 편리함

불변 DTO

  • 생성자를 통해서만 값 설정, setter 없음
  • 한 번 생성되면 값이 변경되지 않아 안전함
  • 멀티스레드 환경에서 Thread-Safe
  • 최근에는 Record 클래스를 활용한 불변 DTO가 인기
Thead Safe -> 멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없음을 뜻한다

VO (Value Object)

VO란?

VO(Value Object)는 값 자체를 나타내는 객체다. 가장 중요한 특징은 동일한 값을 가진 두 VO 객체는 같은 객체로 취급된다는 것이다.

VO의 특징

  • 불변성(Immutable) - 한 번 생성되면 값을 변경할 수 없음
  • 동등성(Equality) - 같은 값을 가지면 같은 객체로 판단
  • equals()와 hashCode() 메서드 오버라이딩 필수
  • setter 메서드 없음 (불변성 보장)

왜 equals/hashCode 오버라이딩이 필수일까?

VO의 핵심 개념은 "값이 같으면 같은 객체"라는 것이다. 하지만 Java의 기본 동작은 객체의 참조값(메모리 주소)으로 비교하기 때문에, 같은 값을 가져도 다른 객체로 인식한다.

예를 들어, 10,000원짜리 지폐 두 장이 있다면

  • 각각 다른 일련번호(참조값)를 가지지만
  • 우리는 둘 다 "10,000원"이라는 동일한 가치로 인식한다

이것이 바로 VO의 개념이다. equals()와 hashCode()를 오버라이딩해야 Java에서도 이 개념을 구현할 수 있다.

DAO vs DTO vs VO 비교

구분DAODTOVO
목적데이터베이스 접근계층 간 데이터 전송값 표현
주요 역할CRUD 연산 수행데이터 운반체값 객체
가변성상관없음가변/불변 모두 가능불변 (Immutable)
비즈니스 로직데이터 접근 로직만일반적으로 없음포함 가능
equals/hashCode불필요불필요필수 오버라이딩
setter 메서드상관없음일반적으로 있음없음
생명주기스프링 빈으로 관리요청별로 생성/소멸값이 같으면 동일

정리

  • DAO: "어떻게 데이터를 저장하고 가져올까?" → 데이터베이스 접근 담당
  • DTO: "어떻게 데이터를 안전하게 전달할까?" → 계층 간 데이터 전송 담당
  • VO: "값 자체를 어떻게 표현할까?" → 불변의 값 객체로 비즈니스 개념 표현

각각의 목적과 특성을 이해하고 적절한 상황에서 올바르게 사용한다면, 더욱 견고하고 유지보수하기 쉬운 코드를 작성할 수 있다. 특히 VO의 경우 equals/hashCode 오버라이딩을 잊지 말자!

profile
컴공학생

0개의 댓글