s
s
spring
Search…
Model Mapping
모델 매핑은 어느 Layer 단에서 구현해야할까?
  • Servie : 여러 서비스에서 사용시 중복코드가 발생하며, 모델간 매핑 로직은 비즈니스 로직이 아니므로, 목적에 부합하지 않는다.
  • Model Object
    • 서비스가 커지고, 모델간 다양한 매핑이 있을 경우 점점 객체안에 메서드가 많아지게 된다.
    • 모델 객체에 모델간 매핑 로직은 모델 객체의 목적에 부합하지 않는다.
      Mapper
      모델간 매핑에 대한 책임을 진다.
      이때, 라이브러리를 이용해서 모델간 매핑을 자동화할것인지 직접 Mapper를 이용해서 처리할지 정해야한다.
  • ModelMapper
    • 내부적으로 Refelction을 사용하므로 사용하지 않는 것이 좋다.
    • Reflection으로 인한 성능 이슈와 예상치 못한 결과가 발생할 수 있다.
  • MapStruct
    • Reflection을 사용하지 않는다.
    • 컴파일시 생성한다.
    • 국내는 적지만 미국에서 점점 사용도가 높아지고 있다.

Model Mapper

Entity와 DTO간 객체 변환을 할 때 ModelMapper를 활용하면, 쉽게 변환할 수 있다.
  • pom.xml
1
<!-- model mapper - entity-DTO conversion -->
2
<dependency>
3
<groupId>org.modelmapper</groupId>
4
<artifactId>modelmapper</artifactId>
5
<version>2.3.0</version>
6
</dependency>
Copied!
사용 방법은 간단하다.
1
private PaymentDto convertToDto(Payment payment) {
2
3
// Entity를 DTO로 변환하기위해 modelmapper사용
4
ModelMapper modelMapper = new ModelMapper();
5
6
PaymentDto paymentDto = modelMapper.map(payment, PaymentDto.class);
7
8
return paymentDto;
9
}
Copied!
처음에는 이렇게 convertToDto 메소드로 Entity에서 DTO로 변환하는 작업을 했으나, 이것은 비즈니스 로직이 아니기 때문에 따로 Mapper클래스를 생성하는 것이 좋다.

MapStruct

  • pom.xml
1
<!-- mapStruct - Entity to Dto-->
2
<dependency>
3
<groupId>org.mapstruct</groupId>
4
<artifactId>mapstruct</artifactId>
5
<version>1.3.1.Final</version>
6
</dependency>
Copied!
1
<plugin>
2
<groupId>org.apache.maven.plugins</groupId>
3
<artifactId>maven-compiler-plugin</artifactId>
4
<configuration>
5
<annotationProcessorPaths>
6
<path>
7
<groupId>org.mapstruct</groupId>
8
<artifactId>mapstruct-processor</artifactId>
9
<version>1.3.1.Final</version>
10
</path>
11
<!-- other annotation processors -->
12
</annotationProcessorPaths>
13
</configuration>
14
</plugin>
Copied!
  • EntityMapper
1
import java.util.List;
2
3
public interface EntityMapper <D, E>{
4
5
E toEntity(D dto);
6
D toDto(E entity);
7
List<D> toDtoList(List<E> entity);
8
}
Copied!
  • PaymentMapper
1
@Mapper(componentModel = "spring")
2
public interface PaymentMapper extends EntityMapper<PaymentDto, Payment> {
3
4
5
}
Copied!
  • Service
1
@Autowired
2
private PaymentMapper paymentMapper;
3
@Override
4
@Transactional
5
public PaymentDto cancelRequest(String mbrId, String pmtId, long pmtAmt, Boolean isParticleCancle) {
6
7
// ...
8
Payment result = paymentRepository.save(newPayment);
9
PaymentDto paymentDto = paymentMapper.toDto(result);
10
11
return paymentDto;
12
}
Copied!
이렇게 사용하면된다. 만약에 변수명이 다르다면, @Mapping annotation으로 쉽게 바꿀 수 있다.

참조