Framework/SpringBoot

[Spring] VO와 BO, DAO, DTO란 무엇인가

  • -
VO, BO, DAO, DTO는 소프트웨어 개발에서 주로 사용되는 용어들입니다. 각각의 용어는 소프트웨어의 다른 층에서 사용되는 객체들을 나타냅니다. 각각의 역할과 특징에 대해 간단히 설명해보겠습니다.

요약

  1. VO (Value Object):
    • VO는 값을 담는 객체를 나타냅니다. 주로 데이터베이스의 테이블에 대응되는 엔티티의 상태를 나타냅니다.
    • VO는 주로 불변(Immutable)하고, equals() 및 hashCode()와 같은 메서드를 오버라이드하여 객체의 동등성을 비교하는 데 사용됩니다.
  2. BO (Business Object):
    • BO는 비즈니스 로직을 처리하는 객체를 나타냅니다. 주로 비즈니스 규칙을 구현하고, 데이터를 처리하며, 다양한 계산을 수행하는 데 사용됩니다.
    • BO는 비즈니스 도메인에서의 객체를 나타내며, 비즈니스 규칙을 캡슐화하고 적용하는 데 사용됩니다.
  3. DAO (Data Access Object):
    • DAO는 데이터베이스와의 상호 작용을 담당하는 객체를 나타냅니다. 주로 데이터베이스에 접근하여 데이터를 검색, 삽입, 갱신, 삭제하는 데 사용됩니다.
    • DAO는 비즈니스 계층과 데이터 액세스 계층 간의 인터페이스를 제공하여, 비즈니스 로직이 데이터베이스에 직접 접근하지 않고도 데이터에 접근할 수 있도록 합니다.
  4. DTO (Data Transfer Object):
    • DTO는 데이터 전송을 위한 객체를 나타냅니다. 주로 여러 계층 간에 데이터를 전달하고 전송하기 위해 사용됩니다.
    • DTO는 데이터를 보유하는 역할로, 특히 원격 인터페이스(예: 웹 서비스)를 통해 데이터를 전송할 때 사용됩니다. 비즈니스 로직을 포함하지 않으며, 단순히 데이터의 전달 목적으로 사용됩니다.

이러한 객체들은 소프트웨어의 다양한 층에서 역할에 따라 사용됩니다. VO는 데이터를 나타내고, BO는 비즈니스 로직을 구현하고, DAO는 데이터 액세스를 처리하며, DTO는 데이터를 전송하거나 전달하는 데 사용됩니다.

 

 

예제와 함께 자세하게 살펴보겠습니다.

VO (Value Object)

VO(Value Object)는 주로 데이터의 불변성을 보장하고, 비즈니스 로직에서 사용되는 데이터 객체를 나타냅니다.

 

VO는 불변하기 때문에 Setter처럼 값을 변경하는 메서드(수정자)가 존재하면 안 됩니다. 값을 변경할 수 없으니 VO는 주로 읽기 전용 데이터를 표현합니다. 

 

Java 코드로 VO의 예시를 보여드리겠습니다.

public class UserVO {
    private Long id;
    private String username;
    private String email;

    // 생성자
    public UserVO(Long id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
    }

    // Getter
    public Long getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public String getEmail() {
        return email;
    }

    // equals 및 hashCode 메서드 오버라이딩
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserVO userVO = (UserVO) o;
        return Objects.equals(id, userVO.id) &&
                Objects.equals(username, userVO.username) &&
                Objects.equals(email, userVO.email);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, username, email);
    }

    // toString 메서드 오버라이딩
    @Override
    public String toString() {
        return "UserVO{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}


위 코드처럼 수정자(Setter)가 없고 읽기만 가능하도록 Getter 메서드만 존재합니다. 또한 필드의 데이터가 모든 같은 객체는 동일한 객체로 판단해야 하기 때문에 equals 와 hashCode메서드를 오버라이딩 해야 합니다.

 

BO (Business Object)

BO(Business Object)는 비즈니스 로직을 수행하는 객체를 나타냅니다. BO는 비즈니스 규칙을 캡슐화하고 적용하는 데 사용됩니다.

 

보통 BO는 데이터베이스의 엔티티와는 조금 다르게, 비즈니스 로직을 구현하는 데에 중점을 둡니다. 즉, VO에 비즈니스 로직이 추가된 것이 BO입니다.

public class OrderBO {
    public boolean placeOrder(Order order) {
        // 주문 유효성 검사 및 처리 로직
        if (order.isValid()) {
            // 주문 데이터베이스에 저장 및 기타 비즈니스 로직 처리
            // ...
            return true;
        } else {
            return false;
        }
    }

    public boolean cancelOrder(Order order) {
        // 주문 취소 처리 로직
        // ...
        return true;
    }

    public double calculateTotalPrice(Order order) {
        // 주문에 대한 총 가격 계산 로직
        double totalPrice = 0.0;
        // ...
        return totalPrice;
    }
}

 

DAO (Data Access Object)

DAO(Data Access Object)는 데이터베이스나 다른 영구 저장소에 접근하기 위한 객체입니다. 이 객체는 주로 데이터베이스와의 상호작용을 추상화하고 캡슐화하여 비즈니스 로직과 데이터 액세스 로직을 분리합니다. 

 

Spring에서는 Repository 인터페이스가 DAO입니니다. 

 

DAO는 주로 다음과 같은 기능을 수행합니다:

  1. 데이터베이스 연결 관리: 데이터베이스와의 연결을 설정하고 닫는 작업을 처리합니다.
  2. 데이터베이스 쿼리 수행: 데이터베이스로 쿼리를 보내고 결과를 받아오는 작업을 수행합니다.
  3. 데이터 조작: 데이터베이스에서 데이터를 검색, 추가, 수정, 삭제하는 작업을 수행합니다.
  4. 데이터베이스 트랜잭션 관리: 여러 개의 데이터 조작 작업을 하나의 논리적인 단위로 묶어서 원자성, 일관성, 격리성, 지속성을 보장합니다.

 

일반적으로 DAO는 인터페이스로 정의되며, 실제 데이터 액세스 로직은 해당 인터페이스를 구현한 클래스에서 구현됩니다. 

import java.util.List;

public interface UserDAO {
    void save(User user);
    User findById(Long id);
    List<User> findAll();
    void update(User user);
    void delete(Long id);
}

 

DTO (Data Transfer Object)

DTO(Data Transfer Object)는 데이터를 전송하기 위한 객체를 나타냅니다. 주로 여러 계층 간에 데이터를 전달하고 전송하기 위해 사용됩니다. DTO는 데이터베이스에서 직접 가져온 데이터나 외부 시스템과의 통신에서 사용되는 데이터를 나타내는 데 사용됩니다.

 

DTO는 데이터를 저장하고 전달하는 데 사용될 뿐 비즈니스 로직을 포함하지 않습니다.

public class UserDTO {
    public final String username;
    public final String email;
    public final String password;

    // 생성자
    public UserDTO(String username, String email, String password) {
        this.username = username;
        this.email = email;
        this.password = password;
    }
}

 

엔티티가 있는데 왜 DTO를 사용해야 해?

Spring에서 간혹 RequstBody나 ResponseBody에 엔티티를 그대로 사용하는 경우가 있습니다. 

 

하지만 다음과 같은 이유들로 인해 엔티티와 DTO를 구분하여 사용하는 것이 좋습니다.

 

  1. DTO대신 엔티티를 사용하면 엔티티 구조가 모두 노출될 수 있습니다. 
  2. 클라이언트로 넘겨줘야 할 데이터는 API마다 다를 수 있습니다. 때문에 엔티티를 반환값으로 사용하면 유지보수가 힘들어집니다.
  3. DTO를 사용하면 클라이언트에 전달해야 할 데이터의 크기를 조절할 수 있습니다. 엔티티를 반환하면 불필요한 데이터가 클라이언트에 전송될 수 있습니다.
  4. validation, swagger 등의 코드들과 엔티티 코드를 분리할 수 있어 유지보수에 좋습니다.

저는 스프링을 처음 했을 땐 DTO를 만드는게 더 귀찮아서 그냥 엔티티만 사용했는데... 부디 저 같은 실수를 하지 말아주세요...

 


 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.