자바 스프링 계열 웹개발을 하다보면 필연적으로 보게되는 단어이다. 과연 이 셋이 뭐길래 항상 등장하는 것일까? 이를 논하기 위해서는 Database(이하 DB) 와 Framework(이하 FW) 의 존재 목적과 패러다임부터 논해야 할 것이다. 이는 다른 포스팅에서 좀 더 깊게 다루도록 하고 오늘은 Mysql(DB) 와 Spring(FW) 의 차이를 느꼈다고 가정하고 이 둘 사이의 컨버팅을 더 자유롭게 해주는 DAO / DTO / VO 의 개념에 대해서 이야기하고자 한다.
DAO / DTO / VO 의 공통점
많은 글을 읽었지만 이 셋의 차이에 대해서는 설명을 하는 반면 셋의 공통점에 대해서는 이야기하지 않았다. 내가 생각하는 이 세 개념의 공통점은 DB와 FW의 차이점을 보완해주는 컨버터라고 느껴졌다. DB는 정보를 저장하기 위해 존재한다. FW는 개발의 생산성을 증진시키기 위해 많은 내장 기능을 내재한다. 두 개념의 목적 자체가 다르기 때문에 저장되는 데이터의 형태가 다르다.
Spring data JPA 공식문서의 기본 구조
#공식문서 본문
package com.example.accessingdatajpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
protected Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format(
"Customer[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
#공식문서 본문
package com.example.accessingdatajpa;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
Customer findById(long id);
}
#공식문서 본문
package com.example.accessingdatajpa;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class AccessingDataJpaApplication {
private static final Logger log = LoggerFactory.getLogger(AccessingDataJpaApplication.class);
public static void main(String[] args) {
SpringApplication.run(AccessingDataJpaApplication.class);
}
@Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a few customers
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
repository.save(new Customer("Kim", "Bauer"));
repository.save(new Customer("David", "Palmer"));
repository.save(new Customer("Michelle", "Dessler"));
// fetch all customers
log.info("Customers found with findAll():");
log.info("-------------------------------");
for (Customer customer : repository.findAll()) {
log.info(customer.toString());
}
log.info("");
// fetch an individual customer by ID
Customer customer = repository.findById(1L);
log.info("Customer found with findById(1L):");
log.info("--------------------------------");
log.info(customer.toString());
log.info("");
// fetch customers by last name
log.info("Customer found with findByLastName('Bauer'):");
log.info("--------------------------------------------");
repository.findByLastName("Bauer").forEach(bauer -> {
log.info(bauer.toString());
});
// for (Customer bauer : repository.findByLastName("Bauer")) {
// log.info(bauer.toString());
// }
log.info("");
};
}
}
DAO?
Data Access Object의 약자이다. 말그대로 FW에서 DB에 쉽게 접근하기 위해 만들어둔 객체이다. 위 예제에서는 Customer 2단계에 나오는 CrudRepository를 확장하는 CustomerRepository를 의미한다. 개인적으로는 데이터 접근에서 가장 핵심적인 부분이라고 생각하지만 그것을 대신해주는 것이 ORM이기 때문에 보통 ORM에서 모두 제공한다. 따라서 우리는 손쉽게 선배님들이 만든 공식문서를 보며 그대로 따라하면 된다.
DTO?
Data Transfer Object의 약자이다. DAO가 데이터를 직접적으로 DB에 넣어주는 역할이었다면, DTO는 좀더 프레임워크에서 손쉽게 쓸 수 있는 형태로 만들어놓은 데이터 원형이라고 이해했다. 위 예제에서는 1단계에서 Customer의 테이블 모습을 꾸며주는 단계이며 이것을 자바에서 바로 접근하기 위해 @getter, @setter를 활용해준다.
VO?
Value Object의 약자라고 한다. 정확하게는 이해하지 못했지만 DTO에서 @Setter 기능만 빠진, get메서드로 값을 불러만 올 수 있는 데이터 형태(Read-Only)라고 이해했다. DB에 무언가 실험을 한다거나 중요한 데이터를 다룰때 사용하면 좋을 것 같다.
3줄 요약
어쩌다보니 'JPA 공식문서 같이 읽기' 코너가 되었는데 요약하자면 다음과 같다.