Introduction
백엔드에서 일반적으로 서비스 로직을 구성할 때 매개변수와 전달인자로 DTO를 사용한다.
여러가지 이유가 있겠지만, 필자가 생각하는 기본적인 이유는
1. 데이터의 종류와 타입 등 클라이언트의 요구사항이 다르다.
- 서비스에서 클라이언트의 요구사항에 맞는 데이터를 가공 및 추가하는 과정이 필요하고, 불필요한 데이터를 응답할 필요가 없다.
2. Entity 객체의 필드 값을 예상하기 힘들다.
- Entity 객체는 특정조건에 따른 결과물일 수도 있기 때문에 특정 데이터에 관해 직관적이지 못하고, 코드 추적이 불가피하다.
3. Entity 객체의 데이터의 무결성
- 서비스 로직에서 전달인자와 매개변수로 Entity 객체를 사용하게 되면, 의도치 않게 Entity의 값이 변경될 경우 JPA 의 Dirty Check로 인한 데이터 변경이 발생할 수 있다.
4. 직렬화 과정에서의 예상치 못한 에러 발생
- Entity 객체의 값이 클라이언트 요구사항에 완벽하게 일치하여, Entity 객체를 전달인자로 그대로 응답할 경우 직렬화 과정에서 toString(), 양방향 연관관계 등등 다양한 문제로 stackoverflow 가 발생할 수 있다.
DTO 매핑
1.JPQL
그렇기 때문에 백엔드에서 전달인자, 매개변수로 DTO객체를 사용한다. 그리고 Entity 를 DTO로 변환 하는 과정을 직접적으로 지원하기도 한다. JPQL 의 경우는 'POSO' 방식을 지원하는데.
@Query("select new com.test.memberDTO(m.id, m.name, m.age) from member m")
List<MemberDTO> findAllByMemberDto();
생성자를 이용해 반환 값을 DTO로 매핑해준다.
2.QueryDSL
JPQL 기반으로 동작하는 QueryDSL 도 Entity 를 DTO로 변환 조회를 지원한다. 크게 세 가지 방법이 존재한다.
1. Projections.bean()
- 기본생성자가 존재해야하며, Setter를 통한 값을 매핑해주는 방법.
jpaQueryFactory.
select(
Projections.bean(Member.class,
member.id,
member.name,
member.age
)).
from(member).
fetch();
2. Projections.fields()
- 리플렉션을 통한 필드의 직접접근 방식으로 조회 시에 결과 필드 값과 DTO 객체의 필드 값이 일치해야한다.
jpaQueryFactory.
select(
Projections.fields(Member.class,
member.id,
member.name,
member.age
)).
from(member).
fetch();
3. Projections.constructor()
- 생성자를 통해 접근하기 때문에 조회 결과의 필드 수와 타입이 일치하는 생성자가 필요하다.
jpaQueryFactory.
select(
Projections.fields(Member.class,
member.id,
member.name,
member.age
)).
from(member).
fetch();
활용
만약 Projections를 활용한 DTO 객체 조회시에 매핑된 DTO 안에 다른 DTO 객체 타입의 필드가 있을 경우 Projections를 중첩으로 사용해 객체 타입의 필드에도 값을 매핑해줄 수 있다.
jpaQueryFactory.
select(
Projections.bean(Member.class,
member.id,
member.name,
member.age,
Projections.bean(Team.class,
team.id,
team.name
).as("team")
)).
from(member).
join(member.team, team).
fetch();
'개발 > QueryDSL' 카테고리의 다른 글
[QueryDSL] 정렬 (동적 정렬) (0) | 2024.03.05 |
---|---|
[QueryDSL] 엔티티 조회 시에 DTO 로 매핑 하는 방법 2탄 (ObjectList in Object) (0) | 2024.03.05 |
[QueryDSL] 동적 업데이트 (0) | 2024.03.04 |
[QueryDSL] 동적 검색 (0) | 2024.03.04 |