스프링부트의 DTO 관리 방법? (옛날 글.. 21년?)

구운몽·2024년 6월 14일
0

레거시 시스템을 운영하고 있기 때문에, 사이드 프로젝트는 최대한 현대에 가까운(?) 기술로 진행해보려고 했다. 실무 경험이나 사수/스승의 부재로 혼자서 모든 걸 다 해야한다. 그 와중에 가장 골치를 썩는 문제가 바로 DTO와 엔티티 관리인 것 같다.

여러가지 생각해본 결과 아래 순서대로 일단 개발하기로 결정했다.

1. 컨트롤러에서 엔티티를 바로 쓰지 말자

회사에서 제공하는 보일러플레이트는 엔티티를 바로 사용하더라.. 테이블 구조를 클라이언트에 노출하는 것은 피해야하고, 순환참조 문제를 피하고 싶다.

2. MAPSTURCT를 사용하자

정답이 아닐 수도 있는데, DTO와 엔티티를 오가는 메소드를 작성하는 것이 너무 번거롭다. Dto와 엔티티를 1:1로 작성하고 Generic 인터페이스로 자동화 코드를 생성한다.

public interface GenericMapper <D,E>{
	D toDto(E e);
	E toEntity(D d);
	List<D> toDto(List<E> e);
	List<E> toEntity(List<D> d);
}

3. request/response DTO

테이블 구조를 노출하고 싶지 않아서 엔티티를 바로 사용하지 않는 것인데, 1:1 매핑을 하면 무슨 소용인가 싶었다. request의 경우에도 1:N 등의 요청에서 불필요하게 테이블 구조에 맞게 JSON 요청을 받는게 좋지 못한 모양새라고 생각했다.

이게 뭐람..?

{
    "orderId" : "itsm111",
    "closed" : "TRUE",
    "product" : {
        "productId" : 11   
    }
}

그래서 req/res DTO를 따로 사용해야할 것 같아서 폭풍 검색을 통해..
https://velog.io/@p4rksh/Spring-Boot에서-깔끔하게-DTO-관리하기
이 분 글을 참고하기로 했다. 결론은 inner class를 이용하고 도메인DTO를 item/req/res로 분리했다. 다만, 위 벨로그 글대로 DTO를 작성해도 테이블 구조가 노출되는 문제를 해결할 수 없다.

item은 엔티티(테이블)과 1:1 매핑되는 DTO이다.
BaseResponse는 리턴코드와 메시지 등을 가지고 있습니다.

	@Getter
	@SuperBuilder
	public static class Response extends BaseResponse {
		private Item item;
	}

4. @Builder와 @JsonIgnore 사용

테이블 구조를 노출을 최소화하는 순서는 아래와 같은데,

4-1. 컨트롤러에서 reqDTO를 받는다. reqDTO는 내 맘대로 작성해도 된다.
4-2. 서비스에서 reqDTO의 데이터를 이용해 item를 빌더로 작성한다.
4-3. itemDTO를 맵스트럭트로 만들어진 메소드로 toEntity화 한다.
4-4. repository로 데이터를 받는다.
4-5. 반환받은 데이터를 toDTO 해주고 컨트롤러로 전달한다.
4-6. 컨트롤러에서 resDTO를 빌드하여 반환한다.
4-7. item 에서 JsonIgnore를 설정하여 노출을 피하고 싶은 컬럼을 숨긴다.

0개의 댓글