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 |