π€ 1. κ³ λ―Ό..
νμ¬ λλ μ°½μ νλ‘μ νΈμμ νΌμ λ°±μλ κ°λ°μ 맑μ μ§ννκ³ μλ€.
λνμμ΄λ λΉμ°ν μ¬μλ μκ³ , κ°μ΄ κ³ λ―Όνκ³ ν λ‘ ν λ°±μλ νμλ μμΌλ λ΄κ° κ²°μ ν λͺ¨λ κ²μ΄ κ·Έλλ‘ νλ‘μ νΈμ λ°μλμλ€. λμ μλͺ»λ νλ¨, μ΅κ΄ λ€λ‘ νλ‘μ νΈκ° λ§κ°μ§μ§ μλλ‘ νκΈ° μν΄ λμμμ΄ λλμλ³΄κ³ μ‘°μΈμ ꡬνλ©° μ§ννκ³ μλ€.
νμ¬ νλ‘μ νΈλ ν° νλ‘ domain, global λ₯Ό λλ΄κ³ , λλ©μΈ λ³λ‘ entity, dtoλ± μμ±νκ³ μμλ€.
νμ§λ§ νλ‘μ νΈ κ·λͺ¨κ° 컀μ§μ λ°λΌ dtoκ΄λ¦¬λ₯Ό νκΈ°κ° λ무 νλ€μλ€. λΉμ₯ λͺ μ£Ό μ μ κ°λ°νλ μ½λλ₯Ό λ± λ΄€μ λ λ¬΄μ¨ μν μ νλ ν΄λμ€μΈμ§ λ°λ‘ μμ차리기 νλ€μλ€. λλ¦ μ½λμ μ κ²½μ λ§μ΄ μ¨μ κ°λ° νλ μ€νμΌμΈλ° κ·λͺ¨κ° 컀μ§λ μ΄μ§λ¬μ λ€.
μλλ νλ‘μ νΈ λλ ν 리 μ€ μΌλΆλ₯Ό μΊ‘μ³ν μ¬μ§μ΄λ€.
dtos ν΄λλ₯Ό 보면 offer, project λ± domain ν΄λκ° λ λ€μ΄μλ€.
λ§μ½ offer λλ©μΈκ³Ό κ΄λ ¨λ λ°ν λ°μ΄ν°μ jobPost λ°μ΄ν°κ° ν¬ν¨λμΌ νλ€λ©΄ offer λλ ν 리μ dtoλ₯Ό μμ±ν΄μ μ¬μ©νμλ€.
λλ¦ μμ보기 μ½μκ³ μ΄λ κ² νλλ° μ’μ λ°©μμ΄ μλλ μκ°μ΄ λ€μλ€.
μμ λ€λ₯Έ λ§μ κ°λ°μ λΆλ€μ΄ μ΄λ―Έ μ΄λ° κ³ λ―Όμ νκ³ , λ€μν λ°©λ²μΌλ‘ ν΄κ²°νκ³ μμλ€.
κ·Έ μ€ Inner Classλ‘ λ¦¬νν°λ§μ μ§νν μμ μ΄λ€.
μ¬μ€ μμ νλ‘μ νΈμλ μ΄κ±Έ λμ ν κΉ νλ€κ° [outer_class].[inner_class] μ²λΌ μ κ·Όν΄μΌ ν΄μ λμ νμ§ μμλλ°, κ·Έλ νλ‘μ νΈ κ·λͺ¨κ° μμμ κ·Έλ° μκ°μ νλ κ² κ°λ€..
λ¬Όλ‘ dtoλ₯Ό μ¬μ©ν λ μ΄μ λ³΄λ€ κΈΈμ΄μ§λ 건 λ§μ§λ§ λͺ¨λ ν΄κ²°μ± μ trade-off κ° μλ λ²μ΄λ..^^
No Silver Bullet (μμ΄νμ μλ€)
2. κ°μ λ°©λ²
DTO κ΄λ¦¬ λ°©λ²μ μ°Ύμ보λ€λ³΄λ Inner Classλ₯Ό νμ©νλ λ°©λ²μ΄ μμ΄μ νλ‘μ νΈμ λμ νλ€.
Inner Classλ₯Ό νμ©νλ©΄ μ¬λ¬κ°μ DTO νλμ ν΄λμ€μμ κΉλνκ² κ΄λ¦¬ν μ μλ€. μμ μ¬νμ΄ μκΈ°λ©΄ μ¬λ¬ κ³³μ λμλ€λλ©΄μ μμ ν νμκ° μκ³ μμμ λ΄κ° λκΌλ λ¬Έμ μ μ ν΄κ²°ν μ μμλ€.
μλλ Inner Class λ₯Ό μ¬μ©νμ¬ κ³μ νλ μ½λμ μμμ΄λ€.
2.1 κ°μ μ
- λ©μΈ λ°ν DTO
public class ProductDto {
private final SellerDto seller;
private final CategoryDto category;
private final AddressDto address;
private final String title;
private final String contents;
}
- νλμ λ€μ΄κ° DTO
public class SellerDto {
// μλ΅...
}
public class CategoryDto {
// μλ΅...
}
public class AddressDto {
// μλ΅...
}
λμ νλ‘μ νΈ κ΅¬μ‘°μλ€λ©΄ SellerDtoλ Seller λλ ν 리μ, CategoryDtoλ CategoryDtoμ.. μ΄μ§λ½λ€..
μ΄κ±Έ InnerClassλ‘ κ΄λ¦¬νλ©΄ μλμ κ°μ΄ μ¬μ©ν μ μλ€.
2.2 κ°μ ν
public class ProductDto {
private final String title;
private final String contents;
private final SellerDto seller;
private final CategoryDto category;
private final AddressDto address;
private static class SellerDto {
// μλ΅
}
private static class CategoryDto {
// μλ΅
}
private static class AddressDto {
// μλ΅
}
}
νμ€ν μ΄λ€ Dtoλ₯Ό λ³΄κ³ μ΄λμ μ¬μ©νλ DtoμΈμ§ μμμ±κΈ° μ¬μΈ κ² κ°λ€.
μλλ μ€μ λ‘ λ΄ μ½λλ₯Ό μ΄λ»κ² 리νν°λ§ νλμ§ μΌλΆ κ³Όμ μ λ΄μλ€.
μλ DTOλ μΈλ ₯ κ΄λ¦¬ κΈ°λ₯μμ λ°νλλ DTOμ΄λ€.
dtoλͺ μ΄ μ λ§.. λ³λ‘λ€. μ²μλΆν° μ λ κ² μ§μ λΆνμ§ μμλ€. μ΄λ€ dtoλ₯Ό λ΄€μ λ μ΄λμ μ¬μ©νλ dtoμΈμ§ ν΄λμ€λͺ λ§ λ³΄κ³ λ μ μ μκ² νκ³ μΆμ΄ μ λ°μμΌλ‘ μμ±νλλ° λ무 λ§μμ§λ€λ³΄λ λ§€λ² λ€λ₯Έ μ΄λ¦μΌλ‘ μμ±νλκ² νλ€μ΄μ§κ³ κΈΈμ΄μ‘λ€.
MemberResponseForApplyHistory ν΄λμ€λ member λλ ν 리μ λ€μ΄κ°μμκ³ , μ΄κ²λ member λλ ν 리μμ ν΄λΉ dtoλ₯Ό λ΄€μ λ μ΄λμ μ¬μ©νλκ±΄μ§ μ μ μκ² νλ €κ³ μ λ°μμΌλ‘ μ§μλ€.
μ΄κ±Έ inner classλ‘ μ¬μ©νλ©΄μ μλμ κ°μ΄ λ³κ²½ν μ μμλ€.
member λλ ν 리μ μλ dtoλ μμ νκ³ static classλ‘ μμ ν΄μ€¬λ€.
@Getter
@Builder
public class ApplyManageResponse {
/**
* μΈλ ₯ κ΄λ¦¬: λκΈ° μ€μΈ μΈλΆ μ‘°ν
* μΈλ ₯ κ΄λ¦¬: νμ λ μΈλΆ μ‘°ν
*/
private Long applyId;
private MemberResponse memberResponse;
public static ApplyManageResponse from(Apply apply) {
return ApplyManageResponse.builder()
.applyId(apply.getId())
.memberResponse(MemberResponse.from(apply.getMember()))
.build();
}
@Builder
public static class MemberResponse {
private Long memberId;
private String workerName; // λ
Έλμ μ΄λ¦
private String phone; // ν΄λν° λ²νΈ
private Integer age; // λμ΄
private Gender gender; // μ±λ³
private String nationality; // κ΅μ
private Integer workTimes; // μΆμ νμ
private Float participationRate; // μ°Έμ¬μ¨
public static MemberResponse from(Member member) {
// λμ΄ κ³μ°
int age = AgeTransfer.getAgeByBirth(member.getWorkerInfo().getBrith());
// μΆμ νμ, μ°Έμ¬μ¨
List<History> workHistory = member.getHistoryList().stream()
.filter(history -> history.getEndStatus() == WorkStatus.FINISH_WORK)
.collect(Collectors.toList());
int workTimes = workHistory.size();
float participationRate = (float) workTimes / (float) member.getHistoryList().size();
// μΆμ λ΄μμ΄ μμ κ²½μ° -1
if (workTimes == 0) {
participationRate = -1;
}
return MemberResponse.builder()
.memberId(member.getId())
.workerName(member.getWorkerInfo().getWorkerName())
.phone(member.getPhone())
.age(age)
.gender(member.getWorkerInfo().getGender())
.nationality(member.getWorkerInfo().getNationality())
.workTimes(workTimes)
.participationRate(participationRate)
.build();
}
}
}
μ μ½λμμ νλμ dtoλ§ innerλ‘ λ΄μμ§λ§ 4~5κ°μ dtoλ₯Ό λ©ννλ dtoλ μ‘΄μ¬νκ³ Inner Classλ‘ κΉλνκ² μ²λ¦¬ν μ μμλ€.
3. κ²°λ‘
μμ ν λ΄μ©λ€μ΄ λ§μ μμ μ μλ£ν건 μλμ§λ§ νμ€ν건 μλ‘μ΄ λ°±μλ κ°λ°μκ° ν©λ₯νκ² λμ λ μ½λλ₯Ό μ΄ν΄νκΈ° μ½κ² λ€ λΌλ μκ°μ΄ λ€μλ€.
μ΄ λ°©μμ νκ°μ§ μμ¬μ΄ μ μ΄ μλ€λ©΄ μ¬λ¬ κ³³μμ λκ°μ ννλ‘ μ¬μ©νλ DTOκ° Inner Classλ‘ μ‘΄μ¬νλ€λ©΄ μ¬μ¬μ©νκΈ° μ 맀ν κ°μ΄ μλ€.
μ΄λ΄ κ²½μ° λλ Inner Classλ‘ λμ§ μκ³ κ·Έλ₯ κ³΅μ© DTOλ‘ λΆλ¦¬ν΄μ μ¬μ©νκ³ μλ€.
λ μ’μ λ°©λ²μ΄ μλ€λ©΄ λκΈλ‘ λ¨κ²¨μ£ΌμΈμ!