-
DAO,DTO,VO의 차이개발 상식 2023. 7. 19. 16:04
Spring 개발을 하면서 dao, dto, vo에 대해서 많이 들어는 봤지만, 정확히 어떤 것을 dao, dto, vo라고 명명하고 사용하는 지에 대해서 리마인드하고자 한다.
DAO(Data Access Object)
DAO는 실제로 DB의 data에 접근하기 위한 객체이다.
- 실제로 DB에 접근하여 data를 삽입, 삭제, 조회, 수정 등 CRUD기능을 수행한다.
- 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는 로직을 가지지 않는 순수한 데이터 객체이다.
- getter/setter 매서드만 가진 클래스를 의미한다.
- Service나 Controller등으로 데이터를 보낼 때 사용한다.
- 즉, 엔티티를 DTO 형태로 변환 후 사용한다.
1) Member라는 Entity가 존재
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder @Entity @EntityListeners(AuditingEntityListener.class) public class Account { @Id @GeneratedValue private Long id; @ManyToOne private AccountUser accountUser; private String accountNumber; @Enumerated(EnumType.STRING) private AccountStatus accountStatus; private Long balance; private LocalDateTime registeredAt; private LocalDateTime unRegisteredAt; @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; }
2) Response를 받을 DTO 클래스
@Getter @Setter @AllArgsConstructor @NoArgsConstructor @Builder public class AccountDto { private Long userId; private String accountNumber; private Long balance; private LocalDateTime registeredAt; private LocalDateTime unRegisteredAt; public static AccountDto fromEntity(Account account){ return AccountDto.builder() .userId(account.getAccountUser().getId()) .accountNumber(account.getAccountNumber()) .balance(account.getBalance()) .registeredAt(account.getRegisteredAt()) .unRegisteredAt(account.getUnRegisteredAt()) .build(); } }
3) Service에 반환
@Transactional public AccountDto createAccount(Long userId, Long initialBanlance){ AccountUser accountUser = accountUserRepository.findById(userId) .orElseThrow(() -> new AccountException(USER_NOT_FOUND)); validateCreateAccount(accountUser); String newAccountNumber = accountRepository.findFirstByOrderByIdDesc() .map(account -> (Integer.parseInt(account.getAccountNumber())) + 1 + "") .orElse("1234567890"); return AccountDto.fromEntity(accountRepository.save( Account.builder() .accountUser(accountUser) .accountStatus(IN_USE) .accountNumber(newAccountNumber) .balance(initialBanlance) .registeredAt(LocalDateTime.now()) .build()) ); }
VO(value Object)
VO는 DTO와 달리 Read-Only속성을 지닌 값 오브젝트로 DTO는 setter를 가지고 있어서 값이 변할 수 있지만 VO의 경우에는 getter만 가지고 있어서 수정이 불가능하다.
VO는 값들에 대해 Read-Only를 보장해줘야 존재의 신뢰성이 확보되지만 DTO의 경우에는 단지 데이터를 담는 그릇의 역할일 뿐 값은 그저 전달되어야 할 대상일 뿐이다.
DTO와 VO 차이
종류 용도 동등 결정 가변 / 불변 로직
DTO - 계층 간 데이터 전달 - 속성값이 모두 같아도 같은 객체가 아닐 수 있음 - setter 존재 시 가변,- setter 비 존재 시 불변 - getter/setter 이외의 로직이 불필요함 VO - 값 자체를 표현 - 속성값이 모두 같으면 같은 객체 - 불변 - getter/setter 이외의 로직을 가질 수 있음 참조
https://dkswnkk.tistory.com/500
https://choitaetae.tistory.com/97
'개발 상식' 카테고리의 다른 글
신입 개발자의 RESTful API 분투기 (0) 2025.07.13