DTO 패턴을 사용하여 클라이언트에게 데이터를 전송할 때 엔티티 클래스 대신 DTO 클래스를 사용하는 것이 좋다고 했습니다. 이는 엔티티 클래스가 데이터베이스 테이블과 직접 연결되어 있으므로, 불필요한 내부 데이터베이스 정보를 클라이언트에 노출시키지 않기 위함입니다.
이제 프로젝트에 DTO 클래스를 코드로 작성해보도록 하겠습니다.
이 클래스에는 클라이언트에 보내고자 하는 필드만 포함됩니다. 예를 들어, customerId 필드는 클라이언트에 필요하지 않으므로 DTO에서 제외됩니다.
Lombok의 @Data 어노테이션을 사용하여 Getter, Setter, toString 등의 메서드를 자동으로 생성합니다.
@Data
@Schema(
name = "Account",
description = "Schema to hold Account information"
)
public class AccountDto {
@NotEmpty(message = "AccountNumber can not be a null or empty")
@Pattern(regexp="(^$|[0-9]{10})",message = "AccountNumber must be 10 digits")
@Schema(
description = "Account Number of Addo Bank account", example = "3454433243"
)
private Long accountNumber;
@NotEmpty(message = "AccountType can not be a null or empty")
@Schema(
description = "Account type of Addo Bank account", example = "Savings"
)
private String accountType;
@NotEmpty(message = "BranchAddress can not be a null or empty")
@Schema(
description = "Addo Bank branch address", example = "123 NewYork"
)
private String branchAddress;
}
이 클래스에는 고객과 관련된 필드만 포함됩니다. 이 DTO 클래스에도 @Data 어노테이션을 사용하여 필드와 관련된 메서드를 자동으로 생성합니다.
@Data
@Schema(
name = "Customer",
description = "Schema to hold Customer and Account information"
)
public class CustomerDto {
@Schema(
description = "Name of the customer", example = "Eazy Bytes"
)
@NotEmpty(message = "Name can not be a null or empty")
@Size(min = 5, max = 30, message = "The length of the customer name should be between 5 and 30")
private String name;
@Schema(
description = "Email address of the customer", example = "tutor@eazybytes.com"
)
@NotEmpty(message = "Email address can not be a null or empty")
@Email(message = "Email address should be a valid value")
private String email;
@Schema(
description = "Mobile Number of the customer", example = "9345432123"
)
@Pattern(regexp = "(^$|[0-9]{10})", message = "Mobile number must be 10 digits")
private String mobileNumber;
@Schema(
description = "Account details of the Customer"
)
private AccountDto accountsDto;
}
이후 ResponseDto와 ErrorResponseDto 클래스를 생성하여 클라이언트에게 응답을 보낼 때 사용할 수 있는 DTO를 준비합니다. 이 DTO 클래스들은 상태 코드와 메시지를 포함하여 클라이언트가 요청 처리 결과를 쉽게 이해할 수 있도록 합니다.
@Schema(
name = "Response",
description = "Schema to hold successful response information"
)
@Data @AllArgsConstructor
public class ResponseDto {
@Schema(
description = "Status code in the response"
)
private String statusCode;
@Schema(
description = "Status message in the response"
)
private String statusMsg;
}
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.http.HttpStatus;
import java.time.LocalDateTime;
@Data @AllArgsConstructor
@Schema(
name = "ErrorResponse",
description = "Schema to hold error response information"
)
public class ErrorResponseDto {
@Schema(
description = "API path invoked by client"
)
private String apiPath;
@Schema(
description = "Error code representing the error happened"
)
private HttpStatus errorCode;
@Schema(
description = "Error message representing the error happened"
)
private String errorMessage;
@Schema(
description = "Time representing when the error happened"
)
private LocalDateTime errorTime;
}
이렇게 DTO 패턴을 활용해봤는데, DTO 패턴을 사용하면 데이터베이스 엔티티와 프레젠테이션 레이어 사이의 결합도를 낮출 수 있습니다. 클라이언트는 DTO를 통해 필요한 데이터만 받으며, 데이터베이스 구조 변경이 클라이언트에 영향을 미치지 않게 됩니다.
또한, DTO 패턴은 네트워크 트래픽을 줄이고, 직렬화 로직을 DTO 클래스에 캡슐화하여 유지보수를 쉽게 할 수 있도록 합니다.