[Spring] MapStruct์ ์ฌ์ฉ๋ฒ ๋ฐ ModelMapper์์ ๋น๊ต
๐ก ์ด ๊ธ๋ก ์๋์ ๊ฐ์ ์ ๋ณด๋ฅผ ์ป์ ์ ์์ต๋๋ค
1. MapStruct์ ModelMapper ๋น๊ต
2. MapStruct์ ์์กด์ฑ ์ค์ ๋ฐ ๋ค์ํ ์ฌ์ฉ ๋ฐฉ๋ฒ
Controller, Service, Repository ๋ฑ ๋ ์ด์ด ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ๋๋ ๋น์ฆ๋์ค ๋ก์ง์์ ํ๋์ ๊ฐ์ฒด๋ฅผ ํ์ ์ด ๋ค๋ฅธ ๊ฐ์ฒด๋ก ํ(Type) ๋ณํํ๊ฑฐ๋ ์ฌ๋ฌ ๊ฐ์ฒด๋ฅผ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ํฉ์น๋ ์ผ์ ๋งค์ฐ ๋น๋ฒํ๊ฒ ๋ฐ์ํฉ๋๋ค. ์ด๋ฐ ์์ ์ ๊ฐ๋ฐ์๊ฐ ๋ชจ๋ ์ง์ ํ๊ฒ๋๋ฉด ๋ฐ์ํ๋ ๋ฌธ์ ์ ์ ๋ช ๊ฐ์ง ๋์ดํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ฌ๋ฏธ๊ฐ ์๊ณ ๋ฐ๋ณต์ ์ด๊ณ ์ฝ๋ ์ค๋ณต์ด ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค.
- ์ค์ํ๊ธฐ ์ฝ์ต๋๋ค.
- ํ๋๊ฐ ์ถ๊ฐ๋ ์์ , ์ญ์ ๊ฐ ์ผ์ด๋ ๊ฒฝ์ฐ ๋ณํํ๋ ๋ก์ง์ ๋ํด์ ์์ ์ด ํ์ํฉ๋๋ค.
- ๋น์ฆ๋์ค ๋ก์ง์ ์์ด๊ฒ ๋๋ฉด ์ฝ๋๊ฐ ๋ณต์กํด์ง๋๋ค.
- ๊ฒฐ๊ตญ ์์ฐ์ฑ์ ๋จ์ด๋จ๋ฆฝ๋๋ค.
UserEntity userDTOToEntity(UserDTO userDTO) {
return new userEntity(userDTO.getId(),
userDTO.getPassword(),
userDTO.getName());
}
๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋ฐ์๊ฐ ์ง์ ์์ฑํ DTO๋ฅผ Entity๋ก ๋ณํํ๋ ์ฝ๋์ธ๋ฐ, ์ฌ๊ธฐ์๋ ๋น๊ต์ ๋จ์ํ ๊ฐ์ฒด๋ผ ์ฝ๋๊ฐ ์งง์ง๋ง ํ๋๊ฐ ๋ช ๊ฐ๋ง ๋ ๋์ด๋๋ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๊ณ ๊ฐ๋ฐ์์๊ฒ ํผ๊ณคํ ์์ ์ด ๋ฉ๋๋ค.
Object Mapping ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ฃผ๋ ์์ฃผ ์ข์ ๋๊ตฌ์ ๋๋ค. Object Mapping์ ์ํ ModelMapper์ MapStruct์ ๋ํด์ ์์กด์ฑ ์ค์ , Mapping ์ฌ์ฉ๋ฒ๊ณผ ์ฐจ์ด์ ์ ์์๋ณด๊ฒ ์ต๋๋ค.
MapStruct vs ModelMapper
๋จผ์ ๋น๊ตํ๊ธฐ ์ ์ ๋ค๋ฅธ ๋ธ๋ก๊ทธ์์ 50๋ง ๋ฒ ์คํํ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์๋ ์ฐจ์ด๋ ์๋์ ๊ฐ์ต๋๋ค.
์์ ๊ฐ์ด MapStruct๊ฐ ์๋๊ฐ ์๋ฑํ ๋น ๋ฅธ ๊ฑธ ๋ณผ ์ ์๊ณ ์๋์ ๊ฐ์ ์ฅ์ ๋ค์ด ๋ง์ต๋๋ค.
- MapStruct๋ ์ปดํ์ผ ์์ ์์ ์ด๋
ธํ
์ด์
์ ์ฝ์ด ๊ตฌํ์ฒด๋ฅผ ๋ง๋ค์ด๋ด๊ธฐ ๋๋ฌธ์ ๋ฆฌํ๋ ์
์ด ๋ฐ์ํ์ง ์์ต๋๋ค.
- ModelMapper๋ Mapping์ด ์ผ์ด๋ ๋ ๋ฆฌํ๋ ์ ์ด ๋ฐ์
- MapStruct์ ์ฒ๋ฆฌ์๋๊ฐ 10-5 m/s๋ก ์๋์ ์ผ๋ก ๋น ๋ฆ
๋๋ค.
- ModelMapper๋ 0.002m/s
- MapStruct๋ ์ปดํ์ผ ์ ์ค๋ฅ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
- MapStruct๋ ๋๋ฒ๊น ์ด ์ฝ์ต๋๋ค.
- MapStruct๋ ์์ฑ๋ ๋งคํ ์ฝ๋๋ฅผ ๋์ผ๋ก ์ง์ ํ์ธํ ์ ์์ต๋๋ค.
๋ฆฌํ๋ ์ ์ด๋ ?
๊ฐ์ฒด๋ฅผ ํตํด ํด๋์ค์ ์ ๋ณด๋ฅผ ๋ถ์ํด ๋ด๋ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ. ๊ตฌ์ฒด์ ์ ํด๋์ค ํ์ ์ ์์ง ๋ชปํด๋ ์ปดํ์ผ๋ ๋ฐ์ดํธ ์ฝ๋๋ฅผ ํตํด ์ญ์ผ๋ก ํด๋์ค์ ์ ๋ณด๋ฅผ ์์๋ด์ด ํด๋์ค๋ฅผ ์ฌ์ฉํ๊ฒ ํ ์ ์์ต๋๋ค.
๋ฆฌํ๋ ์ ๊ธฐ๋ฒ์ ํตํด ๊ฐ์ฒด์ ํ์ ์ ๋ชจ๋ฅด๋ ์ํ์์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค. ์ฆ ๋์ ๋ฐ์ธ๋ฉ์ด ๋์ง ์๋ ์๋ฐ์์ ๋ฆฌํ๋ ์ ์ด๋ผ๋ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ์ ํตํด ๋์ ๋ฐ์ธ๋ฉ์ ์ ๊ณตํ๋ ๊ฒ ์ ๋๋ค.
์ด๋ ๊ฒ MapStruct๋ ๋ง์ ์ฅ์ ์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ MapStruct ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค.
๋, ๋ฐ์ ๊ตฌ๊ธ ํธ๋ ๋๋ก ๋ดค์ ๋๋ MapStruct๊ฐ Java Mapping ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๊ณ ์๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
์์กด์ฑ ์ค์
MapStruct์ Gradle ์์กด์ฑ ์ค์ ์ ์๋์ ๊ฐ์ต๋๋ค.
dependencies {
...
implementation 'org.mapstruct:mapstruct:1.5.4.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.4.Final'
}
Entity/Dto ์์ฑ
์์ ์ ์ฌ์ฉํ Entity์ Dto ๊ฐ์ฒด๋ ์๋์ ๊ฐ์ต๋๋ค.
UserEntity
@ToString
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserEntity {
private Long id;
private String password;
private String name;
private String nickName;
private Date createDate;
@Builder
private UserEntity(Long id, String password, String name,
String nickName, Date createDate) {
this.id = id;
this.password = password;
this.name = name;
this.nickName = nickName;
this.createDate = createDate;
}
}
UserDto
@Getter
@Setter
@ToString
public class UserDTO {
private Long id;
private String password;
private String name;
}
Mapper ์์ฑ ๋ฐ ํ ์คํธ
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
UserEntity userDTOToEntity(UserDTO userDTO);
UserDTO userEntityToDTO(UserEntity userEntity);
}
- ๊ธฐ๋ณธ์ ์ผ๋ก๋ ์ธํฐํ์ด์ค์ @Mapper๋ฅผ ๋ถ์ด๋ฉด ๋ฉ๋๋ค. @Mapper๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด MapStruct๊ฐ ์๋์ผ๋ก UserMapper๋ฅผ ์์๋ฐ์์ UserMapperImpl๋ฅผ ๊ตฌํํด์ค๋๋ค. (์๋์ ๊ฐ์ด ๊ตฌํ๋ ๋ถ๋ถ์ target -> generated-sources->...->Mapper๊ฐ ์๋ ํด๋์์ ๋ณผ ์ ์์ต๋๋ค.)
- MapStruct์์๋ UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); ๊ฐ์ ๋ฐฉ์์ผ๋ก Mapper Bean์ ๋ง๋๋ ๊ฒ์ ๊ถ์ฅํ๋ค๊ณ ํฉ๋๋ค.
- @Mapper(componentModel = "spring")๊ณผ @Autowired๋ฅผ ์ด์ฉํ์ฌ ๋ง๋ค ์๋ ์์ต๋๋ค.
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-06-03T16:00:52+0900",
comments = "version: 1.4.2.Final, compiler: Eclipse JDT (IDE) 1.3.1200.v20200916-0645, environment: Java 15.0.2 (Oracle Corporation)"
)
public class UserMapperImpl implements UserMapper {
@Override
public UserEntity userDTOToEntity(UserDTO userDTO) {
if ( userDTO == null ) {
return null;
}
UserEntityBuilder userEntity = UserEntity.builder();
userEntity.id( userDTO.getId() );
userEntity.name( userDTO.getName() );
userEntity.password( userDTO.getPassword() );
return userEntity.build();
}
@Override
public UserDTO userEntityToDTO(UserEntity userEntity) {
if ( userEntity == null ) {
return null;
}
UserDTO userDTO = new UserDTO();
userDTO.setId( userEntity.getId() );
userDTO.setName( userEntity.getName() );
userDTO.setPassword( userEntity.getPassword() );
return userDTO;
}
}
๋ฉ์๋์ ํ๋ผ๋ฏธํฐ์ ์ค๋ ๊ฐ์ฒด๋ Getter, ๋ฉ์๋๊ฐ ๋ฆฌํดํ๋ ๊ฐ์ฒด๋ Setter๊ฐ ํ์ํ์ง๋ง, Target ๊ฐ์ฒด(๋ฉ์๋๊ฐ ๋ฆฌํดํ๋ ๊ฐ์ฒด)์ @Builder ์ด๋ ธํ ์ด์ ์ด ๋ฌ๋ ค์๋ค๋ฉด Builder ๋ฉ์๋๋ฅผ ์ฐ์ ์ฌ์ฉํฉ๋๋ค. (userDTOToEntity๋ฉ์๋๋ฅผ ๋ณด๋ฉด Builder๋ฅผ ์ด์ฉํ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.)
๋, @Mapping ์ด๋ ธํ ์ด์ ๊ณผ ์์ฑ์ ์ด์ฉํด ๋ค์ํ ๊ฒฝ์ฐ๋ฅผ ์ค์ ํด ์ค ์ ์์ต๋๋ค. (์ด์ ๋ํ ๋ด์ฉ์ ์๋์์ ๋ค๋ฃจ๊ฒ ์ต๋๋ค.)
Test
@Test
public void MapStructTest() throws Exception {
UserEntity userEntity = UserEntity.builder()
.id(1L)
.password("testPassword")
.name("testName")
.nickName("testNickName")
.createDate(new Date())
.build();
// Entity โก๏ธ DTO
UserDTO resultDTO = UserMapper.INSTANCE.userEntityToDTO(userEntity);
// DTO โก๏ธ Entity, Setter๊ฐ ์์ด๋ @Builder๊ฐ ๋ถ์ด์๋ค๋ฉด ๋ณํ ๊ฐ๋ฅ
UserEntity resultEntity = UserMapper.INSTANCE.userDTOToEntity(resultDTO);
System.out.println(resultDTO);
System.out.println(resultEntity);
}
INSTANCE๋ฅผ ์ด์ฉํด ๋ณํ ๋ฉ์๋๋ฅผ ๊ฐ์ ธ์ ๊ฐ์ฒด๋ฅผ Mappingํ ์ ์์ต๋๋ค.
@Mapping์ ์ด์ฉํ ๋ค์ํ Mapping
MapStruct๋ @Mapping ์ด๋ ธํ ์ด์ ์ ์์ฑ์ ์ด์ฉํด ๋ค์ํ ๊ฒฝ์ฐ์ Mapping์ ์ค์ ํด์ค ์ ์์ต๋๋ค.
์๋ก ๋ค๋ฅธ ์์ฑ ๋งคํ
์์ UserDTO์์ ๋๋ค์์ nick์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ์ถ๊ฐํ๊ณ UserEntity์ nickName์ UserDTO์ nick์ Mappingํด์ผ ํ๋ ๊ฒฝ์ฐ source, target ์์ฑ์ ์ด์ฉํด ์ค์ ํด์ค ์ ์์ต๋๋ค.
@Getter
@Setter
@ToString
public class UserDTO {
private Long id;
private String password;
private String name;
private String nick;
}
์๋์ ๊ฐ์ด Mapping ๋ฉ์๋์ @Mapping(source = "ํ๋ผ๋ฏธํฐ ๊ฐ์ฒด์ ๋ณ์์ด๋ฆ", target = "๋ฆฌํด ๊ฐ์ฒด์ ๋ณ์์ด๋ฆ")์ ๊ฐ์ด ์ค์ ํด์ฃผ๋ฉด ๋ฉ๋๋ค.
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping(source = "nick", target = "nickName")
UserEntity userDTOToEntity(UserDTO userDTO);
@Mapping(source = "nickName", target = "nick")
UserDTO userEntityToDTO(UserEntity userEntity);
}
ํน์ ์์ฑ ์์๋ก ์ถ๊ฐ
UserDTO์ message ์์ฑ์ ์ถ๊ฐํ๊ณ ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด ์์๋ก ๊ฐ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
@Getter
@Setter
@ToString
public class UserDTO {
private Long id;
private String password;
private String name;
private String nick;
private String message;
}
์๋์ ๊ฐ์ด ํ๋ผ๋ฏธํฐ์ message๋ฅผ ์ถ๊ฐํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ๋ ๊ธฐ์กด์ @Mapping(source = "nickName", target = "nick")์์ ํ๋ผ๋ฏธํฐ๊ฐ ์ฌ๋ฌ ๊ฐ๋ผ์ source(ํ๋ผ๋ฏธํฐ ๊ฐ์ฒด)์ nickName์ด ์ด๋ค ํ๋ผ๋ฏธํฐ ๊ฐ์ฒด์ ๊ฒ์ธ์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ @Mapping(source = "userEntity.nickName", target = "nick") ๊ฐ์ด ๊ฐ์ฒด๋ช ์ ๋ช ์ํด์ค๋๋ค.
expression = "java(message + \".msg\")"์ฒ๋ผ expression์์ฑ์ ์ฌ์ฉํด message๋ค์ ์๋์ผ๋ก .msg๋ฅผ ๋ถ์ผ ์ ์์ต๋๋ค. java()์์๋ ๊ฐ์ฒด๊ฐ ๋ค์ด๊ฐ์๋ ์๊ณ , ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋ฑ ๋ค์ํ๊ฒ ํ์ฉํ ์ ์์ต๋๋ค.
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping(source = "nick", target = "nickName")
UserEntity userDTOToEntity(UserDTO userDTO);
@Mapping(source = "userEntity.nickName", target = "nick")
@Mapping(target = "message", expression = "java(message + \".msg\")")
UserDTO userEntityToDTO(UserEntity userEntity, String message);
}
๊ฐ์ฒด ์์ฑ ์ถ๊ฐ
Address๋ผ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ , UserDTO์ Address๊ฐ์ฒด๋ฅผ ๊ฐ์ง๋ ์์ฑ์ ์ถ๊ฐํด์ค๋๋ค.
@Getter
@Setter
@ToString
public class Address {
private String address;
private int addressNum;
}
@Getter
@Setter
@ToString
public class UserDTO {
private Long id;
private String password;
private String name;
private String nick;
private String message;
private Address add;
}
์๋์ ๊ฐ์ด ์ฌ๋ฌ๊ฐ์ @Mapping์ ์ด์ฉํด source, target์ ์ง์ ํด์ค ์ ์์ต๋๋ค.
UserDTO์ Address์์ฑ์ ์ด๋ฆ์ add์ด๊ณ ํ๋ผ๋ฏธํฐ๋ก ๋ค์ด์จ Address ๊ฐ์ฒด์ ์ด๋ฆ์ address์ด๊ธฐ ๋๋ฌธ์ source, target์ผ๋ก ์ง์ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
์ ์ฑ ์ค์ ๋ฐ ์์ฑ ๋ฌด์
UserEntity์๋ createDate๊ฐ ์๋๋ฐ DTO์๋ ์๊ธฐ ๋๋ฌธ์ DTO โก๏ธ Entity๋ก ๋ณํํ ๋ createDate์๋ null ๊ฐ์ด ๋ค์ด๊ฐ๊ฒ ๋ฉ๋๋ค.
์ด ๋, @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)์ ์ด์ฉํด ์ ์ฑ ์ ์ค์ ํด์ target ๊ฐ์ฒด์ ๋งคํ ์ ๋งคํ๋์ง ์์ ์์ฑ์ด ์๋ค๋ฉด ์ปดํ์ผ ์๋ฌ๋ฅผ ๋ฐ์์ํค๊ฒ ํ ์ ์์ต๋๋ค.
ํ์ง๋ง @Mapping์ ignore์์ฑ์ ์ด์ฉํด ๋งคํ๋์ง ์๋ ์์ฑ์ ๋ฌด์ํ๊ฒ ํ ์ ์์ต๋๋ค.
// ์ ์ฑ
์ค์
@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
// ignore = true๋ก ๋ฌด์
@Mapping(target = "createDate", ignore = true)
@Mapping(source = "nick", target = "nickName")
UserEntity userDTOToEntity(UserDTO userDTO);
@Mapping(source = "userEntity.nickName", target = "nick")
@Mapping(source = "address", target = "add")
UserDTO userEntityToDTO(UserEntity userEntity, String message, Address address);
}
์ ์ฑ
๋งคํ ์ ์ฑ (Policy)๊ณผ ์ ๋ต(Strategy)๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค. ์๋๋ ๋ช ๊ฐ์ง ์ ์ฉํ ๋งคํ ์ ์ฑ ๊ณผ ์ ๋ต์ ๋ํ ์ค๋ช ์ ๋๋ค.
์ ์ฑ | ๊ฐ | ์ค๋ช |
unmappedSourcePolicy | IGNORE(default), WARN, ERROR | Source์ ํ๋๊ฐ Target์ ๋งคํ๋์ง ์์ ๋ ์ ์ฑ ์ ๋๋ค. ์, ERROR๋ก ์ค์ ํ๋ฉด ๋งคํ ์ Source.aField๊ฐ ์ฌ์ฉ๋์ง ์๋๋ค๋ฉด ์ปดํ์ผ ์ค๋ฅ๊ฐ ๋ฐ์์ํต๋๋ค. |
unmappedTargetPolicy | IGNORE, WARN(default), ERROR | Target์ ํ๋๊ฐ ๋งคํ๋์ง ์์ ๋ ์ ์ฑ ์ ๋๋ค. ์, ERROR๋ก ์ค์ ํ๋ฉด ๋งคํ ์ Target.aField์ ๊ฐ์ด ๋งคํ๋์ง ์๋๋ค๋ฉด ์ปดํ์ผ ์ค๋ฅ๊ฐ ๋ฐ์์ํต๋๋ค. |
typeConversionPolicy | IGNORE(default), WARN, ERROR | ํ์ ๋ณํ ์ ์ ์ค์ด ๋ฐ์ํ ์ ์์ ๋ ์ ์ฑ ์ ๋๋ค. ์, ERROR๋ก ์ค์ ํ๋ฉด long์์ int๋ก ๊ฐ์ ๋๊ธธ ๋ ๊ฐ์ ์ ์ค์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์ ์ปดํ์ผ ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค. |
์ ๋ต | ๊ฐ | ์ค๋ช |
nullValueMappingStrategy | RETURN_NULL(default), RETURN_DEFAULT | Source๊ฐ null์ผ ๋ ์ ์ฑ ์ ๋๋ค. |
nullValuePropertyMappingStrategy | SET_TO_NULL(default), SET_TO_DEFAULT, IGNORE | Source์ ํ๋๊ฐ null์ผ ๋ ์ ์ฑ ์ ๋๋ค. |
Mapping ์ฝ๋ ์ง์ ๊ตฌํ
๊ฐ๋ MapStruct์์ ๋งคํ ์ฝ๋๋ฅผ ๊ตฌํํ์ง ๋ชปํ๊ฑฐ๋ ์ง์ ๊ตฌํํด์ผ๋ ๋๊ฐ ์์ต๋๋ค. MapStruct๋ default ๋ฉ์๋๋ฅผ ์ด์ฉํด Mapping ๋ฉ์๋๋ฅผ ์ง์ ๊ตฌํํ ์ ์๊ฒ ํด์ค๋๋ค.
๋ค์์ ๊ฐ์ฒด๋ฅผ String์ผ๋ก Mappingํ๋ ๋ฉ์๋๋ฅผ ์ง์ ๊ตฌํํ ๊ฒ์ ๋๋ค.
@Mapper
public interface JsonMapper {
ObjectMapper OBJECT_MAPPER = new ObjectMapper();
default String toString(Object obj) {
try {
return OBJECT_MAPPER.writeValueAsString(obj);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
ObjectMapper๋ Jackson์์ Java Object์ JSON์ฌ์ด์ ๋ณํ์ ์ฝ๊ฒ ํด์ฃผ๋ ํด๋์ค์ ๋๋ค.
- writeValueAsString(obj) : obj๊ฐ์ฒด๋ฅผ Json String์ผ๋ก ๋ณํ์์ผ ์ค๋๋ค.
- readValue(arg, type) : arg์ type์ ํด๋นํ๋ ํด๋์ค๋ก ๋ณํํ ์ ์์ต๋๋ค. Class๊ฐ์ฒด, TypeReference๊ฐ ์ฌ ์ ์์ต๋๋ค.
- ex) OBJECT_MAPPER.readValue(arg, ArrayList.class); โก๏ธ arg์ ํด๋นํ๋ Json String์ ArrayList๋ก ๋ณํํฉ๋๋ค.
Mapping ์์ฑ ์ค์ ๊ณตํตํ
Mapper๊ฐ ๋ง์์ ธ์ Mapper๋ง๋ค์ ์ค์ ์ค ์ค๋ณต์ด ๋ฐ์ํ ๋ ์์ฑ ์ค์ ์ ๊ณตํตํํ ์ ์์ต๋๋ค. MapStructMapperConfig๋ฅผ ๋ง๋ค์ด @MapperConfig์ด๋ ธํ ์ด์ ์ ์ด์ฉํด ๊ณตํตํํ ์์ฑ์ ์ค์ ํด์ค๋๋ค.
ํน์ ํ์ ์ด๋ ๊ฐ์ฒด ๊ฐ Mapping์ ์ค์ค๋กํ ์ ์๊ฑฐ๋ ๋ค๋ฅธ Mapper๋ฅผ ์ด์ฉํด์ผ ํ ๋ uses์์ฑ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. uses = JsonMapper.class๋ก ์ค์ ํด์ฃผ๋ฉด ๊ฐ์ฒด์์ String์ผ๋ก ๋ณํ์ด ํ์ํ ๋ JsonMapper๋ฅผ ์ฌ์ฉํฉ๋๋ค.
@MapperConfig(unmappedTargetPolicy = ReportingPolicy.ERROR, uses = JsonMapper.class)
public interface MapStructMapperConfig {
}
์๋์ ๊ฐ์ด Mapper๋ง๋ค ์ฌ์ฉํ ์ ์์ง๋ง, ์ฃผ์์ฒ๋ผ JsonMapper์ ์ ์ฉํ๊ฒ ๋๋ฉด `uses = JsonMapper.class`๋๋ฌธ์ ์ํ์ฐธ์กฐ๊ฐ ์ผ์ด๋ ์ ์์ผ๋ ์กฐ์ฌํด์ผ ํฉ๋๋ค.
@Mapper(config = MapStructMapperConfig.class)
public interface UserMapper {
...
}
// @Mapper(config = MapStructMapperConfig.class)
@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface JsonMapper {
...
}
์ฐธ๊ณ ๋งํฌ
- https://huisam.tistory.com/entry/mapStruc
- https://mangchhe.github.io/spring/2021/01/25/ModelMapperAndMapStruct/
- https://meetup.toast.com/posts/213
- https://wise-develop.tistory.com/18
- https://asfirstalways.tistory.com/221
- https://engaspect.tistory.com/27
- https://mangchhe.github.io/spring/2021/01/25/ModelMapperAndMapStruct/