[Servlet&JSP] Entity, DAO, DTO, VO 구분

2022. 1. 14. 12:15JAVA/Servlet&JSP

1. Entity 클래스란 무엇인가?

Entity 클래스는 실제 데이터베이스의 테이블과 1:1로 매핑되는 클래스입니다. Entity 클래스는 데이터베이스의 테이블 내에 존재하는 컬럼(column)만을 필드멤버로 가져야 합니다. Entity 클래스는 상속을 받거나 구현체여서는 안되며, 테이블내에 존재하지 않는 컬럼을 가져도 안됩니다. 

1.1 Entity와 DTO의 분리 이유

Entity 클래스와 DTO 클래스를 분리해서 관리해야 하는 이유는 DB Layer와 View Layer 사이의 역할을 분리하기 위해서이다. 여기서 DB Layer에서 수행하는 일은 실제 데이터베이스 안에서 INSERT, UPDATE, DELETE문과 같은 테이블의 데이터 레코드에 영향을 미치는 연산을 수행합니다. View Layer에서 수행하는 일은 사용자(Client)에게 UI를 보여주는 역할을 수행합니다. 대표적으로 JSP를 이용하여 자바 로직의 결과를 브라우저를 통해 확인할 수 있습니다.

 

Entity 클래스같은 경우 실제 테이블과 매핑되어 만일 변경되게 되면 여러 다른 Class에 영향을 끼치게 됩니다. DTO는 View와 통신하며 자주 변경되므로 Entity 클래스와 DTO 클래스는 분리 해주어야 합니다.

 

DTO는 Domain Model 객체인 Entity를 그대로 두고 복사하여 Controller Layer에서 Service Layer로 넘길때나 Controller Layer에서 View Layer로 넘길때 사용한다고 생각합니다.

 

1.2 Entity 클래스의 Setter 금지

Entity 클래스를 작성할때 Setter를 무분별하게 사용하면 Entity 객체의 값을 쉽게 변경할 수 있습니다. 즉, 객체의 일관성을 보장할 수 없습니다. 객체의 일관성을 유지할 수 있어야 유지 보수성이 올라가기 때문에 Setter 사용을 지양해야 하며 객체의 생성자를 정의함으로써 Setter 사용을 줄일 수 있습니다.

public Student(int num, String name, int age, int grade)
{
	this.num = num;
    this.name = name;
    this.age = age;
    this.grade = grade;
}

 

1.3 Entity 클래스 예제

public class Student {
	private int num;
	private String name;
	private int age;
	private int grade;
	
	public Student(int num, String name, int age, int grade) {
		this.num = num;
		this.name = name;
		this.age = age;
		this.grade = grade;
	}

	public int getNum() {
		return num;
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

	public int getGrade() {
		return grade;
	}	
}

위의 코드처럼 setter 함수를 없애고 생성자를 통해서 객체를 생성합니다. 

2. DAO란 무엇인가?

DAO(Data Access Object)는 실제로 Persistence Layer인 데이터베이스에 접근하는 객체입니다. SQL을 사용하여 데이터베이스에 접근한 후 적절한 CRUD API를 제공합니다. 

 

아래의 예제는 데이터베이스 접근하여 모든 학생(student)들의 정보를 탐색하는 서비스입니다.

public class StudentService{
	public static List<Student> findAllStudent() throws SQLException
	{
		List<Student> students = new ArrayList<Student>();
		
		PreparedStatement pst = null;
		Connection conn = null;
		ResultSet rs = null;
		String sql = "select * from student";
		
		try {
			conn = JDBCConnection.getConnection();
			pst = conn.prepareStatement(sql);
			rs = pst.executeQuery();
			
			while(rs.next())
			{
				String name = rs.getString("name");
				int age = rs.getString("age");
				int grade = rs.getString("grade");
				
				
				students.add(new Student(name, age, grade));
			}
			
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}finally {
			if(rs!=null)
			{
				rs.close();
			}
			if(pst!=null)
			{
				pst.close();
			}
			if(conn!=null)
			{
				conn.close();
			}
		}
		
		return students;
	}
}
List<Student> students = StudentService.findAllStudents();

위와 같이 StudentService라는 DAO 객체를 사용하여 모든 학생들의 정보를 리스트화하여 저장할 수 있습니다.

 

3. DTO란 무엇인가?

DTO(Data Transfer Object)는 계층간 데이터 교환을 위한 객체입니다. 데이터베이스의 데이터를 Service나 Controller 등으로 전송할 때 사용하는 객체입니다. 로직을 갖고 있지 않는 순수한 데이터 객체이며, getter / setter 메서드만을 갖고 있습니다. 또한 Controller Layer에서 Response DTO 형태로 Client에 전달됩니다.

 

다음은 Student Entity에 대한 DTO 객체입니다.

public class StudentDTO {
	private int num;
	private String name;
	private int age;
	private int grade;
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getGrade() {
		return grade;
	}
	public void setGrade(int grade) {
		this.grade = grade;
	}	
}

 

4. VO란 무엇인가?

VO(Value Object)는 값 객체라는 의미입니다. VO의 대표적인 특징은 다른 객체와는 다르게 내부에 선언된 속성(Field)의 모든 값들이 VO 객체마다 값이 같으면 똑같은 객체라고 판별합니다. 예를 들어 5천원권 화페에는 각각의 일련번호(객체의 주소값)가 존재하지만 사람들은 객체의 주소값이 다르다고 2개의 5천원권이 다르다고 하지 않습니다. 왜냐하면 5천원이(속성 값)라는 가치는 동일하기 때문입니다. 

 

VO는 Getter / Setter를 가질 수 있고 테이블 내에 있는 속성 외에 추가적인 속성을 가질 수 있습니다.

 

4.1 VO의 예제

public class StudentVO {
	private int num;
	private String name;
	private int age;
	private int grade;
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getGrade() {
		return grade;
	}
	public void setGrade(int grade) {
		this.grade = grade;
	}
	
	@Override
	public int hashCode() {
		return Objects.hash(num);
	}
	@Override
	public boolean equals(Object o) {
		if(this==o)
		{
			return true;	
		}	
		if(o==null || getClass() != o.getClass())
		{
			return false;
		}
		Student student = (Student) o;
		return Objects.equals(num, student.getNum());
	}	
}

 

5. DTO와 VO의 차이점

VO와 DTO는 Data를 전달하는 객체로 동일한 개념이지만 VO는 특정한 Business Logic의 결과 값을 담는 객체입니다. equals, hashCode 메서드를 오버라이드하여 구현하여 특정 중요한 데이터를 전달할 때는 VO를 생성하여 이를 동일한 객체 비교까지 필요한 Logic 내에서 주로 사용하게 됩니다. DTO는 레이어간의 단순 통신 용도로 오고가는 데이터 전달 객체입니다. 조금 더 포괄적으로 제한없이 사용할 수 있는 객체이므로, 민감하지 않거나 해당 객체안의 값들을 통해 동일한 객체임을 비교하는 로직에 사용되지 않을 때는 단순하게 DTO를 사용하면 됩니다.

 

References

https://velog.io/@gillog/Entity-DTO-VO-%EB%B0%94%EB%A1%9C-%EC%95%8C%EA%B8%B0
https://gmlwjd9405.github.io/2018/12/25/difference-dao-dto-entity.html