DAO (Data Access Object)와 DTO (Data Transfer Object), VO (Value Object)

CJI0524·2025년 3월 25일
0

Spring/JDBC

목록 보기
2/3

해당 글에서는 DAO, DTO, VO에 대해서 알아본다.

1. DAO (Data Access Object)란?

DAOData Access Object의 약자로, 데이터베이스에 접근하는 코드를 분리해서 관리하는 패턴이다. 예를 들어, 데이터베이스 쿼리를 수행해서 데이터를 가져오거나 저장하는 로직을 DAO에 몰아두면, 비즈니스 로직은 깔끔하게 분리되어 유지보수와 테스트가 쉬워진다. DAO의 예제 코드는 다음과 같다.

✍️ 예시 코드 작성

// 예시: UserDAO.java
@Repository
public class UserDAO {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public User findUserById(Long id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new Object[]{id}, (rs, rowNum) -> 
            new User(rs.getLong("id"), rs.getString("name"), rs.getString("email"))
        );
    }
}

위 코드는 데이터베이스에 접근해서 사용자 정보를 가져오는 역할을 DAO가 담당하는 예시이다. 여기서 DAO는 DB와 직접적으로 소통하는 코드들을 모아두는 역할을 맡는다.


2. DTO (Data Transfer Object)란?

DTOData Transfer Object의 약자로, 계층 간 데이터를 전달할 때 사용하는 객체라고 할 수 있다. 예를 들어, DAO에서 가져온 데이터를 컨트롤러로 넘길 때 불필요한 비즈니스 로직 없이 단순 데이터만 담아서 이동시키는 역할을 맡는다. DTO는 보통 getter/setter만 가진 단순 객체 (POJO)로 만들어진다. DTO의 예제 코드는 다음과 같다.

✍️ 예시 코드 작성

// 예시: UserDTO.java
public class UserDTO {
    private Long id;
    private String name;
    private String email;

    // 생성자, getter, setter 생략
}

DTO를 사용하는 이유는, 데이터베이스 엔티티와 UI 혹은 다른 계층에서 사용되는 데이터의 구조가 다를 때 이를 분리해서 관리하기 위함이다. 예를 들어, 데이터베이스에서는 불필요한 정보까지 다 담고 있을 수 있는데, 클라이언트에 전달할 때는 필요한 데이터만 전달하는 식으로 DTO를 활용할 수 있다.


3. VO (Value Object)란?

VOValue Object의 약자이다. 객체지향 디자인에서 VO는 변경 불가능 (immutable)한 값 객체를 의미한다. 데이터 전달용 DTO와는 다르게, VO는 그 자체의 값으로 동등성을 판단하고, 한 번 생성되면 내부 데이터가 바뀌지 않는다. VO의 예제 코드는 다음과 같다.

✍️ 예시 코드 작성

public final class Money {
    private final BigDecimal amount;
    private final Currency currency;

    public Money(BigDecimal amount, Currency currency) {
        this.amount = amount;
        this.currency = currency;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public Currency getCurrency() {
        return currency;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Money money = (Money) o;
        return amount.equals(money.amount) &&
               currency.equals(money.currency);
    }

    @Override
    public int hashCode() {
        return Objects.hash(amount, currency);
    }
}

이 예제에서 Money는 VO로서, 생성된 후 내부 값 (amount, currency)이 변경되지 않고, 두 Money 객체는 값이 같으면 동일한 것으로 판단한다. 이런 방식은 객체의 불변성을 보장해줘서, 예기치 않은 사이드 이펙트를 막을 수 있다.


4. 이 글을 작성하는데 참고한 글 목록

[JAVA] DAO, DTO, VO 차이

profile
개발돌이

0개의 댓글