JiwonDev

Mapstruct(DTO Mapper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)

by JiwonDev

๐Ÿ’ญ DTO Mapper๊ฐ€ ๋ญ์ฃ ?

View(Controller)๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง, ๋„๋ฉ”์ธ๊ณผ ์ƒ๊ด€์—†์ด ์–ธ์ œ๋“ ์ง€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋‹ค.

๋„๋ฉ”์ธ ์„œ๋น„์Šค์—์„œ ์ž…์ถœ๋ ฅ์„ ๋ฐ”๋กœ ๋ฐ›์œผ๋ฉด View์— ์˜์กด์„ฑ์ด ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์ด DTO๋กœ ๋ณ€ํ™˜ํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

// ์ด์ œ Controller(Dto ๋˜๋Š” Request)๊ฐ€ ๋ณ€ํ•ด๋„, ๋„๋ฉ”์ธ์€ ์˜ํ–ฅ๋ฐ›์ง€ ์•Š๋Š”๋‹ค.
UserEntity toEntity(UserDto userDto) {
        return new userEntity(userDto.getId(), 
                             userDto.getPassword(),
                             userDto.getName());
}

RegisterUserCommand toCommand(RegisterUserRequest request){...}
UserResponse toResponse(UserDto dto){...}
// View - Domain ์‚ฌ์ด ์ค‘๊ฐ„ ๊ณ„์ธต์ด ์žˆ๋‹ค๋ฉด ๊ตณ์ด Dto๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ๊ฐ’์„ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด๋„ ๋œ๋‹ค.
void register(RegisterUserRequest request){
    userService.register(request.getName(), request.getId(), request.getPassword());
}

 

์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๋‹ค๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋งŽ์€ ํ•„๋“œ๋ฅผ ์ฃผ๊ณ ๋ฐ›์•„์•ผ ํ•˜๋Š” ์ผ์ด ๋งŽ๋‹ค.
์ด๊ฒŒ ๊ท€์ฐฎ๊ธฐ๋งŒ ํ•˜๋ฉด ๋‹คํ–‰์ธ๋ฐ, ์ƒ์„ฑ์ž๊ฐ€ ์•„๋‹Œ Builder๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒฝ์šฐ ๋ณ€ํ™˜์„ ๋นผ๋จน์—ˆ์„ ๋•Œ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ฐพ๊ธฐ ์–ด๋ ต๋‹ค.

@Getter
@Setter
@ToString
public class RegisterOrderRequest {
    @NotNull
    private Long userId;
    @NotBlank
    private String payMethod;
    @NotBlank
    private String receiverName;
    @NotBlank
    private String receiverPhone;
    @NotBlank
    private String receiverZipcode;
    @NotBlank
    private String receiverAddress1;
    @NotBlank
    private String receiverAddress2;
    @NotBlank
    private String etcMessage;

    private List<RegisterOrderItem> orderItemList;
}
// Dto, Request๊ฐ€ ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด, ์•„๋ž˜ ๋งคํ•‘ ๋ฉ”์„œ๋“œ( toCommand() )๋„ ๋‹ค์‹œ ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค.
RegisterOrderCommand toCommand(RegisterOrderRequest request) {
        return RegisterOrderCommand.builder()
            .request.id()
            .request.payMethod()
            ...
            .build() // ์‹คํ–‰ํ•˜๊ธฐ ์ „๊นŒ์ง„ ํ•„๋“œ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์Œ์„ ์•Œ๊ธฐ ์–ด๋ ต๋‹ค.
        );
}

์ด๋Ÿฐ ์‹ค์ˆ˜๋ฅผ ๋ง‰์•„์ฃผ๊ณ  ๋งค๋ฒˆ ๋˜‘๊ฐ™์€ ๋ฐ˜๋ณต์ž‘์—…์„ ์ž๋™ํ™” ํ•ด์ฃผ๋Š” ๋„๊ตฌ, Dto Mapper ๊ฐ™์€๊ฑด ์—†์„๊นŒ? 

โžก ์ด๊ฒŒ ๋ฐ”๋กœ Mapstruct์ด๋‹ค.

 

MapStruct 1.5.0.Beta2 Reference Guide

If set to true, MapStruct in which MapStruct logs its major decisions. Note, at the moment of writing in Maven, also showWarnings needs to be added due to a problem in the maven-compiler-plugin configuration.

mapstruct.org

 

 

 

๐Ÿ“‘ ์ž๋™ํ™”ํ•ด์ฃผ๋Š” ModelMapper๋Š” ์˜›๋‚ ๋ถ€ํ„ฐ ์žˆ์—ˆ์ง€์•Š๋‚˜์š”?

ModelMapper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด๋‚˜ ๋„๊ตฌ๋“ค์€ ์˜›๋‚ ๋ถ€ํ„ฐ ์กด์žฌํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„ ๋ฆฌํ”Œ๋ ‰์…˜๊ณผ Setter๋ฅผ ์‚ฌ์šฉ์„ ๊ฐ•์ œํ•˜๋‹ค๋ณด๋‹ˆ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋””๋ฒ„๊น…๋„ ํž˜๋“ค์–ด์ง€๊ณ , ๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ๋ผ์น˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜๊ธฐ์—๋Š” ๋งŽ์ด ๋ง์„ค์—ฌ์กŒ์—ˆ๋‹ค.

 

Mapstruct๋ฅผ ์ถ”์ฒœํ•˜๋Š” ์ด์œ ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • ๋ฆฌํ”Œ๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ์ปดํŒŒ์ผ ํƒ€์ž„(์–ด๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ)์— ์ฒ˜๋ฆฌํ•œ๋‹ค. (= ์•ฑ ์„ฑ๋Šฅ์— ์˜ํ–ฅ ์—†์Œ)
  • ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์„œ ๋งคํ•‘ ๋„์ค‘์— ์˜ค๋ฅ˜๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ ๋””๋ฒ„๊น…์ด ์‰ฝ๋‹ค.
  • ์ฒ˜๋ฆฌ์†๋„๊ฐ€ ๊ต‰์žฅํžˆ ๋น ๋ฅธํŽธ์ด๋ผ์„œ, ์ปดํŒŒ์ผ ์‹œ๊ฐ„์—๋„ ๊ฑฐ์˜ ์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š๋Š”๋‹ค.
  • ์ด๋ฏธ ๋งŽ์€ ์ž๋ฐ”, ์Šคํ”„๋ง ๊ฐœ๋ฐœ์ž๋“ค์ด ์‚ฌ์šฉํ•˜๊ณ ์žˆ๋Š” ๊ฒ€์ฆ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

mapstruct์˜ ์••๋„์ ์ธ ๊ฒ€์ƒ‰๋Ÿ‰ (๊ตฌ๊ธ€ํŠธ๋ Œ๋“œ)

 


๐Ÿ’ญ Mapstruct ์ถ”๊ฐ€ํ•˜๊ธฐ

https://www.baeldung.com/mapstruct

mapstruct๋Š” ์–ด๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋ฅผ ์ด์šฉํ•œ๋‹ค. ์•„๋ž˜์™€ ์˜์กด์„ฑ์„ 2๊ฐœ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor "org.mapstruct:mapstruct-processor:1.4.2.Final"


๋‹จ lombok์„ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ์ปดํŒŒ์ผ ๋„์ค‘ ์ถฉ๋Œํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์•„๋ž˜์™€ ๊ฐ™์ด lombok-mapstruct-binding์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

* ๊ธฐ๋ณธ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋กฌ๋ณต์ด ๋จผ์ € ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ˆœ์„œ๋ฅผ ๋งž์ถฐ์ฃผ์–ด์•ผํ•œ๋‹ค. (1. lombok -> 2. mapstruct)
์ฐธ๊ณ ๋กœ ๋กฌ๋ณต ์ตœ์‹ ๋ฒ„์ „(1.18.16 ์ด์ƒ)์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๊ทธ๋ƒฅ ๋”ฐ๋กœ ์ถ”๊ฐ€ํ•˜๋”๋ผ๋„ ์•Œ์•„์„œ ๋กฌ๋ณต์ด ๋จผ์ € ์‹คํ–‰๋œ๋‹ค.

annotationProcessor(
    'org.projectlombok:lombok', // lombok 1.18.16 ์ด์ƒ์€ ์ด๋ ‡๊ฒŒ ์ˆœ์„œ์ง€์ • ์•ˆํ•ด๋„ ๋œ๋‹ค.
    'org.projectlombok:lombok-mapstruct-binding'
)

 

Maven์—์„œ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•

๋”๋ณด๊ธฐ
<properties>
    <org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
</properties>


<dependencies>
    <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok-mapstruct-binding</artifactId>
        <version>0.2.0</version>
    </dependency>
</dependencies>

...

    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <!-- mapstruct-์–ด๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ -->
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                    
                    <!-- ๋‹ค๋ฅธ ์–ด๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ -->
                
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    <plugins>

 


๐Ÿ’ญ Mapstruct ์‚ฌ์šฉํ•˜๊ธฐ

์ˆœ์ˆ˜ ์ž๋ฐ”์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ , @Mapper ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ์ฃผ๋ฉด ๋์ด๋‹ค.
ํ•„๋“œ ์ด๋ฆ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒ์„ฑ๋˜๋ฉฐ, ๋งŒ์•ฝ ์ด๋ฆ„์ด ๋‹ค๋ฅด๋ฉด @Mapping(source ="~" , target="~")์œผ๋กœ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

import org.mapstruct.Mapper;

@Mapper
public interface UserMapper {

    UserEntity toEntity(UserRequest request);
	
    UserDto toDto(UserEntity entity);

    // ์ด๋ฆ„์ด ๋‹ค๋ฅธ๊ฒฝ์šฐ ์ง์ ‘ ์ง€์ •ํ•ด์ค€๋‹ค. request.nick -> command.nickName
    @Mapping(source = "nickName", target = "nick")
    UserCommand toCommand(UserRequest request);
    
    // ๋ฐ”๊พธ๊ณ  ์‹ถ์€๊ฒŒ ์—ฌ๋Ÿฌ ๊ฐœ๋ผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ง€์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
    @Mappings({
         @Mapping(source = "nickName", target = "nick"),
         @Mapping(source = "userId", target = "id")})
	UserCommand toCommand(UserRequest request);
    
}

 


๋นŒ๋“œํ•˜๊ธฐ ์ „๊นŒ์ง„ ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†๋‹ค. ๊ทธ๋ž˜์„œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์ฃผ์ž…๋ฐ›์•„ ์‚ฌ์šฉํ•˜๋Š”๊ฑธ ๊ถŒ์žฅํ•œ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด UserMapper mapper= Mappers.getMapper(UserMapper.class) ๋กœ ์ฃผ์ž…๋ฐ›์•„์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. 

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
    ...
}

public void main(){
    UserMapper mapper = UserMapper.INSTANCE;
    mapper.toCommand(~) // ์ด๋ ‡๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค์— ์ฃผ์ž…๋ฐ›์•„์„œ ์‚ฌ์šฉ
}

 

๐Ÿ“‘ ๋ฆฌํ”Œ๋ ‰์…˜์ด ์•„๋‹Œ๋ฐ, ์–ด๋–ป๊ฒŒ ๋ณ€ํ™˜ํ•˜๋Š”๊ฑด๊ฐ€์š”?

Mapstruct๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค. ์›ํ•œ๋‹ค๋ฉด ์„ค์ •์„ ํ†ตํ•ด ํŠน์ • ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

  • public ํ•„๋“œ์— ์ง์ ‘ ์ ‘๊ทผ
  • Java Beans ์ด๋ฆ„ ๊ทœ์น™์„ ๋”ฐ๋ฅธ Getter, Setter์„ ์ด์šฉํ•œ ์ ‘๊ทผ
  • ๊ฐ์ฒด ๋‚ด์— ์กด์žฌํ•˜๋Š” Builder (Builder๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๋ผ์„œ ๋ชป์ฐพ๊ฒ ๋‹ค๋ฉด ์ปดํŒŒ์ผ ์˜ค๋ฅ˜)
  • ์ƒ์„ฑ์ž

 

๐Ÿ“‘ ๋งคํ•‘์— ์‹คํŒจํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”?

๊ธฐ๋ณธ ์„ค์ •์€ null์ด ๋“ค์–ด๊ฐ€๋„๋ก ๋˜์–ด์žˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋„๋ก ๋ณ€๊ฒฝํ•ด์ฃผ์ž.

@Mapper(
        unmappedTargetPolicy = ReportingPolicy.ERROR // ๋งคํ•‘ ์‹คํŒจ์‹œ ์ปดํŒŒ์ผ ์—๋Ÿฌ 
)
public interface OrderDtoMapper { ... }

์ฐธ๊ณ ๋กœ ์ด์— ๊ด€ํ•œ ์˜ต์…˜์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค. (๋ฌด์‹œํ•˜๊ธฐ, ์ปดํŒŒ์ผ๊ฒฝ๊ณ , ์ปดํŒŒ์ผ์—๋Ÿฌ)

unmappedSourcePolicy IGNORE(๊ธฐ๋ณธ), WARN, ERROR Source์— ๋งคํ•‘ ๋ชปํ•œ ํ•„๋“œ๊ฐ€ ์žˆ์„ ๋•Œ
unmmapedTargetPolicy IGNORE, WARN(๊ธฐ๋ณธ), ERROR Target์— ๋งคํ•‘ ๋ชปํ•œ ํ•„๋“œ๊ฐ€ ์žˆ์„ ๋•Œ
typeConversionPolicy IGNORE(๊ธฐ๋ณธ), WARN, ERROR ๊ฐ’์ด ์œ ์‹ค๋  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…๋ณ€ํ™˜์ผ ๋•Œ
(ex Long -> Int)
nullValueMappingStrategy RETURN_NULL(๊ธฐ๋ณธ), RETURN_DEFAULT Source ์ž์ฒด๊ฐ€ null์ผ ๋•Œ
nullValuePropertyMappingStrategy SET_TO_NULL(๊ธฐ๋ณธ), SET_TO_DEFAULT,
IGNORE
Source์˜ ํ•„๋“œ ๊ฐ’์ด null์ผ ๋•Œ
(๋ฌด์‹œํ•˜๋ฉด ํ•ด๋‹น ๊ฐ’์„ ๋งคํ•‘ํ•˜์ง€ ์•Š์Œ)

RETURN_DEFAULT๋Š” ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค์— ์žˆ๋Š” default ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๋งŒ์•ฝ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ์—†๋‹ค๋ฉด unmapped ์ •์ฑ…์— ๋”ฐ๋ผ null์„ ๋„ฃ๊ฑฐ๋‚˜ ์ปดํŒŒ์ผ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

 

์ฐธ๊ณ ๋กœ ReportingPolicy.ERROR๋กœ ์„ค์ •ํ–ˆ๋Š”๋ฐ, ํŠน์ • ๊ฐ’์„ ๋ฌด์‹œํ•˜๊ณ  null๋กœ ๋งคํ•‘ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ํ•˜๋ฉด ๋œ๋‹ค.

@Mapping(target = "createDate", ignore = true) // createDate๋Š” ๋งคํ•‘ํ•˜์ง€์•Š๊ณ  null์ด ์ž…๋ ฅ๋œ๋‹ค.
UserEntity userDTOToEntity(UserDTO userDTO);

 

 

๐Ÿ“‘ @Mapper(...) ์„ค์ • ๋Œ๋ ค์“ฐ๊ธฐ

@MapperConfig๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

@MapperConfig(unmappedTargetPolicy = ReportingPolicy.ERROR, uses = GenericMapper.class)
public interface MapStructMapperConfig {

}

// uses ์„ค์ •์„ ์ด์šฉํ•˜๋ฉด GenericMapper๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ƒ์†ํ•˜๋“ฏ์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
@Mapper
public interface GenericMapper {
    // objectMapper๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ์ฒด->๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜
    ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    default String toString(Object obj) {
        ...
    }
}
@Mapper(config = MapStructMapperConfig.class)
public interface UserMapper {
	...
}

@Mapper(config = MapStructMapperConfig.class)
public interface MyMapper {
	...
}

๋‹ค๋งŒ ์—ฌ๋Ÿฌ ์„ค์ •์„ ์ˆœํ™˜์ฐธ์กฐ ( A -> B -> A )ํ•˜๊ฒŒ ๋งŒ๋“ค๋ฉด ๋งคํ•‘๋„์ค‘ ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋‹ˆ, ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜์ž.

 

 


๐Ÿ’ญ ์Šคํ”„๋ง์—์„œ Mapstruct

์Šคํ”„๋ง์˜ ๊ฒฝ์šฐ๋Š” ๋” ๊ฐ„๋‹จํ•˜๋‹ค. ์• ๋…ธํ…Œ์ด์…˜์˜ ์†์„ฑ ๊ฐ’์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ถ”๊ฐ€๋œ๋‹ค.

์ฐธ๊ณ ๋กœ ๋งคํ•‘์ด ์‹คํŒจํ•  ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ๋ฐฉ๋ฒ•, ํ•„๋“œ ์ฃผ์ž… ๋ฐฉ๋ฒ•๋“ฑ ๋‹ค๋ฅธ ์˜ต์…˜๋„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

@Mapper(
        componentModel = "spring", // Spring Bean ์œผ๋กœ ์ƒ์„ฑ
        injectionStrategy = InjectionStrategy.CONSTRUCTOR, // ์ƒ์„ฑ์ž ์ฃผ์ž…
        unmappedTargetPolicy = ReportingPolicy.ERROR // ๋งคํ•‘ ์‹คํŒจ์‹œ ์ปดํŒŒ์ผ ์—๋Ÿฌ 
)
public interface OrderDtoMapper { ... }

'์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ถ”๊ฐ€๋œ๋‹ค'๊ณ  ํ–ˆ๋Š”๋ฐ, ๋ฆฌํ”Œ๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฑด ๋‹น์—ฐํžˆ ์•„๋‹ˆ๋‹ค. ๊ทธ๋ƒฅ @Component ๋ฅผ ๋‹ฌ์•„์ค€๋‹ค.

์‹ค์ œ ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2022-01-16T08:19:05+0900",
    comments = 
        "version: 1.4.2.Final, 
        compiler: IncrementalProcessingEnvironment from gradle-language-java-7.1.1.jar,
        environment: Java 16.0.1 (Oracle Corporation)"
)
@Component // ๊ทธ๋ƒฅ @Component ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ์ค€๋‹ค.
public class OrderDtoMapperImpl implements OrderDtoMapper {...}

 

 

๐Ÿ“‘ ๊ฐ์ฒด๋ฅผ ๋งคํ•‘ํ•˜๊ฑฐ๋‚˜ ์ž…์ถœ๋ ฅ์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ

๊ฐ์ฒด๋ฅผ ๋งคํ•‘ํ•˜๊ฑฐ๋‚˜, ํ•„๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์ผ๋•Œ๋Š” ์ด๋ฆ„(userEntity.name)๊นŒ์ง€ ํ•จ๊ป˜ ์ ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
์ž˜ ์‚ฌ์šฉํ•˜์ง„ ์•Š์ง€๋งŒ expression = "java(..code..)" ๋กœ ๋ณ€ํ™˜ํ•  ๊ฐ’์„ ์ฝ”๋“œ๋กœ ์กฐ์ž‘ํ• ์ˆ˜๋„ ์žˆ๋‹ค. (ํŠน์ • ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜)

@Mapping(source = "userEntity.nickName", target = "nick")
@Mapping(source = "address", target = "add") // Address ๊ฐ์ฒด ๋งคํ•‘
@Mapping(target = "message", expression = "java(message + \".msg\")") // message + ".msg"
UserCommand toCommand(UserEntity userEntity, String message, Address address);
public class UserDTO {
    private Long id;
    private String password;
    private String name;
    private String nick;
    private String message;
    private Address add;
}

public class Address {
	private String address;
	private int addressNum;
}

 

๋งŒ์•ฝ Dto์•ˆ์— ๊ฐ์ฒด(Record, Account)๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•ด์ฃผ์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ž๋™์œผ๋กœ ๋ณ€ํ™˜๋˜์ง€ ์•Š๋Š”๋‹ค.

Dto.name -> Entity.name ์ด๋ ‡๊ฒŒ ํ•˜๋‚˜ํ•˜๋‚˜ ์ ์–ด์ค˜์•ผํ•˜๋Š”๋ฐ, ์ด๋•Œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด target = "." ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 @Mapper
 public interface CustomerMapper {
    // recode.name ์ฒ˜๋Ÿผ ํ•˜๋‚˜ํ•˜๋‚˜ ์จ์ฃผ์ง€ ์•Š๋”๋ผ๋„, "."์„ ์ด์šฉํ•ด์„œ ๊ฐ์ฒด๋ฅผ ํ†ต์œผ๋กœ ๋งคํ•‘ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
     @Mapping( target = ".", source = "record" ) // Dto.record ๊ฐ์ฒด -> Entity.record ๊ฐ์ฒด
     @Mapping( target = ".", source = "account" ) // Dto.account ๊ฐ์ฒด -> Entity.account ๊ฐ์ฒด
     @Mapping( target = "id", source = "record.fileId" ) // ์ด๋ฆ„์ด ๊ฒน์น˜๋Š” ๊ฒฝ์šฐ, ์ด๋ ‡๊ฒŒ ํ•ด๊ฒฐํ•˜๋ฉด ๋œ๋‹ค.    
     Customer customerDtoToCustomer(CustomerDto customerDto);
 	
 }

 

๋ฌผ๋ก  ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•  ์ผ์€ ๊ฑฐ์˜ ์—†๊ธดํ•˜๋‹ค.

 

 

๐Ÿ“‘ ์ปฌ๋ ‰์…˜์ธ ๊ฒฝ์šฐ (List, Set)

๊ทธ๋ƒฅ ์“ฐ๋ฉด ๋œ๋‹ค. ๋‹ค๋งŒ ์ปฌ๋ ‰์…˜ ์•ˆ์— ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด๊ฐ€์žˆ๋‹ค๋ฉด, ์ด ๊ฐ์ฒด๋ฅผ ๋ณ€ํ™˜ํ•ด์ค„ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋กœ ์˜ˆ๋ฅผ ๋“ค๋ฉด CarDto method(Car car)ํ˜•ํƒœ์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜๋“œ์‹œ ์žˆ์–ด์•ผํ•œ๋‹ค.

@Mapper
public interface CarMapper {

    Set<String> integerSetToStringSet(Set<Integer> integers);

    List<CarDto> carsToCarDtos(List<Car> cars);

    CarDto carToCarDto(Car car);
}
// ๋นŒ๋“œ ํ›„ ์ƒ์„ฑ๋œ ์ฝ”๋“œ
@Override
public Set<String> integerSetToStringSet(Set<Integer> integers) {
    if ( integers == null ) { return null; }

    Set<String> set = new LinkedHashSet<String>();
    for ( Integer integer : integers ) {
        set.add( String.valueOf( integer ) );
    }
    
    return set;
}

@Override
public List<CarDto> carsToCarDtos(List<Car> cars) {
    if ( cars == null ) { return null; }

    List<CarDto> list = new ArrayList<CarDto>();
    for ( Car car : cars ) {
        list.add( carToCarDto( car ) );
    }

    return list;
}

๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ณต์‹๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์ž. ๊ทผ๋ฐ ๊ทธ๋ ‡๊ฒŒ ๊นŠ๊ฒŒ ๊ณต๋ถ€ํ•  ํ•„์š”๋Š” ์—†์„ ๋“ฏํ•˜๋‹ค.

์ฐธ๊ณ ๋กœ ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฐ›์€ ๊ฒฝ์šฐ, ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด๋Š” ์œ„ ํ‘œ์™€ ๊ฐ™๋‹ค.

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ