
1. DAO, DTO, VO란?
1.1 DAO (Data Access Object)
DAO는 데이터베이스와 직접적으로 상호작용하는 객체로, 데이터베이스의 CRUD(Create, Read, Update, Delete) 작업을 수행합니다. DAO는 주로 SQL 쿼리를 실행하고 결과를 반환하는 역할을 합니다.
특징:
- 데이터베이스와 직접적인 연결을 담당
- SQL을 실행하여 데이터를 조회하거나 저장
- 서비스 레이어에서 호출되어 데이터를 주고받음
- 일반적으로 인터페이스와 구현 클래스로 분리하여 사용
DAO 예제 (Spring Boot + MyBatis)
@Mapper
public interface UserDAO {
@Select("SELECT * FROM users WHERE id = #{id}")
UserVO getUserById(int id);
@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertUser(UserVO user);
}
1.2 DTO (Data Transfer Object)
DTO는 계층 간 데이터 전송을 위한 객체로, 보통 컨트롤러에서 서비스 레이어로 데이터를 전달할 때 사용됩니다. DTO는 비즈니스 로직을 가지지 않으며, 단순히 데이터를 담는 용도로 사용됩니다.
특징:
- 계층 간 데이터 전달 목적
- 일반적으로 getter, setter 또는 빌더 패턴을 활용
- JSON 직렬화/역직렬화에 적합
- 불필요한 데이터를 제거하여 필요한 데이터만 전송
public class UserDTO {
private String name;
private String email;
public UserDTO() {}
public UserDTO(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
컨트롤러에서 DTO를 사용하는 예제
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/create")
public ResponseEntity<String> createUser(@RequestBody UserDTO userDTO) {
userService.createUser(userDTO);
return ResponseEntity.ok("User created successfully");
}
}
1.3 VO (Value Object)
VO는 특정 도메인 내에서 변하지 않는(Immutable) 데이터를 표현하는 객체입니다. DTO와 달리 불변성을 유지하며, 객체의 값이 한 번 설정되면 변경되지 않습니다.
특징:
- 읽기 전용(Immutable) 객체로 사용
- 값 기반 비교(equals(), hashCode() 재정의 필요)
- 주로 DB에서 조회한 값을 담는 용도로 사용됨
public class UserVO {
private final int id;
private final String name;
private final String email;
public UserVO(int id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public int getId() { return id; }
public String getName() { return name; }
public String getEmail() { return email; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserVO userVO = (UserVO) o;
return id == userVO.id && Objects.equals(name, userVO.name) && Objects.equals(email, userVO.email);
}
@Override
public int hashCode() {
return Objects.hash(id, name, email);
}
}
2. DAO, DTO, VO의 차이점
구분 | DAO | DTO | VO |
역할 | 데이터베이스와 직접 연결하여 데이터를 CRUD 수행 | 데이터를 계층 간 전송할 때 사용 | 불변 객체로 데이터를 보관하는 용도 |
변할 수 있는가? | 변경 가능 (데이터베이스 변경 가능) | 변경 가능 (getter, setter 제공) | 변경 불가능 (Immutable) |
주요 용도 | 데이터베이스 접근 | API 또는 서비스 계층 간 데이터 전송 | 읽기 전용 도메인 객체 |
3. DAO, DTO, VO를 함께 사용
@Service
public class UserService {
private final UserDAO userDAO;
public UserService(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void createUser(UserDTO userDTO) {
UserVO userVO = new UserVO(0, userDTO.getName(), userDTO.getEmail());
userDAO.insertUser(userVO);
}
public UserDTO getUserById(int id) {
UserVO userVO = userDAO.getUserById(id);
return new UserDTO(userVO.getName(), userVO.getEmail());
}
}
실행 흐름
- 클라이언트가 POST /users/create 요청을 보냄 (JSON 데이터 포함)
- UserController에서 DTO로 데이터를 받고 UserService로 전달
- UserService는 DTO를 VO로 변환한 후 UserDAO를 호출하여 DB에 저장
- DB에서 조회할 때는 UserDAO가 VO를 반환하고, UserService가 이를 DTO로 변환하여 컨트롤러에 전달

- DAO: 데이터베이스와 직접 연결하여 CRUD 수행
- DTO: 데이터 전송을 위한 객체 (계층 간 이동)
- VO: 불변 객체로, 읽기 전용 데이터를 표현할 때 사용
'Back_End > JAVA' 카테고리의 다른 글
자바(JAVA) Arrays.sort() vs Collections.sort() (0) | 2025.03.11 |
---|---|
자바(JAVA)의 Default Interface란? (1) | 2025.02.28 |
자바(JAVA) Synchronized (0) | 2025.02.24 |
자바(Java) Optional 이란? (0) | 2025.02.14 |
얼리 리턴 패턴(Early Return Pattern) 이란? (0) | 2025.02.14 |