[Spring] DAO, DTO, VO란? 각각의 개념에 대해 알아보자.

DAO(Data Access Object)

"실제로 DB의 데이터에 접근하는 객체"

DAO는 Service와 DB를 연결하는 역할을 하며, 실제로 DB에 접근하여 data를 삽입, 삭제, 조회, 수정 등 CRUD 기능을 수행합니다.

JPA에서는 DB에 데이터를 CRUD 하는 JpaRepository<>를 상속받는 Repository 객체들이 DAO라고 볼 수 있습니다.

public interface itemRepository extends JpaRepository<Item, Long> {
}

DTO(Data Transfer Object)

"계층 간 데이터 교환을 위한 객체"

로직을 가지지 않고 getter/setter 메소드만 가진 순수한 데이터 객체 클래스(Java Beans)로

DB에서 데이터를 얻어 Service나 Controller 등으로 보낼 때 사용합니다.

 

스프링에서 DTO의 개념을 설명하면 다음과 같습니다.

Item Entity
@Data
@Entity
public class Item {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id;

    @Column(name = "item_name")
    private String itemName;

    @Column(name = "item_name")
    private Integer price;
    
    @Column(name = "item_name")
    private Integer quantity;

    public Item() {} // JPA는 public, protected의 기본 생성자가 필수 !

    public Item(String itemName, Integer price, Integer quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }
}

 

ItemUpdateDto
@Getter
@Setter
public class ItemUpdateDto {
    private String itemName;
    private Integer price;
    private Integer quantity;

    public ItemUpdateDto() {
    }

    public ItemUpdateDto(String itemName, Integer price, Integer quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }
}

 

ItemService
@Service
@RequiredArgsConstructor
@Transactional
public class ItemService {
    private final ItemRepository itemRepository;

    public Item save(Item item) {
        return itemRepository.save(item);
    }

    @Override
    public void update(Long itemId, ItemUpdateDto updateParam) {
        Item findItem = itemRepository.findById(itemId).orElseThrow();
        findItem.setItemName(updateParam.getItemName());
        findItem.setPrice(updateParam.getPrice());
        findItem.setQuantity(updateParam.getQuantity());
        // 변경 쿼리를 날리지 않아도됨.
        // 트랜잭션이 커밋되는 시점에 데이터가 변경되었으면 데이터들의 업데이트 쿼리를 만들어 DB에 알아서 날려줌.
    }
}

 

ItemController
@Controller
@RequestMapping("/items")
@RequiredArgsConstructor
public class ItemController {

    private final ItemService itemService;
	
    ...
    생략
    ...
    
    @GetMapping("/{itemId}/edit")
    public String editForm(@PathVariable Long itemId, Model model) {
        Item item = itemService.findById(itemId).get();
        model.addAttribute("item", item);
        return "editForm";
    }


    @PostMapping("/{itemId}/edit")
    public String edit(@PathVariable Long itemId, @ModelAttribute ItemUpdateDto updateParam) {
        itemService.update(itemId, updateParam);
        return "redirect:/items/{itemId}";
    }
}

 

위 코드들을 보면

객체의 값을 변경 할 시에, ItemService에서 DB에서 Item 엔티티의 값을 받아 form 데이터로 받은 파라미터 값으로 Item 엔티티의 값을 변경하는 것을 볼 수 있습니다.


VO(value Object)

"변경 불가능하며 오직 읽기만 가능 (Read-Only)"

DTO는 setter를 가지고 있어 값을 변경할 수 있지만, VO는 getter만을 가지기 때문에 읽기만 가능하고 수정은 불가능 합니다.

 

DTO와 VO의 차이점

DTO는 인스턴스 개념이고, VO는 리터럴 값(변하지 않는 데이터) 개념입니다.

DTO는 단지 데이터를 담아 전달하는 역할만 하지만, VO는 값들에 대해 읽기만 가능한 Read-Only 속성을 가져 객체로서 데이터 그 자체에 의미를 갖습니다.