티스토리 뷰

Spring

[Spring]DAO와 DTO, VO

retto9522 2024. 9. 12. 10:12

DAO(Data Access Object)

DAO는 실제로 DB의 Data에 접근하기 위한 객체입니다.

  • 실제로 DB에 접근하여 data를 삽입, 삭제, 조회, 수정 등 CRUD 기능을 수행합니다.
  • Service와 DB를 연결하는 고리 역할을 합니다.
  • Repository package가 바로 DAO입니다.
@Repository
@RequiredArgsConstructor
public class MemberRepository {
 
    private final EntityManager em;
 
    public void save(Member member) {
        em.persist(member);
    }
 
    public Member findOne(Long id) {
        return em.find(Member.class, id);
    }
 
    public List<Member> findAll() {
        return em.createQuery("select m from Member m", Member.class).getResultList();
    }
 
    public List<Member> findByName(String name) {
        return em.createQuery("select m from Member m where m.name =:name", Member.class)
                .setParameter("name", name)
                .getResultList();
    }
}

DTO(Data Transfer Object)

DTO는 계층 간 데이터 교환을 하기 위해 사용하는 객체로, DTO는 로직을 가지지 않는 순수한 데이터 객체(Java Beans)입니다.

  • DTO는 즉, Getter/Setter 메서드만 가진 클래스를 의미합니다.
  • DB에서 데이터를 얻어서 Service나 Controller로 보낼 때 사용합니다.
  • 즉, 엔티티를 DTO 형태로 변환한 후 사용합니다.

한번 예시 코드로 정리해보겠습니다.

  1. domain(Entity) logic
  2. DTO logic
  3. Controller logic

1. 먼저 다음과 같은 Entity가 있다고 가정해보겠습니다.

@Entity
@Getter
@Setter
public class Member {
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String name;
	private int age;
 
}

2. 아래는 DTO 클래스 입니다.

   @Getter
    @Setter
    static class ResponseDto {
        private String name;
        private String result = "결과입니다.";
 
        public ResponseDto(Member member) {
            name = member.getName();
        }
    }

3. 아래는 Controller logic 입니다.

    @PostMapping("api/useDTO")
    @ResponseBody
    public ResponseDto useDTO(@RequestParam String name, @RequestParam Long id) {
    	Member findMember = memberService.findOne(id);
        return new ResponseDto(findMember);
    }
    
    @PostMapping("api/notUseDTO")
    @ResponseBody
    public FindMember notUseDTO(@RequestParam String name, @RequestParam Long id) {
        Member findMember = memberService.findOne(id);
        return new FindMember(findMember);
    }

결과

useDTO는 Entity의 결과를 DTO로 변환하여 원하는 결과인 name과 result만 클라이언트에게 반환합니다.

하지만, notUseDTO는 Member 엔티티의 모든 정보. 즉, 엔티티 그 자체를 클라이언트에게 반환합니다.

 

위 예시에는 DTO를 Response에만 이용했지만, Request에도 적용할 수 있습니다.


VO(Value Object)

VO는 DTO와 달리 Read-Only 속성을 지닌 값 오브젝트입니다.

DTO는 Setter를 가지고 있어 값이 변할 수 있지만 VO의 경우, Getter만 가지고 있어 수정이 불가능합니다.

 

DTO와 VO의 차이점은 DTO는 인스턴스 개념이고, VO는 리터럴 값 개념입니다. VO는 값들에 대해 Read-Only를 보장해줘야 존재의 신뢰성이 확보되지만, DTO의 경우 단지 데이터를 담는 그릇의 역할일 뿐 값은 그저 전달되어야 할 대상입니다. 따라서, 값 자체에 의미가 있는 VO와 전달될 데이터를 보존해야 하는 DTO의 특성상 개념이 다릅니다.

 

VO의 핵심은 두 객체의 모든 필드 값들이 동일하면 두 객체는 같다는 것입니다. 따라서 완전히 값 자체 표현 용도로만 사용하는 게 목적이라면, 두 객체의 모든 필드 값들이 모두 같으면 같은 객체이도록 만드는 것(equals()와 hashCode()의 Overriding)이 중요하지, 메서드는 어떤 메서드가 있던 상관 없습니다.

 

DTO와 VO의 차이

종류 용도 동등 결정 가변 / 불변 로직
DTO 계층 간 데이터 전달 속성값이 모두 같아도 같은 객체가 아닐 수 있음 - setter 존재 시 가변,
- setter 비 존재 시 불변
getter/setter 이외의 로직이 불필요함
VO 값 자체를 표현 속성값이 모두 같으면 같은 객체 불변 getter/setter 이외의 로직을 가질 수 있음
공지사항
최근에 올라온 글
Total
Today
Yesterday