✅ 핵심 포인트
필드: 요청/응답에서 필요한 데이터만.
기본 생성자: JSON 역직렬화(Jackson) 시 필수.
Getter/Setter: 값 읽기/쓰기 가능하게.
비즈니스 로직 없음: 계산, 검증은 Service나 Domain에서.
public class FruitCreateRequest {
// 1. 전달할 데이터 필드
private String name;
private String warehousingDate; // 문자열로 받는 경우 (JSON에서 LocalDate 변환 가능)
private long price;
// 2. 기본 생성자 (Jackson 역직렬화용)
public FruitCreateRequest() {
}
// 3. 모든 필드를 초기화하는 생성자
public FruitCreateRequest(String name, String warehousingDate, long price) {
this.name = name;
this.warehousingDate = warehousingDate;
this.price = price;
}
// 4. Getter (JSON → 객체 변환 후 값 읽기)
public String getName() {
return name;
}
public String getWarehousingDate() {
return warehousingDate;
}
public long getPrice() {
return price;
}
// 5. Setter (필요 시)
public void setName(String name) {
this.name = name;
}
public void setWarehousingDate(String warehousingDate) {
this.warehousingDate = warehousingDate;
}
public void setPrice(long price) {
this.price = price;
}
import java.time.LocalDate;
public class Fruit {
private final String name;
private final LocalDate warehousingDate;
private final long price;
public Fruit(String name, LocalDate warehousingDate, long price) {
// 비즈니스 규칙 검증
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Fruit name cannot be empty");
}
if (warehousingDate == null) {
throw new IllegalArgumentException("Warehousing date is required");
}
if (warehousingDate.isAfter(LocalDate.now())) {
throw new IllegalArgumentException("Warehousing date cannot be in the future");
}
if (price <= 0) {
throw new IllegalArgumentException("Price must be greater than zero");
}
this.name = name;
this.warehousingDate = warehousingDate;
this.price = price;
}
public String getName() {
return name;
}
public LocalDate getWarehousingDate() {
return warehousingDate;
}
public long getPrice() {
return price;
}
// 도메인 행동 예시: 할인 적용
public Fruit applyDiscount(int percent) {
long discountedPrice = price - (price * percent / 100);
return new Fruit(name, warehousingDate, Math.max(discountedPrice, 1));
}
✅ Domain vs DTO 차이
