보통 JPA에서 새로운 객체를 저장한다고 할때, dto를 entity로 변환할 것이다.
그런데 , dto를 entity로 변환하는 코드는 어디에 두는게좋을까?
보통 Controller, Service, Repository 3계층으로 나누어 사용하고 Entity생성은 Builder로 생성한다고 가정해보자.
1. DTO에서 생성
@ApiModel(value = "쿠폰 등록")
@Data
public static class CupnRegistration {
@ApiModelProperty
private String cupnIssuSe;
@ApiModelProperty
private Long cupnSplrSn;
....
public Cupn toCupn(){
return Cupn.builder()
.cupnIssuSe(cupnIssuSe)
.cupnSplrId(cupnSplrSn)
...
.build();
}
1. 매개변수가 없기때문에 어떤것에도 의존하지 않는다.
2. DTO가 변경될시 클래스내에서만 변경한다.
3. 엔티티가 변경될시 해당 필드를 변경해야한다.
2.서비스단에서 생성
@Transactional
public void registCupn( CupnRequest.CupnRegistration request){
...
Cupn cupn = registTest(request);
...
}
대충 위와같이 쿠폰생성로직 내에 아래와 같이 쿠폰을 직접 생성하는 메서드가 들어갈것이다.
public Cupn registTest(CupnRequest.CupnRegistration request){
return Cupn.builder()
.cupnIssuSe(request.getCupnIssuSe())
.cupnSplrId(request.getCupnSplrSn())
...
.build();
}
1. Service에서 DTO를 의존한다.
2. DTO변경시 DTO와 Service클래스 모두 코드변경이 일어난다.
3. Entity변경시 해당 필드값을 변경해야한다.
3. Entity에서 직접 변경
@Entity
public class Cupn{
@Column
private String cupnIssuSe;
@Column
private Long cupnSplrSn;
...
public static Cupn of(CupnRequest.CupnRegistration registration, String cupnId){
return Cupn.builder()
.cupnId(cupnId)
.cupnIssuSe(registration.getCupnIssuSe())
.cupnSplrId(registration.getCupnSplrSn())
...
.build();
}
}
1. 엔티티에서 DTO를 의존하고 있다.
2. DTO필드 변경시 DTO클래스와 Entity클래스의 코드 변경이 발생한다.
3. 엔티티 변경시 클래스 내에서만 변경한다.
그래서 내생각은
1.당연하게도 DTO는 안전한 데이터 전달의 목적과 동시에 Entity로 변환하려는 궁극적인 목표가 있다.
따라서 Entity의 변환에 들어갈 모든 값이 DTO내부에 있기에 다른곳에 의존할 필요가없다.
2.DTO와 Entity중 더욱 가볍게 변경될수 있는건 DTO이기에 DTO변경에 따른 책임과 역할을 모두 DTO가 쥐고 있는게 좋다고 생각한다. 즉, DTO가 변경되었을때, Entity가 받을 영향을 최소화할 수 있다.
3. 결론적으로 Entity는 DB와 연관되어 있는 객체기에 생성자만 제공해주고 필요한 곳에서 가져다가 인스턴스를 만들도록 하는게 좋다고 생각한다.
그래서 정작 변환하는 코드는 어디에? ( Controller , Service )
이는 프로젝트마다 다르겠지만 만약 컨트롤러에 위치한다면 아래와 같은 문제가 발생할 수 있다.
1. 복잡한 어플리케이션의 경우 컨트롤러는 View에서 전달받은 DTO만으로 엔티티 구성이 어렵기때문에 Service로직이 Controller에 포함되게 된다. 예를들어 주문번호 같은 고유한 번호는 UUID로 생성하고 최근 번호값에서 +1을 하여 생성한다고 가정할때, 결국 Repository를 거쳐야만 한다.
2. 여러 Entity객체들을 조회해야하기 때문에 하나의 Controller가 의존하는 Service 의 갯수가 많아진다.
즉, 하나의 DTO로 하나의 서비스만 이용하려면 엔티티 변경이 필수불가결이기 때문에 어쩔수없이 의존해야하는 Service의 갯수가 많아진다.
여러 종류의 컨트롤러가 한 서비스를 사용하는 경우와 한 종류의 컨트롤러만 서비스를 사용하는 경우 두가지로 나뉜다면, 보통 현업에선 후자가 많을것이다.
따라서 여러 레퍼런스를 찾고 내린 결론은 아래와 같다.
1.Service에 DTO진입을 허용하고 메서드 상위에서 Entity로 변환하여 사용한다.
2.반환타입의 경우 Entity를 내보내고 컨트롤러에서 DTO로 변환한다. 이는 Service트랜잭션에서 순수엔티티만 가지고 처리할수 있는 장점이있다.
'지식 저장소' 카테고리의 다른 글
JPA insert쿼리전에 select쿼리가 나가는 현상 ( feat.HHH000099 에러) (0) | 2023.08.28 |
---|---|
MPA와 SPA란? (0) | 2023.05.11 |
같은 값 기준 정렬 후 페이징 시 목록 꼬임 문제 (0) | 2023.01.10 |
Replication(복제) (0) | 2022.09.08 |
Cannot add or update a child row 에러 (0) | 2022.01.19 |