인프런 커뮤니티 질문&답변

김태정님의 프로필 이미지
김태정

작성한 질문수

실전! Querydsl

프로젝션과 결과 반환 - DTO 조회

DTO 파라미터 방식

작성

·

455

8

안녕하세요 영한님,

항상 좋은 강의를 만들어 주셔서 감사합니다!

이번강의를 보다 의문점이 들었는데,

이전 강의에서 DTO 생성자 파라미터에 엔티티를 그대로 넣은 방식은 아무런 문제가 되지 않는다는 말씀을 들었던 기억이 있습니다. 

이후의 확장성, 변동성을 생각했을때 이 방식이 정말 최고라고 생각 했었는데요, 

같이 프로젝트를 진행하던 팀원이 DTO 생성자 파라미터에 엔티티 자체를 넣는 방식이 오히려 DTO를 들어가봐야 내부속성을 알기때문에 가독성이 떨어지지 않느냐는 얘기를 하였습니다.

서론이 길었네요,

프로젝션의 생성자 방식에서 생성자 파라미터에 엔티티 자체를 넣는것과 엔티티의 속성을 넣는것 중 어느 것이 실무에 더 잘쓰일까요..?

혹시몰라 코드 남김니다!

@Test
public void findDtoByConstructor(){
List<MemberDto> result = queryFactory
.select(Projections.constructor(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
for (MemberDto memberDto : result) {
System.out.println("memberDto = " + memberDto);
}
}
@Test
public void findUserDtoByConstructor(){
List<UserDto> result = queryFactory
.select(Projections.constructor(UserDto.class,
member))
.from(member)
.fetch();
for (UserDto userDto : result) {
System.out.println("memberDto = " + userDto);
}
}

답변 4

8

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 김태정님^^ 좋은 질문입니다.

DTO 생성자 파라미터에 엔티티를 그대로 넣은 방식은 설계상 문제는 없습니다.

다만! 엔티티를 먼저 조회해서 이후에 DTO로 변환하는 경우에는 이렇게 해도 됩니다. 왜냐하면 DTO는 엔티티를 의존해도 설계상 아무런 문제가 없기 때문이지요.

그런데! 엔티티를 먼저 조회하지 않고, 바로 DTO로 조회하는 경우에는 이렇게 하는 것이 좋지 않습니다.

여기에는 2가지 이유가 있습니다.

1. DTO로 직접 조회하는 이유는 엔티티를 무시하고, 조회용 모델을 바로 만드는 것이 목표입니다. 따라서 중간에 번거롭게 엔티티를 만들 이유가 없습니다.

2. 이것은 설계상에 큰 문제는 없지만, 성능에서 차이가 납니다.

위에서 첫번째는 SQL select 쿼리가 username, age 두 필드만 조회합니다. 반면에 두번째는 SQL 쿼리가 member의 모든 필드를 다 조회합니다.

결국 리포지토리 계층에서 DTO를 바로 조회할 때는 엔티티를 거치지 않는 것이 더 나은 방법입니다.

다만 리포지토리 계층에서 엔티티를 조회하고, 그 엔티티를 어디선가 DTO로 변환할 때는 이미 엔티티를 조회한 상황이기 때문에 이때는 DTO의 생성자 파라미터를 활용하시는 방법도 괜찮습니다.

도움이 되셨길 바래요^^

2

김태정님의 프로필 이미지
김태정
질문자

궁금증이 한번에 해결되었습니다. 

감사합니다!

0

질문
DTO 파라미터 방식

안녕하세요 영한님,

항상 좋은 강의를 만들어 주셔서 감사합니다!

이번강의를 보다 의문점이 들었는데,

이전 강의에서 DTO 생성자 파라미터에 엔티티를 그대로 넣은 방식은 아무런 문제가 되지 않는다는 말씀을 들었던 기억이 있습니다. 

이후의 확장성, 변동성을 생각했을때 이 방식이 정말 최고라고 생각 했었는데요, 

같이 프로젝트를 진행하던 팀원이 DTO 생성자 파라미터에 엔티티 자체를 넣는 방식이 오히려 DTO를 들어가봐야 내부속성을 알기때문에 가독성이 떨어지지 않느냐는 얘기를 하였습니다.

서론이 길었네요,

프로젝션의 생성자 방식에서 생성자 파라미터에 엔티티 자체를 넣는것과 엔티티의 속성을 넣는것 중 어느 것이 실무에 더 잘쓰일까요..?

혹시몰라 코드 남김니다!

@Test
public void findDtoByConstructor(){
List<MemberDto> result = queryFactory
.select(Projections.constructor(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
for (MemberDto memberDto : result) {
System.out.println("memberDto = " + memberDto);
}
}
@Test
public void findUserDtoByConstructor(){
List<UserDto> result = queryFactory
.select(Projections.constructor(UserDto.class,
member))
.from(member)
.fetch();
for (UserDto userDto : result) {
System.out.println("memberDto = " + userDto);
}
}

김영한
김영한2020.08.12 PM 22:42

안녕하세요. 김태정님^^ 좋은 질문입니다.

DTO 생성자 파라미터에 엔티티를 그대로 넣은 방식은 설계상 문제는 없습니다.

다만! 엔티티를 먼저 조회해서 이후에 DTO로 변환하는 경우에는 이렇게 해도 됩니다. 왜냐하면 DTO는 엔티티를 의존해도 설계상 아무런 문제가 없기 때문이지요.

그런데! 엔티티를 먼저 조회하지 않고, 바로 DTO로 조회하는 경우에는 이렇게 하는 것이 좋지 않습니다.

여기에는 2가지 이유가 있습니다.

1. DTO로 직접 조회하는 이유는 엔티티를 무시하고, 조회용 모델을 바로 만드는 것이 목표입니다. 따라서 중간에 번거롭게 엔티티를 만들 이유가 없습니다.

2. 이것은 설계상에 큰 문제는 없지만, 성능에서 차이가 납니다.

위에서 첫번째는 SQL select 쿼리가 username, age 두 필드만 조회합니다. 반면에 두번째는 SQL 쿼리가 member의 모든 필드를 다 조회합니다.

결국 리포지토리 계층에서 DTO를 바로 조회할 때는 엔티티를 거치지 않는 것이 더 나은 방법입니다.

다만 리포지토리 계층에서 엔티티를 조회하고, 그 엔티티를 어디선가 DTO로 변환할 때는 이미 엔티티를 조회한 상황이기 때문에 이때는 DTO의 생성자 파라미터를 활용하시는 방법도 괜찮습니다.

도움이 되셨길 바래요^^

좋아요(7)댓글 달기
김태정
김태정2020.08.13 PM 13:39

궁금증이 한번에 해결되었습니다. 

감사합니다!

좋아요(2)댓글 달기
김영한
김영한2020.08.13 PM 20:57

네 즐거운 코딩생활 되세요^^!

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 고성빈님

첫번째 방법을 사용해야 합니다. 두번째 방법을 사용하면 쿼리에서 select 낭비가 발생합니다.

감사합니다.

0

김영한님의 프로필 이미지
김영한
지식공유자

네 즐거운 코딩생활 되세요^^!

김태정님의 프로필 이미지
김태정

작성한 질문수

질문하기