개발/개발노트

[JPA] DTO와 Entity를 분리하는 이유

Gamii 2024. 1. 26. 07:37
728x90

 

 

 

 

Spring boot +JPA 프로젝트를 하면서 DTO와 Entity를 구별해서 사용했다. 단순히 DB에서 select 한 데이터가 반환될 때, 원하는 형식에 맞춰서 넣을 수 있게 DTO를 사용한다고 알고 있었다. 하지만, '단순한 select를 할 때는 DTO를 따로 만들지 않고 Entity를 사용해도 되지 않을까?' 라는 궁금증에 DTO와 Entity를 분리하는 이유에 대해 정리해보려고 한다.

 

 

 


 

DTO란?

DTO(Data Transfer Object)는  계층(Controller, View, Business Layer) 간 데이터 교환을 위한 Java Bean을 의미한다. DTO는 비즈니스 로직을 가지지 않고, setter, getter메서드만 가진 클래스이다. 주로 View와 서버(Controller, Service) 사이에서 DTO를 활용한다.

 

 

더보기

Java Bean이란?

 

Java Bean은 DTO, VO와 같은 특정 형태의 클래스를 가르키는 뜻으로 사용된다.

필드는 private로 구성되어 getter와 setter를 통해서 접근이 가능하다. 그리고 전달 인자(no-argument) 없는 생성자(기본 생성자)를 가지고 있어야 한다.

 

 

* 아래 [가변 객체 DTO] 예시를 참고하면 이해하기 쉽다.

 

 

 

DTO는 구현하는 방식에 따라 가변 객체, 불변 객체로 사용할 수 있다.

 

 

[가변 객체 DTO]

기본 생성자로 생성 후 setter를 통해 가변적으로 값을 변경한다.

 

//getter, setter
@Setter
@Getter
public class UserInfoDTO {
    
    //필드는 private로 선언
    private long userId;
    private String userNm;
    private String passwd;
    
    //전달 인자가 없는(no-argument) 생성자
    public UserInfoDTO(){
    }
}

 

 

 

[불변 객체 DTO]

생성자를 이용해서 구현할 경우, 변하지 않고 오직 getter를 통해서 사용이 가능하다.

 

@Getter
public class UserInfoDto {
    private final long userId;
    private final String userNm;
    
    public UserInfoDto(long userId, String userNm) {
    	this.userId = userId;
        this.userNm = userNm;
    }
}

 

 

 

 

 

Entity란?

Entity는 실제 DB 테이블과 1:1 매핑되는 클래스이다. DB 테이블내에 존재하는 컬럼만 필드로 가져야 한다. Entity 클래스는 상속받거나 구현체여서는 안 되며, 테이블 내에 존재하지 않는 컬럼을 가져서도 안된다.

 

 

@Entity
@Table(name="user_info")
@Setter
public class UserInfo() {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long userId;
    
    private String userNm;
    
    private String passwd;
    
    @ManyToOne
    @JoinColumn(name="category_id")
    private Category category_id;
}

 

 

 

DB와 매핑되는 클래스이다 보니, 최대한 외부에서 Entity 클래스의 필드에 직접적으로 접근하지 않도록 해야한다. (Entity가 외부에 노출이 안되도록 하기 위해서다.) Entity를 변경하게 된다면 DB와 다른 클래스에 영향을 끼친다.

 

 

 


 

 

Q. Entity와 DTO를 분리하는 이유는 뭘까?

 

1) Entity를 View에 노출시키지 않는다.

 

- DTO를 사용하지 않고 Entity를 사용해 View로 보낼 경우, 테이블 설계를 그대로 노출되므로 보안상 좋지 않다.

 

- Entity를 View에 사용하면, 화면에 필요없는 필드까지 노출이 되므로 필요한 데이터로만 구성된 DTO를 사용하는 게 좋다. 만약 View에서 필요한 데이터가 변경이 됐을 경우에도, Entity를 변경하는 것이 아니라 DTO만 변경하면 된다. DB와 다른 클래스에 영향을 끼지치 않기 때문이다.

 

 

2) validation 코드와 모델링 코드를 분리할 수 있다.

-  Entity에는 DB의 테이블과 매칭되는 필드가 속성으로 선언되어 있고, 복잡한 비즈니스 로직이 작성되어 있는 곳이다. @Column, @JoinColumn, @ManyToOne, @OneToOne 등의 모델링을 위한 코드를 볼 수 있다.

 

- @NotNull, @NotEmpty, @NotBlank 등과 같은 요청에 대한 값에 대한 validation 코드가 들어간다면 Entity는 더 복잡해지고 그만큼 가독성은 낮아진다. 이때, 필요한 validation을 DTO에 정의하면, Entity는 모델링과 비즈니스 로직에 집중되도록 만들 수 있다.

 

 

 

 


 

[참고]

 

https://velog.io/@0sunset0/Dto%EC%99%80-Entity%EB%A5%BC-%EB%B6%84%EB%A6%AC%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EB%B6%84%EB%A6%AC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

 

📚 Dto와 Entity를 분리하는 이유, 분리하는 방법

작년에 프로젝트를 하면서 entity를 view에 그대로 반환했다가 Dto로 변환해야겠다는 생각이 들어서 바꿨었는데, Entity와 dto에 대한 내용을 블로그에 정리하면 좋을 거 같아 글을 쓰게 되었다. (일기

velog.io