민팽로그

순환 참조 문제 해결: DTO 사용 본문

프로젝트/감성 스팟 가이드(2022 한이음)

순환 참조 문제 해결: DTO 사용

민팽 2022. 7. 31. 20:22

지난 프로젝트에서는 순환참조 문제 해결을 위해 어노테이션(@JasonManagedReference, @JsonBackReference)을 사용했는데, 면접에서 다른 방법을 알고 있냐는 질문에 대답하지 못하였다. 좀 더 알아보니 컨트롤러에서 엔티티를 반환하기 보다는, 가능하면 DTO를 사용하여 반환하는게 가장 좋은 방법이라는 것을 알게 됐다.

엔티티를 DTO로 감싸서 반환하면 좀 더 안전하게 사용할 수 있다. 일단 엔티티 객체는 테이블과 매핑되는 객체이기 때문에 값을 쉽게 수정해서는 안된다. 따라서 @Setter 어노테이션은 가급적 사용하지 않아야 한다. DTO는 데이터를 전달하기 위한 객체이기 때문에 @Getter, @Setter를 모두 사용해도 괜찮다. DTO에 필요한 데이터만 선정해서 반환해줄 수도 있기 때문에  DTO를 사용하는 것이 더 바람직하다.

DTO를 사용하여 엔티티의 값을 복사하면 순환참조 문제도 해결할 수 있기 때문에 이번에는 어노테이션을 사용하지 않고 모든 컨트롤러에서 DTO를 반환하도록 구현중이다.

 

Spot 엔티티와 SpotTag 엔티티가 1:N 양방향 매핑, SpotTag 엔티티와 Tag 엔티티가 N:1 단방향 매핑으로 연결되어 있는 상태이다.

 

1) SpotResponse

@Getter @Setter
public class SpotResponse {
    private Long spotId;
    private String spotName;
    private String address;
    private String region;
    private String detail;
    private String tel;
    private String spotImage;
    private Integer viewCnt;
    private List<SpotTagResponse> spotTags;

    public SpotResponse(Spot entity) {
        this.spotId = entity.getSpotId();
        this.spotName = entity.getSpotName();
        this.address = entity.getAddress();
        this.region = entity.getRegion();
        this.detail = entity.getDetail();
        this.tel = entity.getTel();
        this.spotImage = entity.getSpotImage();
        this.viewCnt = entity.getViewCnt();
        this.spotTags = entity.getSpotTags().stream()
                .map(SpotTagResponse::new).collect(Collectors.toList());
    }
}

spot을 조회하면 spotTag와 Tag를 가져와야 한다. 이때 조회된 spot을 그대로 리턴하면 양방향 매핑된 spotTag에서도 spot을 참조하여 무한루프가 발생한다. 따라서 SpotResponse에 spot 값을 담아 리턴한다. 여기서 spotTags는 Tag와 단방향으로 연결되어 있기 때문에 그대로 반환하여도 순환 참조 문제는 발생하지 않겠지만, 엔티티를 반환하지 않기 위해 DTO(SpotTagResponse)로 변환하였다. 

 

2) SpotTagResponse

@Getter @Setter
public class SpotTagResponse {
    private String value;

    @Builder
    public SpotTagResponse(SpotTag spotTag) {
        this.value = spotTag.getTag().getValue();
    }
}

Tag 엔티티는 id, value의 컬럼을 갖고 있지만 id는 반환해주지 않을 것이기 때문에 SpotTagResponse에는 value만 멤버변수로 갖도록 하였다.

 

'프로젝트 > 감성 스팟 가이드(2022 한이음)' 카테고리의 다른 글

log 설정  (0) 2022.07.31
[JPA] N+1 문제  (0) 2022.07.31
MZ와 "가보자고" : 프로젝트 준비 과정  (0) 2022.07.31
Comments