π Java DTO Troubleshooting
π λͺ©μ°¨
π¨ λ¬Έμ μν©
DTO ν΄λμ€μμ final
νλμ @NoArgsConstructor
λ₯Ό ν¨κ» μ¬μ©ν λ λ°μνλ μ»΄νμΌ μλ¬
μλ¬ λ©μμ§: variable might not have been initialized
β ν΄κ²° λ°©λ²
Before (λ¬Έμ μ½λ)
@Getter
@Setter
public class CategoryDto {
private final Long id; // β final ν€μλ λ¬Έμ
private final String name; // β final ν€μλ λ¬Έμ
// ...
}
After (μμ λ μ½λ)
@Getter
@Setter
@NoArgsConstructor // β
κΈ°λ³Έ μμ±μ μλ μμ±
public class CategoryDto {
private Long id; // β
final μ κ±°
private String name; // β
final μ κ±°
// ...
}
π μμ μ΄μ
DTOλ λ°μ΄ν° μ μ‘ κ°μ²΄λ‘μ μ¬λ¬ κ³μΈ΅μμ κ°μ΄ ν λΉλλ κ²½μ°κ° λ§μ΅λλ€. λ°λΌμ final
보λ€λ μΌλ° νλλ‘ μ μΈνλ κ²μ΄ μΌλ°μ μ
λλ€.
π§ @NoArgsConstructor μ΄ν΄νκΈ°
κΈ°λ³Έ κ°λ
@NoArgsConstructor
λ Lombok μ΄λ
Έν
μ΄μ
μΌλ‘, λ§€κ°λ³μκ° μλ κΈ°λ³Έ μμ±μλ₯Ό μλμΌλ‘ μμ±ν©λλ€.
Lombok μ¬μ© μ /ν λΉκ΅
μλ μμ± (Before)
public class CategoryDto {
private Long id;
private String name;
// κ°λ°μκ° μ§μ μμ±ν΄μΌ νλ κΈ°λ³Έ μμ±μ
public CategoryDto() {
}
// getter, setter λ©μλλ€...
}
Lombok μ¬μ© (After)
import lombok.NoArgsConstructor;
@NoArgsConstructor // κΈ°λ³Έ μμ±μλ₯Ό μ»΄νμΌ μμ μ μλ μμ±
public class CategoryDto {
private Long id;
private String name;
// public CategoryDto() {} κ° μλμΌλ‘ μμ±λ¨
}
π« finalκ³Όμ μΆ©λ μ΄μ
-
final
νλλ μ μΈκ³Ό λμμ μ΄κΈ°ν λλ μμ±μμμ μ΄κΈ°ν νμ -
@NoArgsConstructor
λ λ§€κ°λ³μκ° μλ μμ±μλ₯Ό μμ± - λ§€κ°λ³μ μλ μμ±μμμλ
final
νλλ₯Ό μ΄κΈ°νν λ°©λ²μ΄ μμ
π 리νλ μ μ μν
리νλ μ μ΄λ?
νλ‘κ·Έλ¨μ΄ μ€ν μ€(Runtime)μ μκΈ° μμ μ λ€μ¬λ€λ³΄κ³ μ‘°μν μ μκ² ν΄μ£Όλ κΈ°λ₯
ποΈ Spring/JPAμμμ νμ©
1. Spring DI (μμ‘΄μ± μ£Όμ )
@Service
public class PostService {
// Springμ΄ λ¦¬νλ μ
μΌλ‘ κΈ°λ³Έ μμ±μλ₯Ό νΈμΆνμ¬ Bean μμ±
}
2. JPA μν°ν° μμ±
@Entity
public class Post {
// JPAκ° DB μ‘°ν κ²°κ³Όλ₯Ό κ°μ²΄λ‘ λ³νν λ κΈ°λ³Έ μμ±μ μ¬μ©
}
3. JSON μμ§λ ¬ν
@RestController
public class PostController {
@PostMapping("/posts")
public void createPost(@RequestBody PostSaveRequestDto dto) {
// Jacksonμ΄ JSON β DTO λ³ν μ κΈ°λ³Έ μμ±μ μ¬μ©
}
}
π 리νλ μ λμ κ³Όμ
- κ°μ²΄ μμ±: κΈ°λ³Έ μμ±μλ‘ λΉ κ°μ²΄ μμ±
- νλ νμ: 리νλ μ μΌλ‘ ν΄λμ€μ νλ μ 보 μμ§
- κ° μ£Όμ : κ° νλμ λ°μ΄ν° ν λΉ
β οΈ λ¦¬νλ μ μ λ¨μ
λ¨μ | μ€λͺ |
---|---|
μ±λ₯ μ ν | μΌλ°μ μΈ λ©μλ νΈμΆλ³΄λ€ λλ¦Ό |
μΊ‘μν μ ν΄ | private νλμλ μ κ·Ό κ°λ₯ |
μ»΄νμΌ μμ μ²΄ν¬ λΆκ° | μ€ν μ κΉμ§ λ¬Έμ λ°κ²¬ μ΄λ €μ |
π‘ μ€λ¬΄ μ μ© ν
1. DTO μ€κ³ κ°μ΄λλΌμΈ
// β
κΆμ₯νλ DTO ꡬ쑰
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor // λͺ¨λ νλλ₯Ό λ°λ μμ±μλ ν¨κ» μ 곡
public class UserDto {
private Long id;
private String username;
private String email;
private LocalDateTime createdAt;
}
2. μν°ν° vs DTO ꡬλΆ
κ΅¬λΆ | Entity | DTO |
---|---|---|
λͺ©μ | DB ν μ΄λΈ λ§€ν | λ°μ΄ν° μ μ‘ |
final μ¬μ© | κ°λ₯ (ID λ±) | μ§μ |
μμ±μ |
@NoArgsConstructor νμ |
@NoArgsConstructor κΆμ₯ |
3. Lombok μ΄λ Έν μ΄μ μ‘°ν©
// μ€λ¬΄μμ μμ£Ό μ¬μ©νλ μ‘°ν©
@Data // @Getter + @Setter + @ToString + @EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Builder // λΉλ ν¨ν΄ μ§μ
public class ProductDto {
private Long id;
private String name;
private BigDecimal price;
}
4. κ²μ¦ μ΄λ Έν μ΄μ κ³Ό ν¨κ» μ¬μ©
@Getter
@Setter
@NoArgsConstructor
public class CreateUserRequestDto {
@NotBlank(message = "μ¬μ©μλͺ
μ νμμ
λλ€")
private String username;
@Email(message = "μ¬λ°λ₯Έ μ΄λ©μΌ νμμ΄ μλλλ€")
private String email;
@Size(min = 8, message = "λΉλ°λ²νΈλ μ΅μ 8μ μ΄μμ΄μ΄μΌ ν©λλ€")
private String password;
}
π μμ½
-
DTOμμλ
final
ν€μλ μ§μ - λ°μ΄ν° μ μ‘ νΉμ±μ κ° λ³κ²½μ΄ νμ -
@NoArgsConstructor
νμ - Spring/JPAμ 리νλ μ κΈ°λ° λμμ μν΄ - 리νλ μ μ΄ν΄ - νλ μμν¬κ° λμ μΌλ‘ κ°μ²΄λ₯Ό μμ±νκ³ μ‘°μνλ μ리
- μ€λ¬΄ ν νμ© - Lombok μ‘°ν©κ³Ό κ²μ¦ μ΄λ Έν μ΄μ μΌλ‘ ν¨μ¨μ μΈ DTO μ€κ³