2021. 6. 17. 17:59ใBack-End ์์ ์ค/Spring Framework
lombok์ด๋?
Getter์ Setter๋ฅผ Annotationํํ๋ก ์ฌ์ฉํ์ฌ Method๋ฅผ ๊ตฌํํ์ง ์๊ณ , ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ
Java Compile ์์ ์์ ํน์ Annotation์ผ๋ก ํด๋น Code๋ฅผ ์ถ๊ฐํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ. ๊ฐ๋
์ฑ๊ณผ ์ ์ง๋ณด์์ ๋ง์ ๋์์ ์ฃผ๊ฒ๋๋, ์ ๋ชป ์ฌ์ฉํ ๊ฐ๋ฅ์ฑ์ด ๋งค์ฐ ๋์ Library.
๐ @Data ์ฌ์ฉ์ NoNo!!
@Data๋ ์๋ Annotation์ ํ๋ฒ์ ํฌํจํ๋ ๊ฐ๋ ฅํ Annotation์ธ ๊ฒ์ด์์.
@ToString, @EqualseAndHashCode, @Getter, @Setter, @RequiredArgsConstructor
๋ฌธ์ ๋ @Setter๋ฅผ ํฌํจํ๊ณ ์๋ค๋ ๊ฒ์ด๊ฒ ์ง์?
@Setter
๋ ๊ทธ ์๋๊ฐ ๋ถ๋ช
ํ์ง ์๊ณ , ๊ฐ์ฒด(์ธ์คํด์ค ๋ณ์ ๊ฐ)๋ฅผ ์ธ์ ๋ ์ง ๋ณ๊ฒฝํ ์ ์๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์์ ์ฑ์ ๋ณด์ฅ๋ฐ๊ธฐ ํ๋ ๊ฒ์ด์์. ๊ทธ๋ด๊ฑฐ๋ฉด ๊ทธ๋ฅ ์ธ์คํด์ค ๋ณ์๋ฅผ private
๊ฐ ์๋ public
์ผ๋ก ํ๋๊ฒ๊ณผ ๋ค๋ฅผ๊ฒ์ด ์๋ ๊ฒ์ด์์. ๋ง์ฝ ํ์๊ฐ์
์๋น์ค๋ฅผ ๊ตฌํํ ๋, id๋ฅผ ๋ณ๊ฒฝ๋์ง ์๋๋ก ๋ง๋ ๋ค๋ฉด id ๊ด๋ จ setter ๋ํ! ์ ๊ณต ๋๋ฉด ์๋๋ ๊ฒ์ด์์.
๊ทธ๊ฒ์ ๋จ์ ์์ ํจ์ ๋์ด ํด๋น ๊ฐ์ฒด๊ฐ ์์ ์ ๊ฐ์ฅ ์ ํํํ๋ ๊ตฌ์กฐ๋ก id์ ๋ณ๊ฒฝ Point๋ฅผ ์ ๊ณตํ์ง ์์์ผ๋ก, id์ ๋ณ๊ฒฝ ๊ธฐ๋ฅ์ด ์๋ค๋ ๊ฒ์ ํํํ ์ ์๋ ๊ฒ์ด์์.
@ToString์ผ๋ก ์ธํ ์๋ฐฉํฅ ์ฐ๊ด๊ด๊ณ ์ ์ํ ์ฐธ์กฐ ๋ฌธ์
@Entity
@Table(name = "member")
@Data
public class Member {
....
@OneToMany
@JoinColumn(name = "member_ship_id")
private List<MemberShip> ms = new ArrayList<>();
}
@Entity
@Table(name = "memberShip")
@Data
public class MemberShip {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne
private Member member;
public Coupon(Member member) {
this.member = member;
}
}
๋ง์ฝ Member๋ผ๋ ๊ฐ์ฒด์ MemberShip ๊ฐ์ฒด๊ฐ ์๋ฐฉํฅ ์ฐ๊ด ๊ด๊ณ์ผ ๋, ToString์ ํธ์ถํ๊ฒ ๋๋ฉด ๋ฌดํ ์ํ ์ฐธ์กฐ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ ๊ฒ์ด์์. ์ด๊ฒ์ JPA๋ฅผ ์ฌ์ฉํ๋ค๋ณด๋ฉด ๊ฐ์ฒด๋ฅผ Json์ผ๋ก ์ง๋ ฌํ ํ๋ ๊ฐ์ ์์ ๋ฐ์ํ๋ ๋ฌธ์ ์ ๋์ผํ ๊ฒ์ด์์.
ํด๊ฒฐ ๋ฐฉ์์?
@ToString(exclude = "memberShip")
public Class Member {
...
}
์ด๋ ๊ฒ ํด๋น Annotation์ ์ด์ฉํ์ฌ ToString ํญ๋ชฉ์์ ์ ์ธ ์์ผ ๋ฒ๋ฆฌ๋ ๊ฒ์ด์์.
์ข์ ๋ฐฉ๋ฒ
@NoArgsConstructor ์ ๊ทผ ์ต์ํ
JPA์์๋ Proxy ์์ฑ์ ์ํด ๊ธฐ๋ณธ ์์ฑ์๋ ๋ฐ๋์ ํ๋๊ฐ ์์ด์ผ ํ๋ ๊ฒ์ด์์.
์ด ๋, ์ ๊ทผ ๊ถํ์ด protected
์ด๋ฉด ์ถฉ๋ถํฉ๋๋ค! ๊ตณ์ด ์ธ๋ถ์ ์ด์ด๋ ํ์๊ฐ ์๋ ๊ฒ์ด์ง์.
์ด๋ ๊ฒ ํ๋ฉด ์ฅ์ ์ ์ด๋ฌํฉ๋๋ค.
@Entity
@Table(name = "product")
@Getter
@NoArgsConstructor(access = AccessLevel.PUBLIC) // ํ
์คํธ๋ฅผ ์ํด ์์๋ก Public, ์๋ํ ์ฝ๋๋ PROTECTED
public class Product {
@Id
private String id;
private String name;
@Builder
public Product(String name) {
this.id = UUID.randomUUID().toString();
this.name = name;
}
}
์์ ์ฝ๋๋ ID์์ฑ์ UUIDํ์์ผ๋ก ํ๋ ๊ฒ์ด์์.
ID๋ ํญ์ NULL์ด ์๋๊ธธ ๊ธฐ๋ํ์ง๋ง, public ์์ฑ์๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฒ ๋๋ฉด ID์ NULL์ด ๋ค์ด์ค๊ฒ ๋ฉ๋๋ค.
๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์๋ฌด ์ด์ ์์ด ์ด์ด๋๋ ๊ฒ์ ๊ฐ์ฒด ์์ฑ ์ ์์ ์ฑ์ ๋จ์ดํธ๋ฆฌ๋ ์์ธ์ด ๋๋ ๊ฒ์ด์ง์.
์ด๋ด ๋! @NoArgsConstuctor(access = AccessLevel.PUBLIC)
์ ์ฌ์ฉํ๊ฒ ๋๋ค๋ฉด ๊ฐ์ฒด ์์ฑ ์ ์์ ์ฑ์ ์ด๋ ์ ๋ ๋ณด์ฅ ๋ฐ์ ์ ์๋ ๊ฒ์ด์์!
๊ธฐ๋ณธ ์์ฑ์ ์ ๊ทผ์ protected
๋ก ๋ณ๊ฒฝ ์ ์ธ๋ถ์์ ํด๋น ์์ฑ์๋ฅผ ์ ๊ทผํ ์ ์๊ธฐ์ ์๋ ์ฝ๋์ฒ๋ผ ์์ฑ์๋ฅผ ํตํด์ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒ์ด์์.
@Builder
public Product(String name) {
this.id = UUID.randomUUID().toString();
this.name = name;
}
์์ ๊ฐ์ด ํ ๊ฒฝ์ฐ UUID์์ฑ ์ฝ๋๊ฐ ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ๋ฐ๋์ ID๊ฐ์ด ๋ค์ด์ค๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฅ ๋ฐ์ ์ ์๋ ๊ฒ์ด์์.
๊ฐ์ฒด์ ๋ํ ์์ฑ์๋ฅผ ํ๋ ๋๊ณ , ๊ทธ๊ฒ์ @Builder๋ฅผ ํตํด ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์จ์ ์ผ ์ ์๋ค!
@Builder(๋น๋ ํจํด)๋?
๋ณตํฉ ๊ฐ์ฒด์ ์์ฑ ๊ณผ์ ๊ณผ ํํ ๋ฐฉ๋ฒ์ ๋ถ๋ฆฌํ์ฌ ๋์ผํ ์์ฑ ์ ์ฐจ์์ ์๋ก ๋ค๋ฅธ ํํ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค ์ ์๊ฒ ํ๋ ํจํด.
์ฆ, ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋, ์์ฑ์๋ง์ ํตํด์ ์์ฑํ๋ ๊ฒ์ ์ด๋ ค์์ด ์๋ ๊ฒ์ด์์. ๋น๋ ํจํด์ ์ด ๋ฌธ์ ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณ ์ ๋ ํจํด ์ค ํ๋์ธ๋ฐ, ์๋ฅผ ๋ค๋ฉด ์์ฑ์ ์ธ์๋ก ๋๋ฌด ๋ง์ ์ธ์๊ฐ ๋๊ฒจ์ง๋ ๊ฒฝ์ฐ ์ด๋ ํ ์ธ์๊ฐ ์ด๋ ํ ๊ฐ์ ๋ํ๋ด๋์ง๋ฅผ ํ์ธํ๊ธฐ ํ๋ค ์ ์์ฃ ! ๋ ์ด๋ ํ ๊ฐ์ฒด์ ๊ฒฝ์ฐ์๋ ํน์ ์ธ์๋ง์ผ๋ก ์์ฑํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ๋๋ ์๋ ๊ฒ์ด์์. ์ด๋ด ๊ฒฝ์ฐ ํน์ ์ธ์์ ํด๋นํ๋ ๊ฐ์ null๋ก ์ ๋ฌํด์ค์ผ ํ๋๋ฐ, ์ด๋ ์ฝ๋์ ๊ฐ๋
์ฑ ์ธก๋ฉด์์ ๋งค์ฐ ์ข์ง ์๋ค๋ ๊ฒ์
๋๋ค.
public Studnet(long id, String name, String major, int age, String address) {
this.id = id;
this.name = name;
this.major = major;
this.age = age;
this.address = address;
}
์์ ๊ฐ์ด ํ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์ฝ๋๊ฐ ์๋ค๊ณ ํ์ ๋, ํด๋ผ์ด์ธํธ์์๋
Student student = new Student(123456, "java", "hihi", 21, "secho");
์ด๋ฐ์์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฒ ๋๋ ๊ฒ์ด์์. ๊ทธ๋ฐ๋ฐ, ๋ง์ฝ ํ๋ฒ๊ณผ ์ด๋ฆ๋ง ์๋ ๊ฒฝ์ฐ์๋ ์ด๋ป๊ฒ ๋ ๊น์?
Stuent stuent = new Student(123456, "java", null, 0, null);
์์ ๊ฐ์ด Garbage Data๋, Null๊ฐ์ ๋ฃ์ด ํด๊ฒฐํ๊ฒ ๋๋๋ฐ, ์ด๋ด ๊ฒฝ์ฐ ํน์ ํ๋ผ๋ฏธํฐ๊ฐ ์ด๋ ํ ๊ฐ์ ๋ํ๋ด๊ธฐ ํ๋ค์ด ์ง๋ ๊ฒ์ด์์.
๋ง์ฝ Setter๋ฅผ ํตํด Java Bean์ ์์ฑํ๋ค๋ฉด ์ด๋จ๊น์?
Student student = new Studnet();
student.setId(123456);
student.setName("java");
student.setAge(21);
student.setMajor("hihi");
student.setAddress("secho");
ํด๋ผ์ด์ธํธ์์๋ ์ด๋ฐ์์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฒ ๋๋๋ฐ, ํจ์ ํธ์ถ 1ํ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด ์ผ๊ด์ฑ์ด ์ผ์์ ์ผ๋ก ๊นจ์ง ์ ์๋ ๊ฒ์ด์์. ๋ํ, immutable ๊ฐ์ฒด๋ ์์ฑํ ์ ์๊ฒ ๋์ง์!
์ ์ธต์ ์์ฑ์ ํจํด๊ณผ ์๋ฐ ๋น ํจํด์ ์ฅ์ ์ ๊ฒฐํฉํ ๊ฒ์ด ๋ฐ๋ก ๋น๋ ํจํด์ด๋ค.
ํด๋ผ์ด์ธํธ ์ฝ๋์์ ํ์ํ ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ๋ ๋์ , ๊ทธ ์ ์ ํ์ ์ธ์๋ค์ ์ ๋ฌํ์ฌ ๋น๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค, ๋น๋ ๊ฐ์ฒด์ ์ ์๋ ์ค์ Method๋ค์ ํธ์ถํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฒ ๋๋ ๊ฒ์ด์์.
๋น๋ ํจํด ์ฌ์ฉ ์ ๊ฐ์ฒด ์์ฑํ๋๋ฐ ์์ด ํ์ ์ธ์์ ์ ํ์ ์ธ์๋ฅผ ๊ตฌ๋ณํ ์ ์๊ฒ ๋๊ณ , ์ ํ์ ์ธ์์ ๊ฒฝ์ฐ ๋ณด๋ค ๊ฐ๋ ์ฑ์ด ์ข์ ์ฝ๋๋ก ์ธ์๋ฅผ ๋๊ธธ ์ ์๊ฒ ๋๋ ์ฅ์ ์ด ์๋ ๊ฒ์ด์์. ์ด๋ฌํ ์ฅ์ ๋ค์ ๊ฐ๊ณ ์์ผ๋ฉด์๋ ๊ฐ์ฒด ์ผ๊ด์ฑ์ ๊นจ์ง ์์ ์ ์์ต๋๋ค.
public interface Buildable<T> {
T build();
}
์ผ๋จ, interface๋ฅผ ํ๋ ๋ง๋ค์ด ๋ค๋ฅธ builder์๋ ์ ์ฉํ๋๋ก ํ ์ ์๋ ๊ฒ์ด์์.
public class Studnet {
private long id;
private String name;
private String major;
private int age;
private String address;
public Studnet() {
}
public static class Builder implements Buildable {
// ๋ณ๊ฒฝ ๋ถ๊ฐ ํญ๋ชฉ
private final long id;
private final String name;
// ๋ณ๊ฒฝ ๊ฐ๋ฅ ํญ๋ชฉ
private String major = "";
private int age = 0;
private String address = "";
public Builder major(String major) {
this.age = age;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Student build() {
return new Student(this);
}
}
private Student(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.major = builder.major;
this.age = builder.age;
this.address = builder.address;
}
}
Studnet Class์์ Builder๋ผ๋ ์ ์ Member Class๋ฅผ ํ๋ ๋ง๋ค๊ณ , interface๋ฅผ ๊ตฌํํ๊ฒ ํฉ๋๋ค.
์ต์ข
์ ์ผ๋ก build()๋ผ๋ Method๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑํ ๊ฒ์ธ๋ฐ์. Studnet Class์ ์ธ์คํด์ค ๋ณ์ id์ name์ ํ์ ์ธ์๋ก ์ ํํ์ฌ final์ด๋ผ๋ keyword๋ฅผ ์ถ๊ฐํ๊ณ , Builder๋ฅผ ์์ฑํ ๋ ์ธ์๋ก ๋๊ฒจ ๋ฐ๊ฒ ํ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋๋จธ์ง ์ ํ์ ์ธ์๋ค์ Builder๋ฅผ ๋ฐํํ๊ฒ ํ์ฌ Chaining์ ํตํด ์ธ์๋ฅผ ๋๊ฒจ ๋ฐ์ ์ ์๋๋ก ํ์์ต๋๋ค.
์ด๋ ๊ฒ ๋๋ฉด ํด๋ผ์ด์ธํธ ์ฝ๋๋ ์ด๋ป๊ฒ ๋ ๊น์?
Student student = new Student.Builder(123456, "java")
.major("hihi")
.age(21)
.address("secho")
.build();
์ด๋ ๊ฒ ์ฌ๋ฌ ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌํจ์๋ ์ด๋ ํ ๊ฐ์ด ์ด๋ ํ ์๋ฏธ์ธ์ง ํ์ ๋ ์ ์๊ณ , ํ์ ์ธ์์ ์ ํ ์ธ์๋ ๊ตฌ๋ณํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ์ ๋๋ค.
๋ค์ ๋ณธ๋ก ์ผ๋ก ๋์์์ ๊ตณ์ด ID์ ๊ตญํ ๋์ด ์๊ฐํ์ง ์๊ณ , ๊ฐ์ฒด ์์ฑ ์ ๋ฐ๋์ ์์ฑ๋์ด์ผ ํ๋ ๊ฒ๋ค์ ๋ํ ์์ ์ฑ์ ๋์ด๋ ์๊ฐ์ ๊ฐ๋ ๊ฒ์ด ์ค์ํ๊ฒ ์ง์?
ํด๋ฆฐ์ฝ๋, ์ ์ง๋ณด์ ํ๊ธฐ ์ข์ ์ฝ๋๋ค์ ์ด๋ฐ ์ฌ์ํ ๊ฐ์ฒด ์์ฑ๋ถํฐ ์์ฑํด๋ณด๋ ๊ฒ์ด ์ข๋ค๊ณ ์๊ฐ๋ฉ๋๋ค.
Builder ์ฌ์ฉ ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ต์ํ ํ์
@Builder
pubilc class Member {
...
}
Class ์์ @Builder
์ฌ์ฉ ์ @AllArgsConstuctor
Annotation์ ๋ถ์ธ ํจ๊ณผ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด์์.
(๋ชจ๋ ์ธ์คํด์ค ๋ณ์์ ๋ํด ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ๋ ์์ฑ์ ์์ฑ)
Member์ ID ์์ฑ ์ ๋ต์ DB์ Auto_Increament๋ฅผ ์์กดํ๋ค๊ณ ๊ฐ์ ํ์ ๋, ID๋ฅผ ๋๊ฒจ ๋ฐ์ง ์์์ผ ํ๋ ๊ฒ์ด์์. ๋, createAt, updateAt ๊ฐ์ ๊ฒฝ์ฐ @CreationTimestamp, @UpdateTimestamp
๊ฐ๊ฐ ํด๋น ์ผ์ ๋ด๋นํ๋ Annotation์ด ์๋ ๊ฒ์ด์์. ์ด์ฒ๋ผ ๊ฐ์ฒด ์์ฑ ์ ๋ฐ์ง ์์์ผ ํ Data๋ค์ด Class tkdeks @Builder
๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด์์.
public class Member {
@Builder
public Member(String email, String name) {
this.email = email;
this.name = name;
}
}
์์ ๊ฐ์ด ๋ฐ์์ผ ํ๋ ์์ฑ์๋ฅผ ํ์ ์กฐ๊ฑด์ ๋ฐ๋ผ ์ง์ ํ๊ณ , ๊ทธ ์์ @Builder
๋ฅผ ๋ถ์ด๋๊ฒ ์ข๊ฒ ์ต๋๋ค.
๊ทธ๋ผ ๋งค๊ฐ๋ณ์ name๊ณผ email๋ง ๋๊ฒจ ๋ฐ์ ์ ์๊ฒ ๋๋ ๊ฒ์ด์์.
'Back-End ์์ ์ค > Spring Framework' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring Boot] Service ๊ฐ๋ฐ ๋ฐ Test Case ์์ฑ (0) | 2021.08.11 |
---|---|
[Spring Boot] ํ์ ๊ด๋ฆฌ ์์ - Backend (0) | 2021.08.06 |
[Spring Boot] Spring Web ๊ฐ๋ฐ ๊ธฐ์ด (0) | 2021.08.05 |
[Spring Boot] thymeleaf์ Spring Boot (2) | 2021.08.04 |
Spring Frame Work ๊ธฐ์ด (0) | 2021.06.10 |