Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- API
- REST API
- JavaScript
- HTTP
- react
- Spring Framework
- vue
- Github
- vue3
- 어노테이션
- 뷰
- Java
- error
- pls-00103
- CS
- Spring
- oracle
- GIT
- Entity
- 프레임워크
- SQL
- autowired
- 깃허브에러
- JSON
- https
- framework
- 개발자기록
- bean
- DTO
- spring boot
Archives
- Today
- Total
o-ohi-code 님의 블로그
[Spring Framework] Builder 어노테이션 본문
@Builder
Bulider는 필드가 많은 객체를 가독성 좋고, 실수 없이, 유연하게 만들기 위한 디자인 패턴이다.
DTO 에서 자주 사용되지만, Entity, 설정 객체, 테스트 객체 등 다양한 곳에서 활용
🤔 그럼 우리는 Builder 라는 어노테이션을 언제 사용하게 되는 걸까?
우선 기본으로 돌아가서 단순히 객체를 만든다고 가정
// 1. 클래스 생성
public class Person {
String name;
int age;
// 2. 생성자 만들기
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// 3. 객체 생성
Person p = new Person("영웅", 30);
이런식으로 자바 객체가 만들어 질 것이다.
하지만.. 필드가 많아진다면??
// 클래스 만들고
public class Member {
String name;
int age;
String address;
String phone;
String email;
String job;
...
// 생성자 (constructor)
public Member(String name, int age, String address, String phone, String email, String job) {
this.name = name;
this.age = age;
this.address = address;
this.phone = phone;
this.email = email;
this.job = job;
}
...
}
// 객체 생성시
// 이게 어떤 값인지 보기 힘들고, 순서 바꾸거나, 중간에 빠뜨리면 오류가 나게 된다.
Member m = new Member("영웅", 30, "서울", "010-1234-5678", "me@mail.com", "개발자");
그래서 등장한 방법이 Setter 방식이다.
public class Member {
private String name;
...
// 없어도 되지만, 써두면 명확해짐!
public Member() {}
public void setName(String name) {
this.name = name;
}
...
}
Member m = new Member();
m.setName("영웅");
m.setAge(30);
m.setAddress("서울");
- 장점은 순서 상관없이 값을 넣을 수 있다는 것이지만
- 단점은 코드가 너무 길어지고, 불변성이 깨질 수 있다는 점이다.
그리고 나온 게 Builder 어노테이션을 이용한 방식이다.
public class Member {
private String name;
private int age;
private String address;
// ❗ 생성자 (Builder에서 사용)
public Member(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
// ✅ 내부 static Builder 클래스
public static class MemberBuilder {
private String name;
private int age;
private String address;
public MemberBuilder name(String name) {
this.name = name;
return this;
}
public MemberBuilder age(int age) {
this.age = age;
return this;
}
public MemberBuilder address(String address) {
this.address = address;
return this;
}
public Member build() {
return new Member(name, age, address);
}
}
// builder() 메서드
public static MemberBuilder builder() {
return new MemberBuilder();
}
}
Member m = Member.builder()
.name("영웅")
.age(30)
.address("서울")
.phone("010-1234-5678")
.build();
@Builder 어노테이션을 사용한 코드의 흐름
Member.builder()
Static 을 사용하여 class Member 를 객체 생성 없이 바로 사용이 가능하게 만들었다.
먼저 Static 이란?
클래스에 소속되는 '고정된 메모리'
객체(instance)를 만들지 않아도 사용할 수 있다.
// Static 이 없는 경우 (인스턴스 메서드)
public class Hello {
public void sayHi() {
System.out.println("Hi!");
}
}
// 사용하기 위해서는 객체를 만들어 주어야 한다.
Hello h = new Hello();
h.sayHi(); // "Hi!" 출력
=========================================
// Static 이 있는 경우 (클래스 메서드)
public class Hello {
public static void sayHi() {
System.out.println("Hi!");
}
}
// 객체 생성 없이 바로 사용 가능
Hello.sayHi(); // "Hi!" 출력
Member 클래스 안에 있는 builder() 메서드 실행
public Member build() {
return new Member(name, age, address);
}
// 내부에서 new MemberBuilder() 생성 하여
// MeberBuilder() 객체 안의 메서드를 쓰기 위해서 생성자를 호출하는 것이다.
.name(영웅)
public MemberBuilder name(String name) {
this.name = name;
return this;
}
// MemberBuilder 메서드 실행 영웅이라는 값이 들어와서
// return this 를 통해 "자기 자신(MemberBuilder 객체)를 리턴한다.
여기서 사용된 방식이 메서드 체이닝 방식이다.
https://o-ohi-code.tistory.com/37
[Java] 메서드 체이닝이란?
메서드 체이닝여러 개의 메서드를 한 줄로 이어서 호출하는 방식을 말한다.각 메서드가 자기 자신(this)을 리턴하기 때문에 가능하다.메서드 체이닝 없는 방식 ❌ (일반적인 호출)StringBuilder sb = ne
o-ohi-code.tistory.com
.builder()
// builder() 메서드
public static MemberBuilder builder() {
return new MemberBuilder();
}
// 이때까지 .name(), .age(), .address() 로 임시로 저장된 값들을
// 진짜 Member 객체에 넣어서 new Member(...) 로 만들어 준다.
🤔 하지만 @Builder 어노테이션을 활용하면?
// 이런식으로 간단하게 사용 할 수 있다.
@Builder
public class Member {
private String name;
private int age;
private String address;
}