[λ²μ] Data Transfer Object (DTO) in Spring Boot
π‘ μλ³ΈκΈ : https://towardsdev.com/data-transfer-object-dto-in-spring-boot-c00678cc5946
μ΄ κΈμμλ Spring Bootμμ λ°μ΄ν° μ μ‘ κ°μ²΄(DTO)μ μ΄μ μ νꡬνλ©°, μλ DTO μμ±, ModelMapper, Lombokμ ν¬ν¨ν μμ λ€μ μ΄ν΄λ³Ό κ²μ λλ€.
Photo by Joshua Sortino on Unsplash
1. λ°μ΄ν° μ μ‘ κ°μ²΄(DTO)λ 무μμΈκ°?
λ°μ΄ν° μ μ‘ κ°μ²΄(DTO)λ μ ν리μΌμ΄μ μ λ€λ₯Έ κ³μΈ΅ κ° λ°μ΄ν°λ₯Ό μΊ‘μννκ³ μ μ‘νκΈ° μν΄ μ¬μ©λλ λμμΈ ν¨ν΄μ λλ€. DTOλ μΌλ°μ μΌλ‘ νμν νλλ§ ν¬ν¨νλ κ°λ²Όμ΄ κ°μ²΄λ‘, λΉμ§λμ€ λ‘μ§μ ν¬ν¨νμ§ μμ΅λλ€. μ ν리μΌμ΄μ μ λ€λ₯Έ λΆλΆλ€, μλ₯Ό λ€μ΄ νλ‘ νΈμλμ λ°±μλ μ¬μ΄λ λΆμ° μμ€ν λ΄μ λ€μν λ§μ΄ν¬λ‘μλΉμ€ κ°μ λ°μ΄ν°λ₯Ό μ΄λ°νλ κ΅¬μ‘°λ‘ μ¬μ©λ©λλ€.
νΉν Spring Boot μ ν리μΌμ΄μ μμ DTOλ 컨νΈλ‘€λ¬ κ³μΈ΅, μλΉμ€ κ³μΈ΅, κ·Έλ¦¬κ³ μμμ± κ³μΈ΅ κ° λ°μ΄ν°λ₯Ό μ μ‘ν΄μΌ ν λ μ μ©ν©λλ€. DTOλ₯Ό μ¬μ©ν¨μΌλ‘μ¨ λ΄λΆ λ°μ΄ν° λͺ¨λΈκ³Ό μΈλΆ νν(presentation)μ λΆλ¦¬ν μ μμΌλ©°, μ΄λ λ°μ΄ν° μ μ‘μ λν λ λμ ν΅μ λ₯Ό κ°λ₯νκ² ν©λλ€.
2. Spring Boot λ΄μμ DTOλ₯Ό μ¬μ©μ μ΄μ
Spring Boot μ ν리μΌμ΄μ μμ DTOλ₯Ό μ¬μ©νλ©΄ μ¬λ¬ κ°μ§ μ΄μ μ΄ μμ΅λλ€.
- λ°μ΄ν° 격리: DTOλ₯Ό μ¬μ©νλ©΄ μΈλΆ μΈκ³μ λ ΈμΆλλ λ°μ΄ν°λ₯Ό λ΄λΆ λλ©μΈ λͺ¨λΈλ‘λΆν° λΆλ¦¬ν μ μμ΅λλ€. λ―Όκ°νκ±°λ λΆνμν λ°μ΄ν°μ λ ΈμΆμ λ°©μ§νκ³ , λ°μ΄ν° κ΅νμ μν λͺ νν κ·μΉμ μ 곡ν©λλ€.
- μ€λ²ν€λ κ°μ: DTOλ νΉμ ν μ μ€ μΌμ΄μ€μ νμν νλλ§ ν¬ν¨ν μ μμ΄, λ€νΈμν¬λ₯Ό ν΅ν΄ μ μ‘λλ λ°μ΄ν° μμ μ€μΌ μ μμ΅λλ€. μ΄λ ν° κ°μ²΄λ₯Ό μ μ‘ ν λ λ°μνλ λΆλ΄μ μ΅μν ν©λλ€.
- λ²μ κ΄λ¦¬ λ° νΈνμ±: DTOλ λ²μ κ΄λ¦¬λ₯Ό μ©μ΄νκ² νκ³ , μνΈνμ±μ 보μ₯ νλλ° λμμ μ€λλ€. λλ©μΈ λͺ¨λΈκ³Ό λ³κ°λ‘ DTOλ₯Ό λ°μ μν¬μ μμ΄ API λ³κ²½μ λ μ½κ² μ²λ¦¬ν μ μμ΅λλ€.
- 보μ ν₯μ: DTOλ₯Ό ν΅ν΄ λ ΈμΆλλ λ°μ΄ν°λ₯Ό μ μ΄ν¨μΌλ‘μ¨ λ°μ΄ν° μ€μΈμ λ°©μ§νκ³ λ―Όκ°ν μ 보μ λν μ κ·Όμ μ ννμ¬ λ³΄μμ κ°νν μ μμ΅λλ€.
- ν μ€νΈ ν₯μ: DTOλ λ¨μ ν μ€νΈλ₯Ό λ¨μν ν©λλ€. 볡μ‘ν λλ©μΈ κ°μ²΄μ μμ‘΄νμ§ μκ³ ν μ€νΈ μλ리μ€μμ μ½κ² μμ±νκ³ μ‘°μν μ μμ΅λλ€.
3. Spring Bootμμ DTOμ¬μ©νλ λ€μν λ°©λ²
3.1. μλμΌλ‘ DTOλ₯Ό μμ±
μ΄ μ κ·Ό λ°©μμμλ λλ©μΈ μν°ν°μ ꡬ쑰λ₯Ό λ°μν΄ DTO ν΄λμ€λ₯Ό μλμΌλ‘ μμ±ν©λλ€. κ·Έλ° λ€μ λλ©μΈ κ°μ²΄μ DTO μ¬μ΄μ λ°μ΄ν°λ₯Ό 맀ννκΈ° μν μ½λλ₯Ό μμ±ν©λλ€.
public class UserDTO {
private Long id;
private String username;
private String email;
// Constructors, getters, and setters
}
μλμΌλ‘ 맀ννλ κ³Όμ μ΄ μλ controller λ©μλλ₯Ό λ§λ€μ΄ μ£Όλ©΄ λ©λλ€.
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
UserDTO userDTO = new UserDTO();
userDTO.setId(user.getId());
userDTO.setUsername(user.getUsername());
userDTO.setEmail(user.getEmail());
return ResponseEntity.ok(userDTO);
}
}
κ²°κ³Ό**:** GET μμ²μΌλ‘ /api/users/1μ μμ²νλ©΄ μλ΅μΌλ‘ μ μ λ°μ΄ν°λ₯Ό ν¬ν¨ν ****JSONμ λ°μμ μμ΅λλ€.
{
"id": 1,
"username": "john_doe",
"email": "john.doe@example.com"
}
3.2. ModelMapper μ¬μ©
ModelMapperλ₯Ό Spring Boot νλ‘μ νΈμμ λλ©μΈ κ°μ²΄μ DTO κ°μ 맀νμ μλν νκΈ° μν΄ μ¬μ©νλ €λ©΄, pom.xmlμμ ν΄λΉ μμ‘΄μ±μ μΆκ°ν©λλ€. μ΄λ κ² νλ©΄ ModeMappingλ₯Ό μ¬μ©νμ¬ λλ©μΈ κ°μ²΄μ DTO κ°μ 맀νμ μ½κ³ ν¨μ¨μ μΌλ‘ μ²λ¦¬ν μ μμ΅λλ€.
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.4.3</version>
</dependency>
Spring Boot μ ν리μΌμ΄μ μμ ModelMapperλ₯Ό Spring BeanμΌλ‘ μ¬μ©νκΈ° μν΄, Configuration ν΄λμ€ λλ Main Application ν΄λμ€μ Beanμ λ±λ‘ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μ ν리μΌμ΄μ μ 체μμ ModelMapperμ ꡬμ±(Configuration)μ ν μ μμ΅λλ€.
Spring Boot μ ν리μΌμ΄μ μμ ModelMapper Beanμ μμ±νλ λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
import org.modelmapper.ModelMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyApplicationConfig {
@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
}
μ¬κΈ°μ λλ©μΈ κ°μ²΄λ₯Ό DTOλ‘ λ³ννκΈ° μν΄ ModelMapperλ₯Ό μλμ κ°μ΄ μ¬μ©νλ©΄ λ©λλ€.
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private ModelMapper modelMapper; // Autowire the ModelMapper bean
@GetMapping("/{id}")
public ResponseEntity getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
UserDTO userDTO = modelMapper.map(user, UserDTO.class); // Use ModelMapper for mapping
return ResponseEntity.ok(userDTO);
}
}
κ²°κ³Ό: μλ DTO μμ± μμ μ λμΌν κ²°κ³Όκ° λμ΅λλ€.
3.3. Lombok μ¬μ©
Lombok μμ‘΄μ±μ pom.xml νμΌμ μΆκ°νμΈμ.
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
User μν°ν°μ DTOλ₯Ό μμ±νκΈ° μν΄ μλμ κ°μ΄ μμ±νμΈμ.
import lombok.Data;
@Data
public class UserDTO {
private Long id;
private String username;
private String email;
}
μ΄μ λλ©μΈ κ°μ²΄λ₯Ό DTOλ‘ λ³ννκΈ° μν΄ μλμ κ°μ΄ Lombokμ μ¬μ©νλ©΄ λ©λλ€.
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
UserDTO userDTO = UserDTO.builder()
.id(user.getId())
.username(user.getUsername())
.email(user.getEmail())
.build();
return ResponseEntity.ok(userDTO);
}
}
κ²°κ³Ό: μλ DTO μμ± μμ μ λμΌν κ²°κ³Όκ° λμ΅λλ€.
4. DTOμμ λ€μν μ νμ κ° ν¬λ§·ν νκΈ°
DTOμμ λ€μν μ νμ κ°μ ν¬λ§·ν νλ κ²μ λ°μ΄ν°κ° μ§λ ¬νλκ±°λ νμλ λ νΉμ νμμΌλ‘ μ 곡λλλ‘ νλ λ° νμν μΌλ°μ μΈ μꡬμ¬νμ λλ€. ν¬λ§·ν νλ €λ κ°μ μ νμ λ°λΌ, μ΄λ Έν μ΄μ , μ¬μ©μ μ μ λ©μλ λλ μΈλΆ λΌμ΄λΈλ¬λ¦¬λ₯Ό ν¬ν¨ν μ¬λ¬ μ κ·Ό λ°©μμ μ¬μ©ν μ μμ΅λλ€. μλμμλ DTOμμ λ€μν μ νμ κ°μ ν¬λ§·ν νλ λ°©λ²μ λν΄ μ€λͺ νκ² μ΅λλ€.
4.1. Dateμ Time ν¬λ§·
4.1.1. @JsonFormat μ΄λ Έν μ΄μ μ¬μ©(Jackson)
DTOμμ λ μ§μ μκ° κ°μ ν¬λ§·ν νκΈ° μν΄, JSON μ§λ ¬νμ νν μ¬μ©λλ Jackson λΌμ΄λΈλ¬λ¦¬μμ μ 곡νλ @JsonFormat μ΄λ Έν μ΄μ μ μ¬μ©ν μ μμ΅λλ€.
import com.fasterxml.jackson.annotation.JsonFormat;
public class UserDTO {
private Long id;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
private Date registrationDate;
// Other fields, getters, and setters
}
μ΄ μμ μμ registrationDate νλλ₯Ό @JsonFormatμ μ¬μ©ν΄μ λ μ§μ μκ°μ λν΄μ νΉλ³νκ² λ³ννμμ΅λλ€.
4.1.2. SimpleDateFormat μ¬μ©(Custom Method)
DTO ν΄λμ€ λ΄μ μ¬μ©μ μ μ gatter λ©μλλ₯Ό μ 곡ν¨μΌλ‘μ¨ λ μ§μ μκ°μ ν¬λ§·ν ν μλ μμ΅λλ€. μ΄ λ©μλλ ν¬λ§·λ λ μ§λ₯Ό λ¬Έμμ΄λ‘ λ°νν©λλ€.
import java.text.SimpleDateFormat;
public class UserDTO {
private Long id;
private Date registrationDate;
public String getFormattedRegistrationDate() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(registrationDate);
}
// Other fields, getters, and setters
}
4.2. μ«μ ν¬λ§·ν
4.2.1. @NumberFormat μ΄λ Έν μ΄μ μ¬μ© (Spring)
μ«μλ ν΅νμ κ°μ μ«μ κ°μ ν¬λ§·ν νκΈ° μν΄ Springμμ μ 곡νλ @NumberFormat μ΄λ Έν μ΄μ μ μ¬μ©ν μ μμ΅λλ€. μ΄ μ΄λ Έν μ΄μ μ μ¬μ©νλ©΄ μ«μ ν¬λ§·ν ν¨ν΄μ μ§μ ν μ μμ΅λλ€.
import org.springframework.format.annotation.NumberFormat;
public class ProductDTO {
private Long id;
@NumberFormat(pattern = "#,###.00")
private BigDecimal price;
// Other fields, getters, and setters
}
μ΄ μμ μμλ price νλμ @NumberFormat μ΄λ Έν μ΄μ μ μ¬μ©ν΄μ μ«μλ₯Ό ν¬λ§·ν νλ ν¨ν΄μ μ§μ νμμ΅λλ€.
4.2.2. DecimalFormat μ¬μ© (Custom Method)
DTO ν΄λμ€ λ΄μ μ¬μ©μ μ μ getter λ©μλλ₯Ό μ 곡νμ¬ μ«μλ₯Ό ν¬λ§·ν ν μλ μμ΅λλ€. μ΄ λ©μλλ DecimalFormatμ μ¬μ©νμ¬ ν¬λ§·λ μ«μλ₯Ό λ¬Έμμ΄λ‘ λ°νν©λλ€.
import java.text.DecimalFormat;
public class ProductDTO {
private Long id;
private BigDecimal price;
public String getFormattedPrice() {
DecimalFormat df = new DecimalFormat("#,###.00");
return df.format(price);
}
// Other fields, getters, and setters
}
4.3. String ν¬λ§·ν
4.3.1. Custom Methods μ¬μ©
λ¬Έμμ΄ κ°μ ν¬λ§·ν νκΈ° μν΄, νμμ λ°λΌ λ¬Έμμ΄μ μ‘°μνλ μ¬μ©μ μ μ getter λ©μλλ₯Ό DTO ν΄λμ€ λ΄μ μμ±ν μ μμ΅λλ€. μλ₯Ό λ€μ΄, 곡백μ μλ₯΄κ±°λ, λ¨μ΄λ₯Ό λλ¬Έμλ‘ λ§λ€κ±°λ, κΈ°ν λ€λ₯Έ λ¬Έμμ΄ μ‘°μ λ‘μ§μ μ μ©ν μ μμ΅λλ€.
public class ArticleDTO {
private Long id;
private String title;
public String getFormattedTitle() {
// Custom formatting logic here
return title.trim(); // Example: Trim whitespace
}
// Other fields, getters, and setters
}
4.4. Enum ν¬λ§·ν
4.4.1. Custom Method μ¬μ©
DTOμμ μ΄κ±°ν(enum)μ λ€λ£° λ, μ΄κ±°ν κ°μ ν¬λ§·λ ννμ λ°ννλ μ¬μ©μ μ μ getter λ©μλλ₯Ό μμ±ν μ μμ΅λλ€. μλ₯Ό λ€μ΄, μ΄κ±°ν κ°μ λλ¬Έμλ‘ λ³ννκ±°λ λ€λ₯Έ ννμ μ¬μ©ν μ μμ΅λλ€.
public class OrderDTO {
private Long id;
private OrderStatus status;
public String getFormattedStatus() {
return status.toString().toUpperCase(); // Example: Convert to uppercase
}
// Other fields, getters, and setters
}
4.5. Boolean ν¬λ§·ν
4.5.1. Custom Methods μ¬μ©
Boolean κ°μ λν΄μλ “true” λλ “falseλμ μ “Yes”, “No”μ κ°μ ν¬λ§·λ ννμ μ¬μ©μ μ μ getter λ©μλλ‘ μμ±ν μ μμ΅λλ€.
public class UserDTO {
private Long id;
private boolean isActive;
public String getFormattedIsActive() {
return isActive ? "Yes" : "No"; // Example: Convert to "Yes" or "No"
}
// Other fields, getters, and setters
}
μ΄λ¬ν μ κ·Ό λ°©λ²λ€μ μ¬μ©ν¨μΌλ‘μ¨, νΉμ μꡬμ¬νμ λ°λΌ DTO λ΄μμ λ€μν μ νμ κ°μ ν¬λ§·ν ν μ μμΌλ©°, DTOκ° μ§λ ¬νλκ±°λ νμλ λ λ°μ΄ν°κ° μνλ νμμΌλ‘ μ 곡λλλ‘ ν μ μμ΅λλ€.
5. μΆκ°μ μΌλ‘ κ³ λ €ν΄μΌ ν μ κ³Ό Best Practice
5.1. DTOμμμ μ ν¨μ± κ²μ¬
DTOλ₯Ό λ€λ£° λ λ°μ΄ν° κ²μ¦μ κ³ λ €νλ κ²μ΄ νμμ μ λλ€. DTOμ λ€μ΄μ€λ λ°μ΄ν°κ° νμν μ μ½ μ‘°κ±΄κ³Ό λΉμ¦λμ€ κ·μΉμ μΆ©μ‘±νλμ§ νμΈνκΈ° μν΄ λ°μ΄ν°λ₯Ό κ²μ¦ν΄μΌ ν©λλ€. Springμ @NotNull, @Size λλ μ¬μ©μ μ μ κ²μ¦ μ΄λ Έν μ΄μ μ μ¬μ©νμ¬ DTO νλλ₯Ό κ²μ¦ν μ μμ΅λλ€.
Springμ @NotBlank μ΄λ Έν μ΄μ μ μ¬μ©ν DTO κ²μ¦μ μλ λ€μκ³Ό κ°μ΅λλ€:
public class UserDTO {
@NotNull
private Long id;
@NotBlank
@Size(min = 5, max = 50)
private String username;
@Email
private String email;
// Constructors, getters, and setters
}
5.2. 볡μ‘ν μ€μ²© κ°μ²΄ DTO
μ€μ μ ν리μΌμ΄μ μμλ μ€μ²©λ κ°μ²΄λ κ΄κ³λ₯Ό λ€λ£° λ DTOκ° λ 볡μ‘ν΄μ§ μ μμ΅λλ€. μ΄λ¬ν ꡬ쑰λ₯Ό μ ννκ² λνλ΄κΈ° μν΄ μ€μ²©λ DTOλ₯Ό μμ±ν νμκ° μμ΅λλ€.
μλ₯Ό λ€μ΄, Userκ° μ¬λ¬ Address κ°μ²΄μ μ°κ΄λμ΄ μλ€λ©΄, μ€μ²©λ AddressDTOλ₯Ό ν¬ν¨νλ UserDTOλ₯Ό μμ±ν μ μμ΅λλ€:
public class UserDTO {
private Long id;
private String username;
private String email;
private List addresses;
// Constructors, getters, and setters
}
5.3. DTO λ²μ κ΄λ¦¬
μ ν리μΌμ΄μ μ΄ λ°μ ν¨μ λ°λΌ DTOμ λ³κ²½μ ν΄μΌ ν μλ μμ΅λλ€. μνΈνμ±μ μ μ§νκΈ° μν΄ DTOμ λ²μ κ΄λ¦¬λ₯Ό κ³ λ €ν΄λ³΄μΈμ. μ΄λ DTO ν΄λμ€μ λ²μ μλ³μλ₯Ό μΆκ°νκ±°λ νμν λ μλ‘μ΄ DTO λ²μ μ μμ±ν¨μΌλ‘μ¨ λ¬μ±ν μ μμ΅λλ€.
5.4. RESTful APIμμμ DTO
DTOλ ν΄λΌμ΄μΈνΈμ μλ² κ°μ κ΅νλλ λ°μ΄ν°λ₯Ό λνλ΄κΈ° μν΄ RESTful APIμμ μΌλ°μ μΌλ‘ μ¬μ©λ©λλ€. RESTful μλν¬μΈνΈλ₯Ό μ€κ³ν λ, νΉμ μ¬μ© μ¬λ‘μ ν΄λΌμ΄μΈνΈ μꡬμ¬νμ λ§κ² DTOλ₯Ό μ μ€νκ² μ ννκ³ κ΅¬μ‘°νν΄μΌ ν©λλ€. μ΄λ ν¨μ¨μ μΈ λ°μ΄ν° μ μ‘κ³Ό λͺ νν API κ³μ½μ 보μ₯ν©λλ€.
6. Spring Validationκ³Ό DTO μ¬μ©
Springμ 컨νΈλ‘€λ¬ λ©μλμμ @Valid μ΄λ Έν μ΄μ μ μ¬μ©νμ¬ DTOλ₯Ό κ²μ¦νλ κ°λ ₯ν λ©μ»€λμ¦μ μ 곡ν©λλ€. DTO νλΌλ―Έν°μ **@Valid**λ₯Ό μ΄λ Έν μ΄μ μΌλ‘ λ¬λ©΄, Springμ DTO ν΄λμ€μ μ μλ κ²μ¦ μ μ½ μ‘°κ±΄μ κΈ°λ°μΌλ‘ μλμΌλ‘ κ²μ¦μ νΈλ¦¬κ±°ν©λλ€.
컨νΈλ‘€λ¬ λ©μλμμ DTO κ²μ¦μ μ¬μ©νλ μμλ λ€μκ³Ό κ°μ΅λλ€:
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/create")
public ResponseEntity createUser(@Valid @RequestBody UserDTO userDTO) {
// Your validation logic is automatically triggered
// Map UserDTO to User entity and save it
User user = modelMapper.map(userDTO, User.class);
User savedUser = userService.saveUser(user);
// Return the saved UserDTO
UserDTO savedUserDTO = modelMapper.map(savedUser, UserDTO.class);
return ResponseEntity.status(HttpStatus.CREATED).body(savedUserDTO);
}
}
μ΄ μμ μμλ @Valid μ΄λ Έν μ΄μ μ μ¬μ©νμ¬ UserDTO ν΄λμ€μμ μ μν μ μ½ μ‘°κ±΄μ κΈ°λ°μΌλ‘ κ²μ¦μ νΈλ¦¬κ±°ν©λλ€. κ²μ¦μ΄ μ€ν¨νλ©΄ Springμ μλμΌλ‘ κ²μ¦μ λν μ€λ₯λ₯Ό μ²λ¦¬νκ³ μ μ ν μ€λ₯ λ©μμ§λ₯Ό ν¬ν¨ν μλ΅μ λ°νν©λλ€.
7. λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²μμμ DTO
λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²μμλ DTOκ° λ§μ΄ν¬λ‘μλΉμ€ κ°μ κ²½κ³λ₯Ό μ μνλ μ€μν μν μ ν©λλ€. κ° λ§μ΄ν¬λ‘μλΉμ€λ μ체μ μΌλ‘ νΉμ μꡬ μ¬νμ λ§λ DTO μΈνΈλ₯Ό κ°μ§ μ μμ΅λλ€. μ΄ λΆλ¦¬λ λ§μ΄ν¬λ‘μλΉμ€ κ°μ λμ¨ν κ²°ν©μ 보μ₯νκ³ λ 립μ μΌλ‘ μ§νν μ μλλ‘ ν©λλ€.
DTOλ λν λ§μ΄ν¬λ‘μλΉμ€ κ°μ μ μ‘λλ λ°μ΄ν° μμ μ€μ΄λ λ° λμμ΄ λλ©°, μ΄λ λ§μ΄ν¬λ‘μλΉμ€ κΈ°λ° μμ€ν μ μ±λ₯κ³Ό νμ₯μ±μ μ μ§νλ λ° μ€μν©λλ€.
8. κ²°λ‘
λ°μ΄ν° μ μ‘ κ°μ²΄ (DTO)λ Spring Boot μ ν리μΌμ΄μ μμ νμμ μ΄λ©°, μ ν리μΌμ΄μ μ λ€λ₯Έ λ μ΄μ΄μ μΈλΆ μμ€ν μ¬μ΄μ λ€λ¦¬ μν μ ν©λλ€. DTOλ₯Ό μ μ€νκ² μ€κ³νκ³ μ¬μ©ν¨μΌλ‘μ¨ λ°μ΄ν° 격리λ₯Ό κ°μ νκ³ μ€λ²ν€λλ₯Ό μ€μ΄λ©° 보μμ κ°ννκ³ ν μ€νΈλ₯Ό λ¨μνν μ μμ΅λλ€. DTOλ₯Ό μλμΌλ‘ μμ±νκ±°λ ModelMapperμ κ°μ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νκ±°λ μ½λ κ°μνλ₯Ό μν΄ Lombokμ νμ©νλ , ν΅μ¬μ νλ‘μ νΈμ μꡬ μ¬νκ³Ό μ μ§ λ³΄μμ±μ κ°μ₯ μ ν©ν μ κ·Ό λ°©μμ μ ννλ κ²μ λλ€. DTOκ° μν€ν μ²μ μ€μν λΆλΆμΌλ‘ μ‘΄μ¬νλ©΄, κ²¬κ³ νκ³ ν¨μ¨μ μΈ Spring Boot μ ν리μΌμ΄μ μ ꡬμΆνλ λ° λ μ κ°μΆμ΄μ§λλ€.
μΆκ°μ μΌλ‘ μ½μ΄λ³Όλ§ν κΈ: