대다수의 경우에서 DTO를 효율적으로 관리하기 위해 Inner Class로 관리하는 것을 확인할 수 있음.

관련있는 DTO끼리 묶어 상위 DTO (~DTO)로 만들고, 중복되는 필드들을 공통 클래스로 관리하면 코드 양이 줄지 않을까?

예를들어 UserDTO 가 있다면

public class UserDTO {
    public static class LoginRequest {
        private String username;
				private String password;
    }

    public static class LoginResponse {
        private String username;
				private String password;
    }

		public static class DetailInfoResponse {
				private Long id;
        private String username;
				private String role;
    }

		public staic class DetailInfoListResponse {
				private int totalCount;
		    private List<DetailInfoResponse> detailInfoList;
  	}

}

이런식으로 표현할 수 있지 않을까?

DetailInfoListResponse 를 보면 DetailInfoResponse를 사용해 DetailInfo의 목록을 반환하는데, 이런식으로 관리하면 유지보수가 용이하지 않을까?

관련 DTO들끼리 필드를 재사용 할 가능성이 높을 것 같기 때문에 괜찮은 방법 같음.

실제 사용 예시:

/* ReviewDTO */
public class ReviewDTO {

    @Getter
    @Setter
    /* Review Create할 때 쓸 DTO => ReviewDTO.Create */
    public static class Create {
        private Long tutoringId;
        private String body;
        private Long tagId;
    }

    @Getter
    @Setter
    /* Review Update할 때 쓸 DTO => ReviewDTO.Update */
    public static class Update {
        private String body;
        private Long tagId;
    }

    @Getter
    @Setter
    /* Review Check할 때 쓸 DTO => ReviewDTO.Check */
    public static class Check {
        private Boolean isCompleted;
    }

    @Getter
    @Setter
    /* Review 반환할 때 쓸 DTO => ReviewDTO.Response */
    public static class Response {
        private Long id;
        private String body;
        private Boolean isCompleted;
        private ReviewNoteDTO note;
        private ReviewTagDTO tag;

        /* Entity -> DTO Response */
        public Response(Review review) {
            this.id = review.getId();
            this.body = review.getBody();
            this.isCompleted = review.getIsCompleted();
            this.note = new ReviewNoteDTO(review.getNote());
            this.tag = new ReviewTagDTO(review.getTag());
        }

        /* Entity List -> DTO Response List */
        public static List<Response> ResponseList (List<Review> reviewList) {
            List<Response> responseList = reviewList.stream()
            										.map(o->new Response(o))
            										.collect(Collectors.toList());
            return responseList;
        }

        @Getter
        public static class ReviewNoteDTO {
            private Long id;

            public ReviewNoteDTO(Note note) {
                this.id = note.getId();
            }
        }

        @Getter
        public static class ReviewTagDTO {
            private Long id;
            private String name;

            public ReviewTagDTO(Tag tag) {
                this.id = tag.getId();
                this.name = tag.getName();
            }
        }
    }
}
/* service 예시 */
public String createReview(ReviewDTO.Create createReview) {
	Optional<Tutoring> tutoring = tutoringRepository.findById(createReview.getTutoringId());
	Optional<Tag> tag = tagRepository.findById(createReview.getTagId());
	// ...생략...
}

public List<ReviewDTO.Response> reviewList() {
	List<Review> reviewList = reviewRepository.findAll();
	return ReviewDTO.Response.ResponseList(reviewList);
}

그리고 MapStruct를 통해서 DTO와 Entity간 변환을 좀 우아하게 할 수 있는거 같은데

어려워 보여서 공부가 필요해 보임.

MapStruct 라이브러리를 이용해 DTO <-> Entity 변환 하기