네로개발일기

개발자 네로의 개발 일기, 자바를 좋아합니다 !

'2022/04/06'에 해당되는 글 1건


반응형

개발을 하다보면 API의 요청이나 응답을 처리할 때 또는 다른 계층으로 넘기는 파라미터가 너무 많은 시점에 별도의 DTO를 생성하는 것이 좋습니다.

 

[엔티티(Entity) 또는 도메인 객체(Domain Object)와 DTO를 분리해야 하는 이유]

1) 관심사의 분리

2) Validation 로직 및 불필요한 코드 등과의 분리

3) API 스펙과의 분리

4) API 스펙의 파악이 용이

 

1. 관심사의 분리

엔티티와 DTO를 분리해야 하는 가장 근본적인 이유는 관심사가 서로 다르기 때문이다. 관심사의 분리(separation of concerns, SoC)는 소프트웨어 분야의 오래된 원칙 중 하나로서, 서로 다른 관심사들을 분리하여 변경 가능성을 최소화하고, 유연하며 확장가능한 클린 아키텍처를 구축하도록 도와준다.

DTO(Data Transfer Object)의 핵심 관심사는 이름 그대로 데이터의 전달이다. DTO는 데이터를 담고, 다른 계층(Layer) 또는 다른 컴포넌트들로 데이터를 넘겨주기 위한 자료구조(Data Structure)이다. 그러므로 어떠한 기능 및 동작도 없어야 한다.

반면에 엔티티는 핵심 비즈니스 로직을 담는 비즈니스 도메인 영역의 일부이다. 그러므로 엔티티 또는 도메인 객체는 그에 따른 비즈니스 로직이 추가될 수 있다. 엔티티 또는 도메인 객체는 다른 계층이나 컴포넌트 사이에서 전달을 위해 사용되는 객체가 아니다.

엔티티와 DTO는 엄연히 서로 다른 관심사를 가지고 있고, 그렇기 때문에 분리하는 것이 합리적이다.

 

2. Validation 로직 및 불필요한 코드 등과의 분리

Spring 에서는 요청에 대한 데이터를 검증하기 위해 @Valid 어노테이션을 지원하고 있다.

@Valid 처리를 위해서는 @NotNull, @NotEmpty, @Size 등과 같은 유효성 검증 어노테이션들을 변수에 붙여주어야 한다. 반면에 JPA도 변수에 @Id, @Column 등과 같은 어노테이션을 활용해 객체와 관계형 데이터베이스를 매핑해주는데, DTO와 엔티티를 분리하지 않는다면 엔티티의 코드가 상당히 복잡해진다. 

또한, 엔티티 클래스의 생성일자, 수정일자를 나타내는 변수들은 API 요청이나 응답에서는 필요가 없다. 그렇기 때문에 응답에서 해당 변수를 제거하기 위해서는 @JsonIgnore 등과 같은 또 다른 어노테이션을 통해 별도의 작업이 필요할 수도 있다.

이렇게 엔티티 클래스를 사용하게 되면 핵심 비즈니스 도메인 코드들이 아닌 요청/응답을 위한 값, 유효성 검증을 위한 코드 등이 추가되면서 엔티티 클래스가 지나치게 비대해질 것이고, 확장 및 유지보수 등에서 매우 어려움을 겪게 될 것이다. 

그러므로 이러한 경우에는 별도의 DTO를 생성해서 엔티티로부터 분리하는 것이 바람직할 것이다.

 

3. API 스펙의 유지

@Entity 
@Table 
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Membership {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false)
    private Long id;
    
    @Enumerated(EnumType.STRING)
    private MembershipType membershipType; 
    
    @Column(nullable = false) 
    private String userId;
    
    @Setter 
    @Column(nullable = false) 
    @ColumnDefault("0") 
    private Integer point;
}
{ 
    "id" : "15", 
    "membershipType" : "NAVER", 
    "userId" : "NC10523", 
    "point" : "10000" 
}

내부 정책 변경으로 userId를 memberId로 변경해야 하는 상황이다. DTO를 사용하지 않는다면 userId가 memberId로 바꿈에 따라 API 스펙이 변경되고, API를 사용하던 사용자들은 모두 장애를 겪게 될 것이다. 물론 @JsonProperty를 이용해 반환되는 값의 이름을 변경할 수 있지만, 이는 결국 Entity를 무겁게 만들어 근본적인 해결책이 될 수 없다.
스펙이 변경되어 테이블에 컬럼이 추가되는 경우도 마찬가지이다. 테이블에 새로운 컬럼이 추가되면 엔티티에 새로운 변수가 추가될 것이고, 별도로 처리를 하지 않는 이상 API 스펙이 변경되는 것이다.

이러한 상황을 위해 DTO를 이용해 분리하여 독립성을 높임으로써 변경이 전파되는 것을 방지해야 한다. 만약 우리가 응답을 위한 DTO 클래스를 활용하고 있으면, Entity 클래스의 변수가 변경되어도 API 스펙이 변경되지 않으므로 안정성을 확보할 수 있다.

 

4. API 스펙의 파악 용이

DTO를 사용함으로써 얻는 또 다른 장점은 DTO를 통해 API 스펙을 어느정도 파악할 수 있다는 점이다. API 문서의 요약본을 작성하는 것과 유사한 효과를 얻을 수 있으며, 특히 요즘같은 MSA 아키텍처로 개발을 많이 하는 상황에서 다른 사람이 작성한 API 호출 코드를 파악할 때 요청/응답을 손쉽게 파악할 수 있어 용이하다.

 

출처

https://mangkyu.tistory.com/192

 

[Spring] 엔티티(Entity) 또는 도메인 객체(Domain Object)와 DTO를 분리해야 하는 이유

개발을 하다 보면 API의 요청이나 응답을 처리할 때 또는 다른 계청으로 넘기는 파라미터가 너무 많은 시점에 별도의 DTO를 생성해야 하나 고민을 하는 시점이 생깁니다. 개인적으로는 간단한 애

mangkyu.tistory.com

 

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !