그저 내가 되었고

🌱Spring 패키지 구조(Entity, DTO, DAO, Controller, Service, Repository) + DTO를 굳이 사용하는 이유 본문

개발/Spring

🌱Spring 패키지 구조(Entity, DTO, DAO, Controller, Service, Repository) + DTO를 굳이 사용하는 이유

hyuunii 2023. 4. 11. 22:15

Spring 패키지 구조

사실 아주 익숙한 그림인데

저기 각 Layer 사이사이에 DTO가 '진짜로', '왔다갔다하는' 객체라는게 잘 이해가 안됐다.

그러다 어떤 블로그 글에서 관련 내용을 보고 어느정도 정리가 돼서 남겨본다.

 

 

 

 

 

 

Entity란?

Entity 클래스는 실제 DB 테이블과 매핑되는 핵심 클래스로, 데이터베이스의 테이블에 존재하는 컬럼들을 필드로 가지는 객체입니다.

(DB의 테이블과 1:1로 매핑되며, 테이블이 가지지 않는 컬럼을 필드로 가져서는 안됩니다.)

이 Entity 클래스는 다른 클래스를 상속받거나 인터페이스의 구현체여서는 안되고 순수한 데이터 객체인 것이 좋습니다.

 

또한 Entity는 데이터베이스 영속성(persistent)의 목적으로 사용되는 객체이기 때문에 요청(Request)이나 응답(Response) 값을 전달하는 클래스로 사용하는 것은 좋지 않습니다. 

더불어 많은 서비스 클래스와 비즈니스 로직들이 Entity 클래스를 기준으로 동작하기 때문에 Entity 클래스가 변경되면 여러 클래스에 영향을 줄 수 있습니다.

 

@Builder
@Getter
@Entity
@NoArgsConstructor
public class Membmer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long idx;
    private String name;
    private String email;
 
    public Member(Long idx, String name, String email) {
        this.idx = idx;
        this.name = name;
        this.email = email;
    }
}

// 사용 방법
Member member = Member.builder()
        .name("Jan")
        .email("Jan@Jan.com")
        .build();

예컨대 DB의 Member라는 테이블에는

idx, name, email 이외의 필드는 있어서는 안됩니다.

 

스프링에서 JPA를 사용한다면 Entity 클래스에 @Entity 어노테이션을 붙여 해당 클래스가 Entity 클래스임을 명시할 수 있습니다.

또한 id 칼럼에는 @Id 어노테이션을 붙일 수 있고 다른 칼럼에는 @Column 어노테이션을 붙여 다양한 기능을 사용할 수 있습니다.

 

 

 

 

 

 

DTO(Data Transfer Object)란?

DTO는 말 그대로 데이터를 Transfer(이동)하기 위한 객체입니다.

 

Client가 Controller에 요청을 보낼 때도 RequestDto의 형식으로 데이터가 이동하고, Controller가 Client에게 응답을 보낼 때도 ResponseDto의 형태로 데이터를 보냅니다.

 

Controller와 Service, Repository 계층 사이에 데이터가 오갈 때도 데이터는 DTO의 형태로 이동합니다.

 

DTO는 로직을 갖고 있지 않는 순수한 데이터 객체이며, 일반적으로 getter/setter 메서드만을 가집니다.

하지만 DTO는 단순히 데이터를 옮기는 용도이기 때문에 굳이 Setter를 이용해 값을 수정할 필요가 없이, 생성자만을 사용하여 값을 할당하는 게 좋습니다.

 

 

DTO를 사용하는 이유🤔

그런데 데이터를 움직일때 왜 Entity 객체를 그대로 사용하지 않고 굳이 DTO를 사용하는 것일까요?!

 

1. View Layer와 DB Layer의 역할을 분리하기 위해서

➡️ 객체를 표현하기 위한 계층과 객체를 저장하는 계층의 역할을 분리

 

2. Entity 객체의 변경을 피하기 위하여

➡️ Entity 객체를 그대로 사용하면 프로그래머의 의도와 다르게 데이터가 변질될 수 있다(고 함ㅋ..)

 

3. View와 통신하는 DTO 클래스는 자주 변경된다

➡️ View(클라이언트)와 통신하는 DTO 클래스(View Layer), 예를 들어 ResDTO, ReqDTO는 요구사항에 따라 자주 변경된다.

예컨대 어떤 요청에서는 특정 값이 추가될 수도 있고, 특정값이 없을 수도 있다. 

따라서 Entity 클래스와 분리하여 관리해야 한다. 

테이블과 매핑되는 Entity 클래스가 변경되면 여러 클래스에 영향을 끼치기 때문에.

즉 DTO는 Domain Model을 복사한 형태로, 다양한 Presentation Logic을 추가한 정도로 사용하며 Domain Model 객체는 Persistent만을 위해서 사용한다.

 

4. 도메인 모델링을 지키기 위하여

➡️ 도메인 설계를 잘하였다고 하더라도 원하는 데이터를 표시하기가 쉽지 않을 수 있다.

예를 들어 Entity 클래스의 특정 컬럼들을 조합하여 특정 포맷을 출력하고 싶다고 하자.

Entity 클래스에 표현을 위한 필드나 로직이 추가되면 객체 설계를 망가뜨릴 수 있다.

따라서 DTO에 표현을 위한 로직을 추가해서 사용하는 것이 Entity의 도메인 모델링을 지킬 수 있다.

 

 

 

 

 

 

DAO(Data Access Object)란?

DAO는 말 그대로 실제 DB에 접근하는 객체를 뜻합니다.

DAO는 Service와 실제 데이터베이스를 연결하는 역할을 합니다.

즉, DB에서 데이터를 꺼내오거나 넣는 역할을 DAO가 담당하며,

실제로 DB에 접근하여 data를 삽입, 삭제, 조회, 수정 등 CRUD 기능을 수행합니다.

 

JPA의 경우 Repository가 DAO의 역할을 한다고 볼 수 있지만, 둘이 완벽히 같은(===) 것은 아닙니다!

엄밀히 말하면 Repository가 DAO를 대체한다고 보는 것이 맞을 것 같습니다.

DAO와 Repository 모두 DB에 직접 쿼리를 날려 CRUD를 하는 것은 동일하나, 개념적인 측면에서 차이가 있습니다.

 

 

참고 : 영한님의 말씀~!(출처: 인프런 큐엔에이 https://www.inflearn.com/questions/111159/domain%EA%B3%BC-repository-%EC%A7%88%EB%AC%B8)

질문

repository == dao

이렇게 똑같이 봐도 괜찮은 건가요?

 

답변

repository := dao (비슷함)

 

이 둘은 거의 같다고 생각하셔도 무방합니다.

좀 더 깊이있게 차이를 설명하면,

repotiroy는 엔티티 객체를 보관하고 관리하는 저장소이고,

dao는 데이터에 접근하도록 DB접근 관련 로직을 모아둔 객체입니다.

둘다 개념의 차이일뿐 실제로 개발할 때는 비슷하게 사용됩니다.

 

 

 

 

 

 

 

Controller

Controller는 Client의 요청을 DTO의 형태로 받아 Service의 기능을 호출하고,

적절한 응답을 DTO의 형태로 반환하는 역할을 합니다.

즉, 요청과 응답을 관리하는 계층이라고 생각하면 됩니다.

 

 

 

 

 

 

Service

Service 계층은 DTO를 통해 받은 데이터를 이용해 비즈니스 로직을 처리하고,

DAO(혹은 Repository)를 통해 DB에 접근하여 데이터를 관리하는 역할을 합니다.

 

 

 

 

 

 

Repository(DAO)

JPA를 사용하면 Repository를 통해 DB에 실제로 접근할 수 있습니다.

Service와 DB를 연결해주는 역할을 하며, Service 계층에서 Repository를 이용하여 데이터를 관리할 수 있습니다. 

 

 

 

 

 

출처:: https://code-lab1.tistory.com/201