Entity와 Dto, 왜 나누어야 할까?

J_Eddy·2021년 12월 23일
1

인턴십 과정에서 처음 웹 프로젝트를 할 때 모든것이 낯설었지만 그 중에서 기억에 남는것은 EntityDto를 분리 하는것이다. 처음에는 '어차피 데이터에서 뽑아 쓰고 저장하고 업데이트 하고 하는건데 굳이 패키지, 클래스 하나 더 만들어서 해야하나?' 라는 생각을 하였다. 심지어 매번 Dto에서 EntityEntity에서 Dto로 변환하는 과정이 상당히 많았다. 그때의 기억과 느낌이 남아있을 때 기록해 보고자 한다.

📌 Entity?

Entity 란?

Entity란 실제 DB에 매칭되는 클래스를 의미한다. 주로 @Entity, @Getter, @Id, @Column의 어노테이션을 사용하였다. 이 때 특징은 Entity 클래스의 값을 함부로 세팅 할 수 없게 @Setter 어노테이션은 사용하지 않았다.

아래예시코드에서 보이듯이 BuildertoDto를 구현하였다. 매번 생성자를 만들지 않고 바로 사용할수 있도록 Builder를 구현하였고, toDto는 Entity를 호출할 때 거의 매번 쓰여서 따로 만들게 되었다.

@Getter
@Entity
@Table(name="BOARD")
@SequenceGenerator(
        name = "BOARD_SEQ_GEN",
        sequenceName = "BOARD_SEQ",
        initialValue = 1,
        allocationSize = 1
)

public class BoardEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BOARD_SEQ_GEN")
    @Column(name = "BOARD_ID")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "Board_WRITER")
    private MemberEntity writer;

    @Column(name = "TITLE")
    private String title;

    @Column(name = "CONTENT")
    private String content;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
    @Column(name = "CREATEDDATE")
    private LocalDateTime createdDate;
  
   ...

    @ManyToOne
    @JoinColumn(name = "CATEGORY_ID")
    private BoardCategoryEntity category;

    public void setCategory(BoardCategoryEntity category){
        this.category=category;
    }
   
    public BoardDto toDto() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        return BoardDto.builder()
                .id(id)
                .title(title)
                .writer(writer.getNickname())
                .content(content)
                .createdDate(createdDate.format(formatter))
                .updatedDate(updatedDate.format(formatter))
                .hit(hit)
                .price(price)
                .rating(rating)
                .status(status)
                .categoryName(category.getName())
                .categoryId(category.getId())
                .writeIp(writeIp)
                .myLat(myLat)
                .myLng(myLng)
                .alertRead(alertRead)
                .build();
    }
    @Builder
    public BoardEntity(Long id, String title, String content, LocalDateTime createdDate, LocalDateTime updatedDate,int hit, int price, Rating rating, Status status,String writeIp, double myLat, double myLng,int alertRead ) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.createdDate = createdDate;
        this.updatedDate = updatedDate;
        this.hit = hit;
        this.price = price;
        this.rating = rating;
        this.status=status;
        this.writeIp = writeIp;
        this.myLat = myLat;
        this.myLng = myLng;
        this.alertRead = alertRead;
    }
}

📌 Dto?

Dto 란?

Data Transfer Object로 계층간의 데이터 교환을 위한 객체이다. DB에서 데이터를 얻어와서 Service나 Controller 등으로 보낼 때 사용하는 객체 이다. @Getter , @Setter 어노테이션을 사용하여 구성하였다. 아래 예제 코드에서 보이듯이 toEntity를 구현하여 Dto에서 Entity로의 변환이 자유롭도록 설정하였다.
Dto를 주로 View에 뿌려주는 데이터를 담는 용도로 많이 사용하였다.

@Getter
@Setter
@NoArgsConstructor
public class BoardDto {
    private Long id;
    private String writer;
    private String title;
    private String content;
    private String createdDate;
    private String updatedDate;
    private int hit;
    private int price;
    private Rating rating;
    private Status status;
    private String categoryName;
    private Long categoryId;
    private String writeIp;
    private double myLat;
    private double myLng;
    private int alertRead;

    public BoardEntity toEntity() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        return BoardEntity.builder()
                .id(id)
                .title(title)
                .content(content)
                .createdDate(LocalDateTime.parse(createdDate, formatter))
                .updatedDate(LocalDateTime.parse(updatedDate, formatter))
                .hit(hit)
                .price(price)
                .rating(rating)
                .status(status)
                .writeIp(writeIp)
                .myLat(myLat)
                .myLng(myLng)
                .alertRead(alertRead)
                .build();
    }

    @Builder
    public BoardDto(Long id, String writer, String title, String content, String createdDate, String updatedDate, int hit, int price, Rating rating, Status status, String categoryName, Long categoryId, String writeIp, double myLat, double myLng,int alertRead) {
        this.id=id;
        this.writer=writer;
        this.title=title;
        this.content=content;
        this.createdDate=createdDate;
        this.updatedDate=updatedDate;
        this.hit=hit;
        this.price=price;
        this.rating=rating;
        this.status=status;
        this.categoryName=categoryName;
        this.categoryId=categoryId;
        this.writeIp=writeIp;
        this.myLat = myLat;
        this.myLng = myLng;
        this.alertRead = alertRead;
    }
}

📌 Entity, Dto 구분하는 이유?

만약에 Dto가 없이 Entity만 존재한다고 가정하면 DB와 직접적으로 매핑되어있는 Entity가 변경되면 여러 클래스에 영향을 미치게 될것이다.
하지만 Dto가 존재한다면 변경사항을 Entity가 아닌 View와 통신하는 Dto에서 처리하고 마지막 commit단계만 Entity에서 처리되도록 한다면 클래스에 영향이 덜 미칠것이다.

예시

사용자가 어떤 게시물의 내용을 수정한다고 가정해보면 먼저 해당 게시물의 id를 가지고 Repository를 통해 해당게시물의 DB정보를 찾는다.

이때 Repository는 Entity형식으로 리턴한다. 이후 해당 Entity를 toDto를 이용하여 Dto로 변환 후 수정하고 싶은 내용을 반영하여 Dto에 저장한다. 이후 toEntity를 통해 Entity화 시킨 후 save를 한다.

profile
논리적으로 사고하고 해결하는 것을 좋아하는 개발자입니다.

0개의 댓글