o-ohi-code 님의 블로그

[Spring Framework] Builder 어노테이션 본문

카테고리 없음

[Spring Framework] Builder 어노테이션

o-ohi-code 2025. 4. 5. 09:22

@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;
}