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์ด๋ค.
๐ ์๋ํํด์ฃผ๋ ModelMapper๋ ์๋ ๋ถํฐ ์์์ง์๋์?
ModelMapper ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด๋ ๋๊ตฌ๋ค์ ์๋ ๋ถํฐ ์กด์ฌํ๋ค.
ํ์ง๋ง ๋๋ถ๋ถ ๋ฆฌํ๋ ์ ๊ณผ Setter๋ฅผ ์ฌ์ฉ์ ๊ฐ์ ํ๋ค๋ณด๋ ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ฒ๊น ๋ ํ๋ค์ด์ง๊ณ , ๋ฐํ์ ์ฑ๋ฅ์ ์ํฅ์ ๋ผ์น๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ๊ธฐ์๋ ๋ง์ด ๋ง์ค์ฌ์ก์๋ค.
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;
}
๋ ์์ธํ ๋ด์ฉ์ ๊ณต์๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์. ๊ทผ๋ฐ ๊ทธ๋ ๊ฒ ๊น๊ฒ ๊ณต๋ถํ ํ์๋ ์์ ๋ฏํ๋ค.
'๐ฑBackend > Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
DTO๋ ์ด๋ค Layer์ ํฌํจ๋์ด์ผ ํ๋๊ฐ. (1) | 2022.01.21 |
---|---|
๋ JPA๋ฅผ ์ ๋๋ก ์๊ณ ์ฐ๋ ๊ฒ์ธ๊ฐ (์ ๋ฆฌ์ค..) (0) | 2021.11.17 |
ํ ์คํธ ๋ชจํน Mockito ๋ผ์ด๋ธ๋ฌ๋ฆฌ (0) | 2021.09.07 |
[์ฝ๋๋ถ์๋๊ตฌ]# 3 SonarLint, SonarQube (0) | 2021.08.21 |
[์ฝ๋๋ถ์๋๊ตฌ]#2 Jacoco ์ ์ฉํ๊ธฐ (0) | 2021.08.21 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev