MapStruct 편리한 객체 간 맵핑

2024. 2. 14. 11:21Web/spring-boot

1. MapStruct 란?

  • Java 객체 간의 맵핑을 단순화하는 코드 생성 라이브러리입니다.
  • Annotation processor를 이용하여 객체 간 매핑을 자동으로 제공합니다.
  • 반복되는 객체 매핑에서 발생할 수 있는 오류를 줄일 수 있으며, 구현 코드를 자동으로 만들어주기 때문에 사용이 쉽습니다.
  • 컴파일 시점에 코드를 생성하여 런타임에서 안정성을 보장합니다.

2. 설정 방법

  • Dependency를 먼저 추가해 주어야합니다.
  • 주의할 사항으로는  Lombok 라이브러리에 먼저 dependency (의존성) 추가가 되어있어야 합니다. MapStruct는 Lombok의 getter, setter, builder를 이용하여 생성되므로 Lombok 보다 먼저 의존성이 선언된 경우 실행할 수 없습니다.
<dependencies>
    <!-- MapStruct -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>

  <build>
        <plugins>
        	  <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source> <!-- depending on your project -->
                    <target>11</target> <!-- depending on your project -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${org.projectlombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
              </plugin>
          </plugins>
    </build>

 

3. 사용 방법

  • 먼저 DB 조회한 데이터를 담을 Entity를 선언합니다.
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder(builderMethodName = "entityBuilder", toBuilder = true)
@Table (name = "tb_user_info")
public class TbUserInfo implements Serializable {
	@Id
	@Comment("사용자 고유 ID")
   	@Column(name = "user_id" )
	private Long userId;

	@Comment("이메일")
   	@Column(name = "email" )
	private String email;

	@Comment("별명")
   	@Column(name = "nick_nm" )
	private String nickNm;
}

 

  • 그리고 데이터를 담은 Entity에 담긴 내용을 UserInfo에 맵핑할려고 합니다.
public record UserInfo(long userId, String email, String nickNm) {
}
@Mapper
public interface UserInfoMapper {
    UserInfoMapper INSTANCE = Mappers.getMapper(UserInfoMapper.class);

    UserInfo toUserInfo(@NonNull final TbUserInfo userInfo);
}
  • UserInfoMapper INSTANCE = Mappers.getMapper(UserInfoMapper.class)는 매퍼 클래스에서 UserInfoMapper 를 찾을 수 있도록 하는 방법입니다. 매퍼 interface에서 위와 같이 Instance를 선언해주면 매퍼에 대한 접근이 가능합니다.
  • Mapper 인터페이스에 @Mapper 어노테이션을 붙이면 MapStruct가 자동으로 MessageMapper의 구현체를 생성해줍니다
    public UserInfo getUserInfo(final long userId) {
        final TbUserInfo tbUserInfo = userInfoRepository.findById(userId)
                .orElseThrow(() -> new CustomException(ResponseCode.NOT_FOUND, "조회불가 userId"));

        return UserInfoMapper.INSTANCE.toUserInfo(tbUserInfo);
    }
  • 이런 식으로 DB에서 조회한 Entity를 간편하게 맵핑하여 레이어 간 이동이 가능하게 됩니다.