MapStruct 를 이용하여 DTO 와 Entity 클래스 매핑하는 방법

Lundy·2023년 11월 18일
0
post-thumbnail

DTO와 Entity를 서로 변환해주는 작업을 Controller가 직접 하지않고, 그 행위를 Mapper가 하도록 요청하여 역할을 분리한다.

MapStruct를 사용하지 않고 매핑하는 방법

  1. Mapper 클래스 구현
@Component
public class MemberMapper {
		// MemberPostDto를 Member로 변환
    public Member memberPostDtoToMember(MemberPostDto memberPostDto) {
        return new Member(0L,
                memberPostDto.getEmail(), 
                memberPostDto.getName(), 
                memberPostDto.getPhone());
    }

		// MemberPatchDto를 Member로 변환
    public Member memberPatchDtoToMember(MemberPatchDto memberPatchDto) {
        return new Member(memberPatchDto.getMemberId(),
                null, 
                memberPatchDto.getName(), 
                memberPatchDto.getPhone());
    }

    // Member를 MemberResponseDto로 변환
    public MemberResponseDto memberToMemberResponseDto(Member member) {
        return new MemberResponseDto(member.getMemberId(),
                member.getEmail(), 
                member.getName(), 
                member.getPhone());
    }
}
  1. Controller의 핸들러 메서드에 Mapper 적용
@RestController
@RequestMapping("/members")
@Validated
public class MemberController {
    private final MemberService memberService;
    private final MemberMapper mapper;

		// MemberMapper DI
    public MemberController(MemberService memberService, MemberMapper mapper) {
        this.memberService = memberService;
        this.mapper = mapper;
    }

    @PostMapping
    public ResponseEntity postMember(@Valid @RequestBody MemberPostDto memberDto) {
				// 매퍼를 이용해서 MemberPostDto를 Member로 변환
        Member member = mapper.memberPostDtoToMember(memberDto);

        Member response = memberService.createMember(member);

				// 매퍼를 이용해서 Member를 MemberResponseDto로 변환
        return new ResponseEntity<>(mapper.memberToMemberResponseDto(response), 
                HttpStatus.CREATED);
    }
}

위 예시를 통해 Controller의 역할이 분리되었지만 여전히 문제점이 남아있다.

만약 엔티티와 컨트롤러가 많아진다면, 그에 따라 수작업으로 작성해아 할 mapper 클래스 코드가 어마무시하게 늘어난다.

이를 해결하기 위해 MapStruct 가 탄생했다.

MapStruct는 Mapper 클래스를 자동으로 구현해주는 코드 자동 생성기이며, 이를 사용함으로써 생산성을 향상시킬 수 있다.

MapStruct 를 사용한 매핑 방법

  1. build.gradle 의존 라이브러리 설정
dependencies {
	...
	...
	implementation 'org.mapstruct:mapstruct:1.4.2.Final'
	annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
}
  1. Mapper 인터페이스 정의
@Mapper(componentModel = "spring")
public interface MemberMapper {
    Member memberPostDtoToMember(MemberPostDto memberPostDto);
    Member memberPatchDtoToMember(MemberPatchDto memberPatchDto);
    MemberResponseDto memberToMemberResponseDto(Member member);
}
  • @Mapper 애너테이션의 attribute로 componentModel = "spring" 을 지정해주면 스프링 빈으로 등록된다.
  • MapStruct가 위 인터페이스를 기반으로 Mapper 구현 클래스를 자동 생성해준다.
    • 구현 클래스는 Gradle의 build task를 실행하면 자동 생성된다.
    • 생성 위치: 프로젝트 -> build -> Mapper 인터페이스가 위치한 패키지 내부
  1. Controller에 MapStruct 적용
import [패키지 경로].MemberMapper;
  • MapStruct 인터페이스가 위치한 인터페이스의 위치를 import 해주면 적용된다.
profile
아주 사소하더라도

0개의 댓글

관련 채용 정보