[Java] DAO, DTO, Repository을 이해하자
DAO, DTO, Repository, Entity Class를 이해하기
일반적으로 스프링 프로젝트 파일에 이름을 정할때, DTO, Repository, Entity 등의 이름이 들어가는 것을 알 수 있는데, 좀 더 자세하게 이 정의에 대해서 알고 싶어졌다.
스프링을 사용한 웹앱의 경우 DAO, DTO, Repository, Entity를 사용하여 데이터를 다루며 스프링부트의 경우 내장 톰캣을 통해 서블릿을 관리하고 이를 컨트롤러에서 각 어노테이션을 통해 매핑한다.
Repository
- MVC 패턴에서 모델에 해당하는 부분으로 POJO로는 접근불가능하다.
- Persistence Layer와 1:1 매칭이 가능하다.
- Java Persistenc API 구현체를 통해서 자바 객체에 접근할 수 있다.
@Repository
@RequiredArgsConstructor
public class MemberRepository {
private final EntityManager em;
public void save(Member member) {
em.persist(member);
}
}
해당 코드는 JPA 구현체가 Entity Model 객체를 사용해서 DB에 접근한다.
POJO란.
- 간단하게 설명하자면, "getter / setter를 가진 단순한 자바 오프젝트"이며 의존성이 없고, 테스트도 용이하며 추후 수정이 편리한 오프젝트라고 설명할 수 있을 것 같다/
- 좀 더 자세하게 설명하면 더 복잡해서 POJO에 대한 글은 다음에 따로 정리하겠다.
DAO(Data Access Object)
- 원래 DB의 데이터(필드)와 프로그래밍 언어는 패러다임의 불일치로 인해 사용할 수 없다. 이를 원래 사용할려면 별도의 SQL을 작성해서 SQL을 객체의 필드에 하나씩 매핑하거나 순수한 SQL을 작성하여 사용해야 한다.
Entity
- 하지만 별도의 Entity Class를 사용해서 클래스를 테이블과 1:1 매칭할 수 있다. 이러한 Entity Class를 도메인이라고 하며 가장 DB와 가까운 클래스이다.
@Entity
@Getter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id; // PK
@NotEmpty
@NotNull
private String name;
@Embedded // 내장 타입 임베딩
private Address address;
@JsonIgnore
@OneToMany (mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
다음은 예시 코드이다.
- Entity의 각 필드는 DB 테이블과 1:1매칭되며 PK를 가진다.
- Entity는 순수한 도메인 로직과 비지니스 로직만 가지고 있어야한다.
- Entity는 DB의 데이터를 전달해주고 Service에서 사용할 비즈니스 로직만을 가져야한다.
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
다음 코드는 서비스 계층의 Repository를 사용한 코드이다.
DTO(Data Transfer Object)
- Entity를 통해 DB에서 데이터를 꺼내왔지만 데이터를 접근해야하는 경우 문제가 있다.
- Controller와 Presentation Layer는 클라이언트와 직접 만나며, Entity는 프레젠테이션 계층과 완전히 분리되어야 한다.
- 이러한 경우에 DTO를 사용한다.
@Data
@AllArgsConstructor
static class MemberDto {
private String name;
private Address address;
}
이러한 경우 다음과 같이 DTO를 사용한다.
특징은 다음과 같다.
- Getter/Setter가 없다.
- Wrapping 된 순수한 데이터 객체
- Entity에 직접 접근하지 않으므로, Entity 변경시, DTO만 변경하면 된다.
결론.
정리하자면 스프링 프로젝트는 다음과 같은 구조를 가진다.
구성은 다음 4개와 같다.
Domain(Entity)
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
- DB 테이블과 1:1 매칭된다.
Repository(DAO)
@Repository
@RequiredArgsConstructor
public class MemberRepository{
private final EntityManager em;
- Entity를 통해 데이터를 DB에 저장된다.
- 엔티티는 DB의 데이터와 매칭되는 것
- 실제 DB에 데이터를 저장하는 건 Repository 클래스의 Entity Manager를 통해 이루어진다
Service
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
- 프레젠테이션(뷰)에서 엔티티에 직접 접근하지않고 비즈니스 로직을 처리할 수 있도록하는 계층이다.
- Repository에 정의된 비즈니스 로직을 처리하거나 엔티티에 접근한다.
Controller
@RestController // Response + Request
@RequiredArgsConstructor
public class MemberApiController {
private final MemberService memberService;
@GetMapping("api/v1/members")
public Result<List<MemberDto>> memberV2() {
- 프레젠테이션 계층으로 클라이언트의 요청을 처리한다.
- 엔티티는 서비스에 의해 추상화되어 직접 접근 불가능하다.
- 서비스에 정의된 비즈니스 로직을 호출한다.
- ResponseBody에 데이터를 담아 반환해준다
출처