add slf4j examples
This commit is contained in:
@@ -1,215 +1,229 @@
|
||||
# ModelMapper 소개
|
||||
### ModelMapper 소개 및 사용 방법
|
||||
|
||||
ModelMapper는 Java 객체 간의 매핑을 쉽게 해주는 라이브러리입니다. 복잡한 객체 변환 코드를 작성할 필요 없이 객체의 속성들을 자동으로 매핑해주어 개발 시간을 단축하고 코드의 가독성을 높여줍니다.
|
||||
ModelMapper는 자바에서 객체 간 매핑을 간편하게 처리할 수 있도록 도와주는 오픈소스 라이브러리입니다. DTO(Data Transfer Object)와 엔티티(Entity) 간의 변환 작업을 수동으로 작성하는 대신, ModelMapper를 사용하면 코드의 중복을 줄이고 가독성을 높일 수 있습니다. 이 라이브러리는 객체의 필드 이름과 타입을 기반으로 자동 매핑을 수행하며, 필요에 따라 사용자 정의 매핑 규칙을 추가할 수도 있습니다.
|
||||
|
||||
## ModelMapper의 주요 특징
|
||||
ModelMapper의 주요 특징은 다음과 같습니다:
|
||||
|
||||
- **타입 안전성**: 컴파일 시점에서 타입 오류를 확인할 수 있습니다.
|
||||
- **자동 매핑**: 이름과 타입이 일치하는 속성들을 자동으로 매핑합니다.
|
||||
- **커스텀 매핑**: 복잡한 매핑 로직을 위한 커스텀 컨버터 지원
|
||||
- **깊은 매핑**: 중첩된 객체 구조도 쉽게 매핑 가능
|
||||
- **설정 유연성**: 다양한 매핑 전략 및 설정 제공
|
||||
- **자동 매핑**: 필드 이름이 동일하면 별도의 설정 없이 매핑 가능.
|
||||
- **유연성**: 복잡한 매핑 요구사항을 커스터마이징 가능.
|
||||
- **간결함**: boilerplate 코드를 줄여 개발 생산성 향상.
|
||||
|
||||
## ModelMapper 사용 방법
|
||||
---
|
||||
|
||||
### 1. 의존성 추가
|
||||
### 의존성 추가
|
||||
|
||||
Maven을 사용한다면 pom.xml에 다음 의존성을 추가합니다:
|
||||
ModelMapper를 사용하려면 먼저 프로젝트에 의존성을 추가해야 합니다. Maven을 사용하는 경우 `pom.xml`에 다음 코드를 추가하세요:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.modelmapper</groupId>
|
||||
<artifactId>modelmapper</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.2.0</version> <!-- 최신 버전 확인 필요 -->
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Gradle을 사용한다면 build.gradle에 다음을 추가합니다:
|
||||
Gradle을 사용하는 경우 `build.gradle`에 아래를 추가합니다:
|
||||
|
||||
```groovy
|
||||
implementation 'org.modelmapper:modelmapper:3.0.0'
|
||||
```gradle
|
||||
implementation 'org.modelmapper:modelmapper:3.2.0' // 최신 버전 확인 필요
|
||||
```
|
||||
|
||||
### 2. 기본 사용법
|
||||
---
|
||||
|
||||
```java
|
||||
// ModelMapper 인스턴스 생성
|
||||
ModelMapper modelMapper = new ModelMapper();
|
||||
### 기본 사용 예시
|
||||
|
||||
// 소스 객체에서 대상 객체로 매핑
|
||||
DestinationType destination = modelMapper.map(source, DestinationType.class);
|
||||
```
|
||||
아래는 ModelMapper를 사용해 간단한 객체 간 매핑을 수행하는 예제입니다.
|
||||
|
||||
### 3. 실제 사용 예시
|
||||
#### 1. 엔티티와 DTO 클래스 정의
|
||||
|
||||
다음은 사용자 정보를 담은 엔티티와 DTO 간의 변환 예시입니다:
|
||||
먼저 매핑할 두 클래스를 정의합니다:
|
||||
|
||||
```java
|
||||
// 엔티티 클래스
|
||||
public class User {
|
||||
private Long id;
|
||||
private String name;
|
||||
private String email;
|
||||
private String password;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private Address address;
|
||||
|
||||
// 생성자, getter, setter 생략
|
||||
}
|
||||
|
||||
public class Address {
|
||||
private String street;
|
||||
private String city;
|
||||
private String country;
|
||||
private String zipCode;
|
||||
|
||||
// 생성자, getter, setter 생략
|
||||
// Getter와 Setter
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
}
|
||||
|
||||
// DTO 클래스
|
||||
public class UserDTO {
|
||||
private Long id;
|
||||
private String name;
|
||||
private String email;
|
||||
private String fullName;
|
||||
private AddressDTO address;
|
||||
|
||||
// 생성자, getter, setter 생략
|
||||
}
|
||||
|
||||
public class AddressDTO {
|
||||
private String street;
|
||||
private String city;
|
||||
private String country;
|
||||
private String zipCode;
|
||||
|
||||
// 생성자, getter, setter 생략
|
||||
}
|
||||
|
||||
// 매핑 예시
|
||||
public class UserService {
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public UserService() {
|
||||
this.modelMapper = new ModelMapper();
|
||||
|
||||
// firstName과 lastName을 fullName으로 매핑하는 커스텀 설정
|
||||
modelMapper.createTypeMap(User.class, UserDTO.class)
|
||||
.addMappings(mapper -> {
|
||||
mapper.map(src -> src.getFirstName() + " " + src.getLastName(),
|
||||
UserDTO::setFullName);
|
||||
});
|
||||
}
|
||||
|
||||
public UserDTO convertToDTO(User user) {
|
||||
return modelMapper.map(user, UserDTO.class);
|
||||
}
|
||||
|
||||
public User convertToEntity(UserDTO userDTO) {
|
||||
return modelMapper.map(userDTO, User.class);
|
||||
}
|
||||
// Getter와 Setter
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 고급 매핑 기능
|
||||
#### 2. ModelMapper로 매핑
|
||||
|
||||
#### 커스텀 매핑 설정
|
||||
이제 ModelMapper를 사용해 `User` 객체를 `UserDTO`로 변환해봅시다:
|
||||
|
||||
```java
|
||||
// 속성 이름이 다른 경우 명시적 매핑
|
||||
modelMapper.createTypeMap(Source.class, Destination.class)
|
||||
.addMapping(Source::getSourceProperty, Destination::setTargetProperty);
|
||||
import org.modelmapper.ModelMapper;
|
||||
|
||||
// 조건부 매핑
|
||||
modelMapper.getConfiguration().setPropertyCondition(context -> {
|
||||
// 조건에 따라 true/false 반환
|
||||
return context.getSource() != null;
|
||||
});
|
||||
|
||||
// 타입 변환 매핑
|
||||
Converter<String, Date> stringToDateConverter =
|
||||
ctx -> ctx.getSource() == null ? null : new SimpleDateFormat("yyyy-MM-dd").parse(ctx.getSource());
|
||||
|
||||
modelMapper.createTypeMap(Source.class, Destination.class)
|
||||
.addMappings(mapper -> mapper.using(stringToDateConverter)
|
||||
.map(Source::getDateAsString, Destination::setDate));
|
||||
```
|
||||
|
||||
#### 매핑 전략 설정
|
||||
|
||||
```java
|
||||
// 필드 매핑 전략 (필드 이름 기준 매핑)
|
||||
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
|
||||
|
||||
// 접근 방식 설정 (필드 직접 접근)
|
||||
modelMapper.getConfiguration().setFieldAccessLevel(AccessLevel.PRIVATE);
|
||||
modelMapper.getConfiguration().setFieldMatchingEnabled(true);
|
||||
```
|
||||
|
||||
### 5. 컬렉션 매핑
|
||||
|
||||
```java
|
||||
// List 매핑
|
||||
List<UserDTO> userDTOs = users.stream()
|
||||
.map(user -> modelMapper.map(user, UserDTO.class))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Type Token 사용하여 컬렉션 매핑
|
||||
Type listType = new TypeToken<List<UserDTO>>() {}.getType();
|
||||
List<UserDTO> userDTOs = modelMapper.map(users, listType);
|
||||
```
|
||||
|
||||
## 실제 사용 사례
|
||||
|
||||
Spring Boot 애플리케이션에서 ModelMapper를 빈으로 등록하여 사용하는 예시:
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
public class ApplicationConfig {
|
||||
|
||||
@Bean
|
||||
public ModelMapper modelMapper() {
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// ModelMapper 인스턴스 생성
|
||||
ModelMapper modelMapper = new ModelMapper();
|
||||
|
||||
// 엄격한 매핑 전략 설정
|
||||
modelMapper.getConfiguration()
|
||||
.setMatchingStrategy(MatchingStrategies.STRICT)
|
||||
.setSkipNullEnabled(true)
|
||||
.setFieldMatchingEnabled(true)
|
||||
.setFieldAccessLevel(AccessLevel.PRIVATE);
|
||||
|
||||
return modelMapper;
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
public class ProductService {
|
||||
|
||||
private final ProductRepository productRepository;
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
@Autowired
|
||||
public ProductService(ProductRepository productRepository, ModelMapper modelMapper) {
|
||||
this.productRepository = productRepository;
|
||||
this.modelMapper = modelMapper;
|
||||
}
|
||||
|
||||
public ProductDTO getProduct(Long id) {
|
||||
Product product = productRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Product not found"));
|
||||
|
||||
return modelMapper.map(product, ProductDTO.class);
|
||||
}
|
||||
|
||||
public List<ProductDTO> getAllProducts() {
|
||||
List<Product> products = productRepository.findAll();
|
||||
|
||||
return products.stream()
|
||||
.map(product -> modelMapper.map(product, ProductDTO.class))
|
||||
.collect(Collectors.toList());
|
||||
// User 객체 생성 및 데이터 설정
|
||||
User user = new User();
|
||||
user.setId(1L);
|
||||
user.setName("홍길동");
|
||||
user.setEmail("hong@example.com");
|
||||
|
||||
// User -> UserDTO로 매핑
|
||||
UserDTO userDTO = modelMapper.map(user, UserDTO.class);
|
||||
|
||||
// 결과 출력
|
||||
System.out.println("ID: " + userDTO.getId());
|
||||
System.out.println("Name: " + userDTO.getName());
|
||||
System.out.println("Email: " + userDTO.getEmail());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 결론
|
||||
**출력 결과:**
|
||||
|
||||
ModelMapper는 Java 애플리케이션에서 객체 간 매핑을 간소화하는 강력한 도구입니다. 자동 매핑 기능으로 반복적인 코드를 줄이고, 커스텀 매핑 설정으로 복잡한 변환 로직도 깔끔하게 처리할 수 있습니다. 특히 엔티티와 DTO 간의 변환이 많은 웹 애플리케이션에서 유용하게 활용할 수 있습니다.
|
||||
```
|
||||
ID: 1
|
||||
Name: 홍길동
|
||||
Email: hong@example.com
|
||||
```
|
||||
|
||||
위 예제에서 `modelMapper.map()` 메서드는 `User` 객체의 필드를 `UserDTO`로 자동으로 매핑합니다. 필드 이름과 타입이 동일하기 때문에 별도의 설정 없이도 동작합니다.
|
||||
|
||||
---
|
||||
|
||||
### 고급 사용 예시: 커스터마이징 매핑
|
||||
|
||||
필드 이름이 다르거나 특정 변환 로직이 필요한 경우, ModelMapper의 설정을 커스터마이징할 수 있습니다.
|
||||
|
||||
#### 1. 필드 이름이 다른 경우
|
||||
|
||||
예를 들어, `User` 클래스의 `email` 필드를 `UserDTO`의 `emailAddress`로 매핑한다고 가정해봅시다.
|
||||
|
||||
```java
|
||||
// 수정된 UserDTO 클래스
|
||||
public class UserDTO {
|
||||
private Long id;
|
||||
private String name;
|
||||
private String emailAddress; // 필드 이름 변경
|
||||
|
||||
// Getter와 Setter
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getEmailAddress() { return emailAddress; }
|
||||
public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; }
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 커스터마이징 매핑 설정
|
||||
|
||||
ModelMapper에 매핑 규칙을 추가합니다:
|
||||
|
||||
```java
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.modelmapper.PropertyMap;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// ModelMapper 인스턴스 생성
|
||||
ModelMapper modelMapper = new ModelMapper();
|
||||
|
||||
// 커스터마이징 매핑 규칙 추가
|
||||
modelMapper.addMappings(new PropertyMap<User, UserDTO>() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
map().setEmailAddress(source.getEmail()); // email -> emailAddress
|
||||
}
|
||||
});
|
||||
|
||||
// User 객체 생성
|
||||
User user = new User();
|
||||
user.setId(1L);
|
||||
user.setName("홍길동");
|
||||
user.setEmail("hong@example.com");
|
||||
|
||||
// 매핑 수행
|
||||
UserDTO userDTO = modelMapper.map(user, UserDTO.class);
|
||||
|
||||
// 결과 출력
|
||||
System.out.println("ID: " + userDTO.getId());
|
||||
System.out.println("Name: " + userDTO.getName());
|
||||
System.out.println("Email Address: " + userDTO.getEmailAddress());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**출력 결과:**
|
||||
|
||||
```
|
||||
ID: 1
|
||||
Name: 홍길동
|
||||
Email Address: hong@example.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 추가 기능: 리스트 매핑
|
||||
|
||||
여러 객체를 포함한 리스트를 매핑할 수도 있습니다:
|
||||
|
||||
```java
|
||||
import org.modelmapper.ModelMapper;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
ModelMapper modelMapper = new ModelMapper();
|
||||
|
||||
// User 리스트 생성
|
||||
List<User> users = Arrays.asList(
|
||||
new User(1L, "홍길동", "hong@example.com"),
|
||||
new User(2L, "김영희", "kim@example.com")
|
||||
);
|
||||
|
||||
// 리스트 매핑
|
||||
List<UserDTO> userDTOs = users.stream()
|
||||
.map(user -> modelMapper.map(user, UserDTO.class))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 결과 출력
|
||||
userDTOs.forEach(dto -> System.out.println(dto.getName() + ": " + dto.getEmail()));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**출력 결과:**
|
||||
|
||||
```
|
||||
홍길동: hong@example.com
|
||||
김영희: kim@example.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 결론
|
||||
|
||||
ModelMapper는 객체 간 매핑을 단순화하고 개발자의 시간을 절약해주는 강력한 도구입니다. 기본적인 자동 매핑부터 복잡한 커스터마이징까지 지원하므로, 프로젝트 요구사항에 따라 적절히 활용할 수 있습니다. 위 예제를 참고하여 실제 프로젝트에 적용해보세요! 추가 질문이 있다면 언제든 물어보세요.
|
||||
Reference in New Issue
Block a user