[java Spring] DAO, DTO, VO

‍박태우·2024년 10월 7일

Spring

목록 보기
4/6

이번에 스프링을 공부하게 되면서 DTO 라는 객체를 만들어서 사용해 보게 되었다.
DTO 말고도 DAO, VO 라는 객체도 존재하는데 이들의 역할이 무엇인지 정확히 알아보고 싶었다.

1. DTO

  • Data Transfer Object 의 약자로서 데이터를 전달하기 위한 객체

레이어 간 데이터를 주고 받을 때 사용하며, getter, setter 메서드를 포함한다. (가변 객체와 불변 객체로 나뉠 수 있다.)

  • 예시 코드 (가변 객체)
// 기본 생성자로 생서 후 필드를 변경 가능하다.
@Getter
@Setter
public class DtoEx {
    private String name;
 	private Integer age;
}
  • 예시 코드 (불변 객체)
// setter 가 없고 오로지 필드 값을 얻을 수만 있는 경우
// 오버라이딩 된 생성자를 사용한다.
@Getter
public class DtoEx {
    private final String name;
    private final int age;

    public DtoEx(String name, int age) {
        this.name = name;
        this.age = age;
    }

}

=> 사실 지금까지 많이 써왔기 때문에 이해하는데 어려움은 없었다. 하지만 생소한건 다음말할 것 부터이다.


2. DAO

  • Data Access Object 의 약자로서 Database 에 접근하는 역할을 하는 객체로서 service 와 db를 연결하는 역할

사용하는 이유? :
1. 효율적인 커넥션 관리, 보안성
2. DAO 는 비즈니스 로직을 분리하고 도메인 로직으로 부터 DB와 관련한 메커니즘을 은닉하기 위하여 사용한다.

  • 예시 코드
  1. UserDAO 인터페이스
import java.util.List;

public interface UserDAO {
    void addUser(User user);
    User getUser(int id);
    List<User> getAllUsers();
}
  1. 구현체 클래스 UserDAO 클래스
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class UserDAOImpl implements UserDAO {
    private Connection connection;

    public UserDAOImpl(Connection connection) {
        this.connection = connection;
    }

    @Override
    public void addUser(User user) {
        try (PreparedStatement statement = connection.prepareStatement("INSERT INTO users (name) VALUES (?)")) {
            statement.setString(1, user.getName());
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public User getUser(int id) {
        try (PreparedStatement statement = connection.prepareStatement("SELECT * FROM users WHERE id = ?")) {
            statement.setInt(1, id);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                return new User(resultSet.getInt("id"), resultSet.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<User> getAllUsers() {
        List<User> users = new ArrayList<>();
        try (Statement statement = connection.createStatement();
             ResultSet resultSet = statement.executeQuery("SELECT * FROM users")) {
            while (resultSet.next()) {
                users.add(new User(resultSet.getInt("id"), resultSet.getString("name")));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return users;
    }
}

jdbc 예시 ) 위와 같은 식으로 데이터베이스에 접근할 객체를 정의하고
정해진 객체를 통해 db에 접근함으로서 db의 매커니즘을 은닉가능

JPA 에서는 Repository 를 이용하여 DAO 를 대신한다. (보통은)


3. VO

  • Value Object 의 약자로서 값을 표현하는 객체를 의미한다.

특징

  1. 불변성 (Immutable) : VO 는 값이 한 번 설정되면 변경되지 않는다. 값이 변경되는 경우 새로운 VO 객체를 생성하는 방식으로 처리된다.
  2. 동등성 (Equality) : VO 객체는 메모리 주소가 아닌 값을 기준으로 동일성을 판단한다.
    (ex : String str1 = new String("abc");
    String str2 = "abc" ; // 이떼 str1 == str2)
  3. 데이터 전달 : 주로 시스템 내에서 데이터를 전달하거나 값을 표현하는 용도로 사용된다.

=> 보통 VO는 데이터페이스에서 가져온 데이터를 읽기 전용으로 사용하거나, 특정 연산에서 상태 변경이 불필요한 값을 전달하는 데 사용됨

  • 예시
public class UserVO {
    private final String name;
    private final String email;

    // 생성자를 통해 값 설정
    public UserVO(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // getter 메서드만 제공하여 값이 변경되지 않도록 함
    public String getName() {
        return name;
    }

    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;

        if (!name.equals(userVO.name)) return false;
        return email.equals(userVO.email);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + email.hashCode();
        return result;
    }
}
  • 사용 예시
public class Main {
    public static void main(String[] args) {
        UserVO user1 = new UserVO("John", "john@example.com");
        UserVO user2 = new UserVO("John", "john@example.com");

        // 두 객체가 같은 값이면 동등하다고 간주됨
        if (user1.equals(user2)) {
            System.out.println("두 사용자는 동일한 사용자입니다.");
        }
    }
}

4. VO vs DTO

  • VO : 불변성을 가지며, 주로 값 자체를 표현 하는 객체, 값이 변경되지 않는 상태를 전달할 때 사용
  • DTO : 계층 간 데이터 전송을 위한 객체로, 주로 값의 변경이 가능하고 읽기/쓰기 기능을 제공.

가변, 불변의 차이일 뿐 혼용해서 사용되기도 한다. DTO는 계층간 이동이 추가된 것!

profile
잘 부탁드립니다.

0개의 댓글