2025-04-08T19:56:24
This commit is contained in:
200
docs/21_model_mapper.md
Normal file
200
docs/21_model_mapper.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# **ModelMapper와 DTO 패턴**
|
||||
|
||||
Spring Boot 애플리케이션에서 **DTO(Data Transfer Object) 패턴**은 엔티티(Entity)와 클라이언트 간의 데이터를 효율적으로 주고받기 위한 중요한 패턴입니다.
|
||||
이 과정에서 **ModelMapper**는 DTO와 엔티티 간의 변환을 자동화하는 도구로 많이 사용됩니다.
|
||||
|
||||
이번 글에서는 **ModelMapper의 개념과 사용법**, 그리고 **DTO 패턴의 개념과 장점**을 설명하겠습니다.
|
||||
|
||||
---
|
||||
|
||||
## **1. DTO(Data Transfer Object) 패턴이란?**
|
||||
|
||||
### **📌 DTO란?**
|
||||
- 클라이언트와 서버 간의 **데이터 교환을 위한 객체**
|
||||
- **Entity와 분리**하여 사용
|
||||
- 보안, 데이터 무결성, 성능 최적화를 위해 활용
|
||||
|
||||
---
|
||||
|
||||
## **1.1 DTO 패턴을 사용하는 이유**
|
||||
|
||||
| 문제 | 해결책 (DTO) |
|
||||
|------|------------|
|
||||
| **엔티티를 직접 반환하면 보안 문제가 발생할 수 있음** | **필요한 데이터만 DTO에 담아 전송** |
|
||||
| **JPA 엔티티는 영속성 컨텍스트에서 관리되므로 직접 수정하면 원치 않는 변경 발생 가능** | **DTO를 통해 영속성과 분리된 객체로 전달** |
|
||||
| **엔티티가 클라이언트에 직접 노출되면 변경 시 API가 영향을 받음** | **DTO를 사용하여 API 구조를 안정적으로 유지** |
|
||||
|
||||
---
|
||||
|
||||
## **1.2 DTO 패턴 적용 예제**
|
||||
|
||||
### **📌 Entity 클래스**
|
||||
```java
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
private String email;
|
||||
private String password; // 보안 문제로 DTO에서는 제외
|
||||
}
|
||||
```
|
||||
|
||||
### **📌 DTO 클래스**
|
||||
```java
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserDTO {
|
||||
private String username;
|
||||
private String email;
|
||||
}
|
||||
```
|
||||
✔ **Entity와 달리 `password` 필드를 포함하지 않음** → 보안 강화
|
||||
✔ **불필요한 필드를 제거하여 API 성능 최적화**
|
||||
|
||||
---
|
||||
|
||||
# **2. ModelMapper란?**
|
||||
|
||||
### **📌 ModelMapper란?**
|
||||
- DTO와 Entity 간 변환을 **자동으로 처리해주는 라이브러리**
|
||||
- 수동으로 `set()` 메서드를 호출하지 않아도 DTO ↔ Entity 변환 가능
|
||||
- Spring Boot 프로젝트에서 사용 가능
|
||||
|
||||
---
|
||||
|
||||
## **2.1 ModelMapper 설정 및 사용법**
|
||||
|
||||
### **✅ ModelMapper 의존성 추가**
|
||||
`pom.xml`에 ModelMapper 의존성을 추가합니다.
|
||||
|
||||
```kotlin
|
||||
implementation("org.modelmapper:modelmapper:3.2.2")
|
||||
```
|
||||
|
||||
### **✅ ModelMapper를 Bean으로 등록**
|
||||
Spring Boot에서 `ModelMapper`를 사용하려면 **Bean으로 등록**해야 합니다.
|
||||
|
||||
```java
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class ModelMapperConfig {
|
||||
|
||||
@Bean
|
||||
public ModelMapper modelMapper() {
|
||||
return new ModelMapper();
|
||||
}
|
||||
}
|
||||
```
|
||||
✔ **ModelMapper를 Bean으로 등록하여 서비스에서 주입받아 사용 가능**
|
||||
|
||||
---
|
||||
|
||||
## **2.2 ModelMapper를 활용한 DTO 변환**
|
||||
|
||||
### **✅ DTO로 변환 (Entity → DTO)**
|
||||
```java
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public UserService(ModelMapper modelMapper) {
|
||||
this.modelMapper = modelMapper;
|
||||
}
|
||||
|
||||
public UserDTO convertToDTO(User user) {
|
||||
return modelMapper.map(user, UserDTO.class);
|
||||
}
|
||||
}
|
||||
```
|
||||
✔ `modelMapper.map(user, UserDTO.class)` → **자동으로 User → UserDTO 변환**
|
||||
✔ 수동으로 `setUsername()`, `setEmail()`을 호출할 필요 없음
|
||||
|
||||
---
|
||||
|
||||
### **✅ Entity로 변환 (DTO → Entity)**
|
||||
```java
|
||||
public User convertToEntity(UserDTO userDTO) {
|
||||
return modelMapper.map(userDTO, User.class);
|
||||
}
|
||||
```
|
||||
✔ `UserDTO`를 `User` 엔티티로 변환 가능
|
||||
✔ DB 저장 시 활용
|
||||
|
||||
---
|
||||
|
||||
## **2.3 ModelMapper를 활용한 API 컨트롤러 예제**
|
||||
|
||||
```java
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/users")
|
||||
public class UserController {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
public UserController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public UserDTO getUser(@PathVariable Long id) {
|
||||
User user = userService.getUserById(id); // 가정: userService에서 User 엔티티 조회
|
||||
return userService.convertToDTO(user);
|
||||
}
|
||||
}
|
||||
```
|
||||
✔ 엔티티 대신 `UserDTO`를 반환하여 API 응답을 안전하게 유지
|
||||
✔ **비밀번호(password) 등의 민감한 정보를 클라이언트에 노출하지 않음**
|
||||
|
||||
---
|
||||
|
||||
# **3. DTO vs Entity: 언제 사용해야 할까?**
|
||||
|
||||
| 구분 | DTO | Entity |
|
||||
|------|-----|--------|
|
||||
| **목적** | 클라이언트와 데이터 교환 | DB와 직접 매핑 |
|
||||
| **사용 위치** | 컨트롤러, 서비스 계층 | 리포지토리 계층 |
|
||||
| **영속성 관리** | X (JPA 관리 대상 아님) | O (JPA 관리 대상) |
|
||||
| **보안** | 민감한 정보 제외 가능 | 모든 필드 포함 |
|
||||
|
||||
✔ **API 응답 및 요청에는 DTO 사용**
|
||||
✔ **DB 작업에는 Entity 사용**
|
||||
|
||||
---
|
||||
|
||||
# **4. 정리**
|
||||
|
||||
### ✅ **DTO(Data Transfer Object) 패턴**
|
||||
- **클라이언트와 서버 간 데이터 전송을 위한 객체**
|
||||
- **엔티티를 직접 노출하지 않도록 보호**
|
||||
- **불필요한 필드를 제외하여 성능 최적화**
|
||||
|
||||
### ✅ **ModelMapper 활용**
|
||||
- DTO ↔ Entity 간 변환을 자동화
|
||||
- `modelMapper.map(source, destinationClass)`을 사용하여 변환
|
||||
|
||||
Spring Boot 프로젝트에서 **DTO 패턴과 ModelMapper를 활용하면 보안성과 유지보수성을 높일 수 있습니다.**
|
||||
특히 REST API 설계 시 엔티티를 직접 반환하지 않고 DTO를 사용하면 **보안 강화 및 API 변경 최소화**가 가능합니다. 🚀
|
||||
Reference in New Issue
Block a user