1️⃣ DAO (Data Access Object)
- 실제 DB에 접근하는 객체
DB에서 데이터를 꺼내오거나 넣는 역할
DB에 접속하여 데이터의 CRUD작업을 하는 클래스 - Service와 실제 데이터베이스를 연결하는 역할을 하게 됨
- 데이터베이스에 접근하기 위한 로직과 비즈니스 로직을 분리하기 위해 사용함
(원래 DB의 데이터와 프로그래밍 언어는 패러다임의 불일치로 인해 사용할 수 없음)
Spring Data JPA에서는 JpaRepository를 상속받는 인터페이스가 DAO의 역할을 하게된다.
2️⃣ Entity
이때, Entity Class를 통해 클래스를 DB테이블과 1:1 매칭할 수 있음
- Entity는 실제 DB테이블에 존재하는 Column들과 매핑되는 핵심 클래스
- Entity는 DB의 테이블과 1대1 대응이며, 테이블에 가지지 않는 칼럼을 필드로 가져서는 안됨
- 이를 기준으로 테이블이 생성되고 스키마가 변경됨
- 절대 요청이나 응답값을 전달하는 클래스로 사용해서는 안됨
- Entity는 id로 구분되며, 비지니스 로직을 포함할 수 있음
setter를 가지는 경우 가변 객체로 활용 가능
public class Member {
private final Long id;
private final String email;
private final String password;
private final Integer age;
public Member() {
}
public Member(Long id, String email, String password, Integer age) {
this.id = id;
this.email = email;
this.password = password;
this.age = age;
}
}
💚 Entity, DTO 클래스를 분리하는 이유
Entity 클래스를 통해 DB에서 데이터를 꺼내왔지만, 데이터를 접근해야하는 경우 문제가 생김!!
→ DTO 사용
데이터를 움직일 때 Entity 객체를 그대로 사용하지 않고 DTO를 사용하는 이유는 무엇일까?
- View와 DB의 역할을 분리하기 위해서
- Entity 객체의 변경을 피하기 위하여
- Entity는 실제 DB테이블과 매핑되어 있어 만약 변경될 시에 다른 클래스에 영향을 미침
- DTO는 View와 통신하며 자주 변경되므로
- Entity 클래스를 보호하기 위해 분리해주어야 함
- 도메인 모델링을 지키기 위하여
3️⃣ DTO (Data Transfer Object)
- 데이터를 Transfer(이동)하기 위한 객체
- 계층간 데이터를 주고 받을때, 데이터를 담아 전달하는 바구니임
- 주로 Client와 Controller 사이에서 데이터 주고받을 때 활용
(여러 레이어 사이에서 사용은 가능) - Client가 Controller에 요청을 보낼 때도 RequestDto의 형식으로 데이터가 이동
Controller가 Client에게 응답을 보낼 때도 ResponseDto의 형태로 데이터를 보냄 - DTO는 로직을 갖고 있지 않는 순수한 데이터 객체
일반적으로 getter/setter 메서드만을 가짐 (Setter보다 생성자 쓰는거 권유)
💚 Setter 보다 생성자 사용을 권유하는 이유
setter의 경우 변조 가능성이 있기 때문
//getter와setter 메서드 만을 가진다
public class UserDTO {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
아래와 같이 생성자로 값을 넣어주도록 하게 하면 전달하는 과정에서 변조가 불가능
//생성자를 이용한 불변 객체
public class UserDTO {
private String name;
private String id;
public UserDTO(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
}
4️⃣ VO (Value Object)
- 값 자체를 표현하는 객체
(고유번호가 다른 만원 2장이 있으면 둘다 10000의 값을 가지므로 동일하다고 여김) - getter 메소드와 비지니스 로직을 포함할 수 있으며 setter 메소드는 가지지 않음
- 특정 값 자체를 표현하기 때문에 setter 같은 성격의 변조 가능성이 있는 메서드가 존재하면 안되며 생성자를 사용해야함
- 값 비교를 위해서는 equals()와 hashCood() 메소드를 오버라이딩 해줘야 함
equals()와 hashCood() 메소드를 오버라이딩 하지 않았을 때
// Money.java
public class Money {
private final String currency;
private final int value;
public Money(String currency, int value) {
this.currency = currency;
this.value = value;
}
public String getCurrency() {
return currency;
}
public int getValue() {
return value;
}
}
// MoneyTest.java
public class MoneyTest {
@DisplayName("VO 동등비교를 한다.")
@Test
void isSameObjects() {
Money money1 = new Money("원", 10000);
Money money2 = new Money("원", 10000);
assertThat(money1).isEqualTo(money2);
assertThat(money1).hasSameHashCodeAs(money2);
}
}
equals()와 hashCood() 메소드를 오버라이딩 했을 때
// Money.java
public class Money {
private final String currency;
private final int value;
public Money(String currency, int value) {
this.currency = currency;
this.value = value;
}
public String getCurrency() {
return currency;
}
public int getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Money money = (Money) o;
return value == money.value && Objects.equals(currency, money.currency);
}
@Override
public int hashCode() {
return Objects.hash(currency, value);
}
}
// MoneyTest.java
public class MoneyTest {
@DisplayName("VO 동등비교를 한다.")
@Test
void isSameObjects() {
Money money1 = new Money("원", 10000);
Money money2 = new Money("원", 10000);
assertThat(money1).isEqualTo(money2);
assertThat(money1).hasSameHashCodeAs(money2);
}
}
5️⃣ 총정리 비교
분류 | DTO | VO | ENTITY |
정의 | 레이어간 데이터 전송용 객체 | 값 표현용 객체 | DB 테이블 매핑용 객체 |
상태 변경 여부 | setter 존재 시 가변 setter 비존재 시 불변 |
불변 | setter 존재 시 가변 setter 비존재 시 불변 |
로직 포함 여부 | 포함 불가능 | 포함 가능 | 포함 가능 |
💻 reference
'Server > Spring Boot' 카테고리의 다른 글
[Spring Boot] ERD (Entity Relationship Diagram) 란? (0) | 2023.10.15 |
---|---|
[Spring Boot] JWT를 사용한 인증, 인가 과정 (Access Token, Refresh Token 이용) (0) | 2023.10.01 |
[Spring Boot] 빌더(Builder) 패턴의 정의, 생성자 패턴 빌더 패턴 비교 (0) | 2023.09.25 |
[Spring] 스프링 의존성 주입 종류와 @RequiredArgsConstructor 어노테이션을 사용한 생성자 주입 (0) | 2023.09.24 |
[Chapter 03] 스프링 부트에서 JPA로 데이터베이스 다뤄보자 (1) - 등록 (0) | 2023.09.24 |