개발 일기

[Spring Boot] ModelMapper와 MapStruct 본문

Back-End/Spring

[Spring Boot] ModelMapper와 MapStruct

개발 일기장 주인 2024. 5. 31. 14:18

공부하게된 계기

기존에는 하나의 객체의 값을 다른 객체에 바인딩 시키는 경우. 즉, Entity로 가져온 데이터를 Response DTO에 바인딩 시키는 경우에 record 타입의 DTO에서 정적 메소드를 직접 선언하여 일일이 다 매핑해준다.

아래 코드가 내가 실제로 썼던 Entity 객체 값을 Response DTO에 바인딩 시켰던 예시이다.

그러나 실무를 해본 같은 동아리 친구가 이 방식보다 ModelMapper와 MapStruct를 써보는 것이 어떻겠냐고 제안해줘서 한번 이번 기회에 정리해보고 Trade-Off를 따져보고 혹시 더 좋은 방법이라면 도입해보고자 정리해보기로 했다.


ModelMapper와 MapStruct는 모두 Java에서 객체 간 매핑을 위한 라이브러리이다.

ModelMapper

ModelMapper는 런타임 시점에 Reflection API를 사용하여 객체를 매핑한다.

자바에서 객체 간 데이터 값을 전달할 때, Setter를 사용하거나 Record형식의 DTO에 정적 메서드를 통해 필드에 값을 하나씩 직접 매핑하는 작업은 단순하고 반복적인 작업이다.
그러한 작업을 자동화하기 위해 ModelMapper 라이브러리를 활용하여 간소화 시킬수 있다.

ModelMapper는 객체 간의 데이터를 자동으로 매핑해주어, 개발자의 반복 작업을 줄이고 코드의 간결성과 유지보수성을 높여준다.

 

실제로 적용시켜보자

@Configuration
public class ModelMapperConfig {
    @Bean
    public ModelMapper modelMapper(){
        ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE);
        return modelMapper;
    }
}

MdoelMapper의존성을 추가해준 뒤 위와 같이 Config를 추가해주고 

위에 MemberGetResponseDto.record를

이렇게하여 정적 메소드나 Setter필요없이 일일이 매핑해줄 필요도 없이

@Service
@RequiredArgsConstructor
@Transactional
public class MemberService {
    private final MemberRepository memberRepository;
    private final ModelMapper modelMapper;

    public MemberGetProfileResponseDto getMemberProfile(Long memberId) {
        Member member = memberRepository.findMemberByIdOrThrow(memberId);
//        return MemberGetProfileResponseDto.of(member);
        return modelMapper.map(member, MemberGetProfileResponseDto.class);
    }
}

이렇게 해주면 자동으로 매핑이 되어 정상적으로 반환된다.

 

MapStruct

 

자바 코드 매핑 vs ModelMapper vs MapStruct 비교