어제보다 한걸음 더

Spring Boot - DTO, VO, DAO, Repository, Entity, Domain 란? 본문

Spring

Spring Boot - DTO, VO, DAO, Repository, Entity, Domain 란?

지안22 2023. 4. 24. 16:58

스프링 부트를 사용해서 프로젝트를 만들다가, 각 용어들에 대한 개념 정리의 필요성을 느꼈다.

 

 

DTO vs VO

DTO (Data Transfer Object)

- 계층간 데이터 교환을 위해 임시적으로 담아놓는 바구니 역할을 하는 객체를 의미한다.

VO (Value Object)

- DTO와 VO는 거의 같은 개념이라고 볼 수 있다.

- VO는 Read Only이다. (setter를 사용하지 않는다)

- DTO와 달리, 로직을 포함할 수 있고, 값 비교를 위해서 hashcode(), equals() 메서드를 오버라이딩 해줘야 한다.

- Builder Pattern을 사용한다.

 

🌟 DAO vs Repository

- 데이터 액세스 계층(Data Access Layer)에서 데이터 처리를 위해 존재.

- Service와 DB를 연결해 주는 중간 다리 역할.

- 목적과 구현 방법에 차이가 있다.

- DAO, Repository 에 대한 구분은 관점에 따라 다양하게 나뉠 수 있어 논쟁의 요소이다.

DAO (Data Access Object)

- 매핑 레벨이 SQL 수준이다. (영속성)

- 퍼시스턴트 레이어에 대한 추상화

- 데이터 액세스 계층과 비즈니스 로직 계층 사이의 인터페이스를 정의한다.

- 일반적으로 JDBC(Java DataBase Conectivity)를 사용해서 데이터베이스와 통신한다.

- 데이터 엑세스 계층과 비즈니스 로직 계층 간의 결합도를 낮춘다.

- 서비스 레이어와 리포지토리의 중간 계층을 구성하는 역할로 쓰이는 경우도 있다.

- Spring Framework, Spring MVC 사용자는 repository라는 개념을 사용하지 않고, DAO객체로 데이터베이스에 접근한다.

Repository

- 매핑 레벨이 객체 수준이다.

- 도메인 레이어에 객체 컬렉션의 추상화

- DAO를 여러 개 선언해서 사용 가능하다.

- 도메인 모델에서 데이터를 가져오고 저장하는 데 사용된다.

- 특정 데이터베이스와 밀접하게 연관되어 있다.

- 일반적으로 ORM(Object-Relational Mapping) 프레임워크를 사용해서 데이터베이스와 통신한다. (중개자 역할)

- 도메인 모델의 변경사항을 처리하는데 중요한 역할을 한다.

Spring Data JPA 에서 제공하는 기능.

🌟 Entity vs Domain

Domain

- 비즈니스 로직.

- 개발 대상과 범위.

- 해결하고자 하는 문제 영역.

- Entity 객체를 기반으로 비즈니스 규칙을 구현하고 상호작용하는 데 사용한다.

Domain Model

- 도메인 레이어의 결과.

- 도메인을 모든 사람(기획자, 다른 개발자 등)이 동일한 관점에서 이해할 수 있도록 단순화시킨 것.

- UML 다이어그램으로 표현할 수 있다.

Entity

- 개체

- 객체(Object)의 데이터 버전이라고 볼 수 있다. (정보를 표현하는 단위)

- DB에서 테이블과 매핑되는 객체를 의미. (영속성)

- 이 클래스의 필드(속성)는 테이블 내부의 칼럼(Column)과 동일하다.

- 비즈니스 영역을 캡슐화한 영역이라 볼 수 있다.

- Entity는 Domain의 일부분으로 볼 수 있다.

 

DTO vs Entity

- DTO는 Entity와 비슷한 Field를 가질 수는 있지만, Service에서 추가, 삭제가 이루어질 수 있다.

 

영속성

- 데이터를 생성한 프로그램이 종료되더라도 사라지지 않는 데이터의 특성을 의미한다.

비즈니스 로직

- 소프트웨어 시스템에서 업무 처리를 위해 필요한 규칙과 절차를 의미.

- 도메인 영역의 비즈니스 규칙, 정책, 프로세스 등을 포함하며, 이를 구현한 코드이다.

 

 

코드 예시

form.html ➡️ Client

<!-- 생략 -->
<form method="post" action="/users/create">
  <label for="userId>사용자 아이디</label>
  <input name="userId">
  <label for="password>비밀번호</label>
  <input type="password" name="password">
  <button type="submit">회원가입</button>
</form>
<!-- 생략 -->

 

UserForm.java ➡️ DTO

public class UserForm {
    private String userId;
    private String password;  
    // 생성자, getter, setter 생략
}

 

User.java ➡️ Entity

public class User {

    private Long customerId; // 회원번호
    private String userId; // 아이디
    private String password; // 비밀번호 
    // 생성자, getter, setter 생략
}

 

UserController.java ➡️ Controller

// import 생략
@Controller
public class UserController {
  // UserService 필드, 생성자 주입 생략
    @GetMapping("/users/create")
    public String create(){ return "user/form";}
    
    @PostMapping("/users/create")
    public String create(UserForm form){
        userService.join(form);
        return "redirect:/users";
    }
}

 

UserService.java ➡️ Service

// import 생략
@Service
public class UserService {
    // UserRepository 필드 생성자 주입 생략
    public String join(UserForm form){
        User user = new User(form);
        // 검증 생략
        return userRepository.save(user).getUserId();
    }

 

JdbcUserRepository.java ➡️ Repository

// import 생략
@Repository
public class JdbcUserRepository implements UserRepository{
    // JdbcTemplate 생성자 주입 생략
    @Override
    public User save(User user) {
        SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
        jdbcInsert.withTableName("user").usingGeneratedKeyColumns("customer_id");

        Map<String, Object> parameters = new ConcurrentHashMap<>();
        parameters.put("user_id", user.getUserId());
        parameters.put("password", user.getPassword());

        Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
        user.setCustomerId(key.longValue());
        return user;
    }
}

 

schema.sql ➡️ DB Table

create table user
(
    customer_id bigint not null auto_increment,
    user_id varchar(16) not null,
    password varchar(32) not null,
    primary key (customer_id)
);

 

 

 

간단히 공부해보고 느낀점

각 개념들을 깊숙하게 이해하려면 JPA, ORM, Spring Data JPA 등에 대해서도 공부해야 할 것 같다.

 

 

본 게시글은 하단의 참고 자료를 보고 스스로의 생각을 정리한 글입니다.
잘못된 부분을 발견하게 된다면 알려 주시면 감사하겠습니다! 🙇🏻‍♀️

 

참고 자료

 

https://www.baeldung.com/java-dao-vs-repository

 

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/

 

Spring Data JPA - Reference Documentation

Example 119. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

https://velog.io/@yeahg_dev/Domain%EA%B3%BC-Entity%EC%9D%98-%EA%B0%9C%EB%85%90\

 

Domain과 Entity의 개념

Domain, Entity + layered architecture에 대해 공부해보자미~

velog.io

https://tecoble.techcourse.co.kr/post/2021-05-16-dto-vs-vo-vs-entity/

 

DTO vs VO vs Entity

DTO와 VO는 분명히 다른 개념이다. 그런데, 같은 개념으로 생각해서 사용하는 경우가 많다. 왜일까? ⌜Core J2EE Patterns: Best Practices and Design Strategies⌟ 책의 초판에서는 데이터 전송용 객체를 로 정의

tecoble.techcourse.co.kr

https://yong0810.tistory.com/57

 

[Java, Spring Boot] DTO, DAO, Repository, Domain(Entity)

스프링부트를 사용하다 보면, DTO, DAO, Repository, Domain, Entity, 등 다양한 용어를 접할 수 있다. 그리고 이 용어들에 대해서 공부하다보면 각 용어가 점점 헷갈려진다.. 이번 게시글에서는 이 용어들

yong0810.tistory.com

https://www.youtube.com/watch?v=4Pvd0KrTfvE&t=973s 

https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/

 

JPA, Hibernate, 그리고 Spring Data JPA의 차이점

개요 Spring 프레임워크는 어플리케이션을 개발할 때 필요한 수많은 강력하고 편리한 기능을 제공해준다. 하지만 많은 기술이 존재하는 만큼 Spring 프레임워크를 처음 사용하는 사람이 Spring 프레

suhwan.dev