π @NoArgsConstructor μ¬μ©: DTO vs Entity
π ν΅μ¬ μ°¨μ΄: μμ±μμ μ κ·Ό μ μ΄μ
κ²°λ‘ λΆν° λ§μλ리면, λ μ΄λ Έν μ΄μ μ μ μΌν μ°¨μ΄λ μμ±λλ κΈ°λ³Έ μμ±μ(no-argument constructor)μ μ κ·Ό μ μ΄μ(Access Modifier) μ λλ€.
@NoArgsConstructor
public κΈ°λ³Έ μμ±μλ₯Ό λ§λλλ€.
public class MyDto {
// @NoArgsConstructorκ° μμ±ν μ½λ
public MyDto() {
}
}
@NoArgsConstructor(access = AccessLevel.PROTECTED)
protected κΈ°λ³Έ μμ±μλ₯Ό λ§λλλ€.
public class MyEntity {
// @NoArgsConstructor(access = AccessLevel.PROTECTED)κ° μμ±ν μ½λ
protected MyEntity() {
}
}
π€ μ μ΄ μ°¨μ΄κ° μ€μνκ°μ?
μ΄ μ κ·Ό μ μ΄μμ μ°¨μ΄λ βλκ° μ΄ ν΄λμ€λ₯Ό μ§μ μμ±ν μ μλκ°?β λ₯Ό κ²°μ νλ©°, μ΄λ JPA Entityμ DTOμμ κ°κ° λ€λ₯Έ μλ―Έλ₯Ό κ°μ§λλ€.
π₯ Request DTOμμ: @NoArgsConstructor (public)
μ public κΈ°λ³Έ μμ±μκ° νμνκ°μ?
Request DTOλ μ£Όλ‘ μΈλΆ(ν΄λΌμ΄μΈνΈ)μμ μ¨ JSON λ°μ΄ν°λ₯Ό μλ° κ°μ²΄λ‘ λ³ν(Deserialization)ν λ μ¬μ©λ©λλ€.
Spring Bootκ° ν΄λΌμ΄μΈνΈλ‘λΆν° λ°μ JSON λ°μ΄ν°λ₯Ό DTO κ°μ²΄λ‘ λ³ννλ κ³Όμ λλ¬Έμ λλ€.
JSON β DTO λ³ν κ³Όμ
-
κ°μ²΄ μμ± λ¨κ³
- ν΄λΌμ΄μΈνΈκ° APIλ₯Ό νΈμΆνλ©΄, Springμ λ΄λΆμ μΌλ‘ Jackson λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν΄ HTTP Bodyμ JSON λ¬Έμμ΄μ μ½μ΅λλ€
- Jacksonμ μ΄ JSON λ°μ΄ν°λ₯Ό λ΄μ μλ° κ°μ²΄(Request DTO)λ₯Ό λ¨Όμ μμ±ν΄μΌ ν©λλ€
-
publicκΈ°λ³Έ μμ±μ νΈμΆ- Jacksonμ κ°μ₯ κ°λ¨νκ³ νμ€μ μΈ λ°©λ²μΈ
publicκΈ°λ³Έ μμ±μ(new YourRequestDto()) λ₯Ό νΈμΆνμ¬ μΌλ¨ ν λΉ DTO κ°μ²΄λ₯Ό λ§λλλ€
- Jacksonμ κ°μ₯ κ°λ¨νκ³ νμ€μ μΈ λ°©λ²μΈ
-
νλ κ° μ£Όμ
- κ·Έ νμ JSONμ κ° νλ(
"chapterName": "μ μ¬μλ")λ₯Ό λΆμνμ¬, μμ±λ DTO κ°μ²΄μ ν΄λΉ νλμ κ°μ μΈν°(setter)λ 리νλ μ (reflection)μ ν΅ν΄ μ£Όμ ν©λλ€
- κ·Έ νμ JSONμ κ° νλ(
β οΈ λ§μ½
publicκΈ°λ³Έ μμ±μκ° μλ€λ©΄ Jacksonμ 1λ¨κ³μμ κ°μ²΄λ₯Ό μμ±νλ κ²λΆν° μ€ν¨νκ² λμ΄ μ€λ₯κ° λ°μν©λλ€.
μ½λ μμ
package com.kobe.koreahistory.dto.request;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* μ±ν° μμ± μμ² DTO
*/
@Getter
@NoArgsConstructor // public κΈ°λ³Έ μμ±μλ₯Ό λ§λ€μ΄μ€
public class ChapterCreateRequestDto {
private int chapterNumber;
private String chapterTitle;
// ... νλλ€
}
ν΅μ¬ ν¬μΈνΈ
Request DTOμλ @NoArgsConstructorλ₯Ό μ¬μ©νμ¬ public κΈ°λ³Έ μμ±μλ₯Ό μ΄μ΄λλ κ²μ΄ μΌλ°μ μ΄κ³ μ¬λ°λ₯Έ λ°©λ²μ
λλ€.
ποΈ JPA Entityμμ: @NoArgsConstructor(access = AccessLevel.PROTECTED)
μ protectedλ₯Ό μ¬μ©νλμ?
JPA Entityλ λ°μ΄ν°λ² μ΄μ€ ν μ΄λΈκ³Ό μ§μ λ§€νλλ ν΅μ¬ λλ©μΈ κ°μ²΄μ λλ€. μ΄ κ°μ²΄λ ν¨λΆλ‘ μμ±λμ΄μλ μ λλ©°, νμ μΌκ΄λ μνλ₯Ό μ μ§ν΄μΌ ν©λλ€.
JPAκ° κΈ°λ³Έ μμ±μλ₯Ό νμλ‘ νλ μ΄μ
- JPA λͺ μΈ: JPAλ DBμμ λ°μ΄ν°λ₯Ό μ‘°ννμ¬ Entity κ°μ²΄λ₯Ό λ§λ€ λ, λ΄λΆμ μΌλ‘ 리νλ μ (reflection)μ ν΅ν΄ κΈ°λ³Έ μμ±μλ₯Ό μ¬μ©ν©λλ€
- λ°λΌμ κΈ°λ³Έ μμ±μλ λ°λμ νμν©λλ€
μ publicμ΄ μλ protectedμΈκ°?
λ§μ½ κΈ°λ³Έ μμ±μλ₯Ό publicμΌλ‘ μ΄μ΄λλ©΄, κ°λ°μκ° μλΉμ€ λ‘μ§ λ±μμ μ무 μκ° μμ΄ new Chapter()μ κ°μ΄ λΉμ΄μλ(μνκ° λΆμμ ν) Entity κ°μ²΄λ₯Ό μμ±ν μ μμ΅λλ€.
μ΄λ λ°μ΄ν° 무결μ±μ ν΄μΉκ³ λ²κ·Έλ₯Ό μ λ°νλ μ£Όμ μμΈμ΄ λ©λλ€.
protectedμ μμ μ₯μΉ μν
μμ±μλ₯Ό protected λ‘ λ§λ€λ©΄, μΈλΆ ν¨ν€μ§μμ new Chapter()λ₯Ό νΈμΆνλ κ²μ λ§μ μ μμ΅λλ€.
μ΄λ κ°λ°μμκ² βμ΄ κ°μ²΄λ λΉλ(@Builder)λ μ μ ν©ν 리 λ©μλμ²λΌ μ ν΄μ§ λ°©μμΌλ‘λ§ μμ±ν΄μΌ ν΄!βλΌλ λͺ
νν λ©μμ§λ₯Ό μ λ¬νλ μμ μ₯μΉ μν μ ν©λλ€.
π‘ JPAλ 리νλ μ μ μ¬μ©νλ―λ‘
protectedμ¬λ λ¬Έμ μμ΄ κ°μ²΄λ₯Ό μμ±ν μ μμ΅λλ€.
μ½λ μμ
package com.kobe.koreahistory.entity;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.AccessLevel;
import javax.persistence.*;
/**
* μ±ν° μν°ν°
*/
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED) // protected κΈ°λ³Έ μμ±μ
public class Chapter {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private int chapterNumber;
private String chapterTitle;
@Builder
public Chapter(int chapterNumber, String chapterTitle) {
this.chapterNumber = chapterNumber;
this.chapterTitle = chapterTitle;
}
}
π μ΅μ’ μ 리
| Β | @NoArgsConstructor(public) |
@NoArgsConstructor(access = AccessLevel.PROTECTED) |
|---|---|---|
| μμ±μ | public |
protected |
| μ£Όμ μ©λ |
Request DTO (JSON μμ§λ ¬νμ©) |
JPA Entity (κ°μ²΄ μμ±μ μμ μ± ν보μ©) |
| μλ | βμ΄ ν΄λμ€λ μΈλΆμμ μμ λ‘κ² μμ±λ μ μμ΅λλ€β |
βμ΄ ν΄λμ€λ μ ν΄μ§ λ°©μ μΈμλ ν¨λΆλ‘ μμ±νμ§ λ§μΈμβ |
| λΉμ | λ¬Έμ νμ§ μ΄μ΄λκΈ° πͺ | λ¬Έμ μ΄μ§λ§ μ΄μ΄λκΈ° π |
π‘ ν΅μ¬ μμΉ
Request DTO
μΈλΆμ JSON λ°μ΄ν°λ₯Ό λ°μμΌ νλ―λ‘, λꡬλ κ°μ²΄λ₯Ό μμ±ν μ μλλ‘ λ¬Έμ νμ§ μ΄μ΄λμ΄μΌ ν©λλ€.
π @NoArgsConstructor (public)
JPA Entity
ν΅μ¬ λλ©μΈ κ°μ²΄μ΄λ―λ‘, μ ν΄μ§ κ·μΉ(λΉλ ν¨ν΄ λ±)μΌλ‘λ§ μμ±νλλ‘ κ°μ νκ³ μΆμ΅λλ€.
π @NoArgsConstructor(access = AccessLevel.PROTECTED)
μ΄ μμΉμ μ§ν€λ©΄ λ μμ μ μ΄κ³ μλκ° λͺ νν μ½λλ₯Ό μμ±ν μ μμ΅λλ€.