정적 팩토리 메서드 (정팩메)의 사용에 대해서

2025. 2. 16. 14:33·Side Tech Notes

스터디나 프로젝트를 하면서 많은 사람들이 생성자보다 정팩메를 우선적으로 사용하는 모습을 봤습니다.

하지만 저는 가능한 정팩메의 사용을 지양하는 편입니다. 그래서 정팩메의 사용에 대해 토의를 한 적이 여러 번 있어 제 기준에 대해 정리해보려고 합니다.

정적 팩토리 메서드 (정팩메)란?

정팩메는 static 메서드를 통해 객체를 생성하는 것을 의미합니다.

class Food {
    private int price;
    
    private Food(int price) {
    	this.price = price;
    }
    
    public static Food foodWithPrice(int price) {
        return new Food(price);
    }
}

 

 

그러면 왜 많은 사람들이 이런 정팩메를 많이 사용하는 걸까요?

생성자보다 정팩메를 우선적으로 사용하는 사람의 공통점은 프로그래밍을 공부한지 얼마되지 않았다는 점이었습니다.

그리고 이펙티브 자바라는 책을 읽거나 관련된 스터디를 해본 경험이 있습니다.

이 책에서 처음으로 소개하는 내용이 생성자 대신 정적 팩터리 메서드를 고려하라입니다.

물론 이 책을 비판하는 내용은 아닙니다. 전 아직 많이 부족하고 저도 이 책을 통해 공부를 많이 했었으니까요. 좋은 책입니다.

하지만 분명 고려하라라고 적혀있는데 이걸 무조건 정팩메가 더 좋다고 판단하여 무분별하게 정팩메를 사용하는 사람이 너무 많은 것 같습니다.

정팩메의 장점

1. 객체 생성 로직에 이름을 부여할 수 있다.

생성자는 생성 목적에 따라 오버로딩을 통해 생성자를 구분해서 사용할 수 있습니다.

class Food {
    private int price;
    private int amount;
    
    public Food(int price) {
    	this.price = price;
    }
    
    public Food(int price, int amount) {
    	this.price = price;
        this.amount = amount;
    }
}
public static void main(String[] args) {
    Food food1 = new Food(1000);

    Food food2 = new Food(2000, 3);
}

 

하지만 이런 방식은 다른 개발자가 보기에 코드의 의미를 파악하기 힘들 수 있습니다. 내가 원하는 객체를 생성하기 위해서 어떤 값을 몇번째 파라미터에 넣어야 될 지 매번 파악해야 하기 때문입니다.

이 부분을 정팩메를 통해 이름을 부여해주면 쉽게 파악할 수 있습니다.

class Food {
    private int price;
    private int amount;
    
    private Food(int price, int amount) {
    	this.price = price;
        this.amount = amount;
    }
    
    public static Food foodWithPrice(int price) {
        return new Food(price, 1);
    }
    
    public static Food foodWithPriceAndAmount(int price, int amount) {
        return new Food(price, amount);
    }
}

 

이런 식으로 이름을 통해 구현 의도를 전달 할 수 있습니다.

2. 인스턴스를 통제할 수 있다.

생성자를 통해 객체를 생성하게 되면 새로운 객체가 생성됩니다. 하지만 정팩메를 사용하면 기존의 객체를 재활용 할 수도 있습니다. 대표적으로 싱글톤 패턴이 있습니다.

class Food {
    private static final Food instance = new Food(5000, 3);
    
    private int price;
    private int amount;
    
    private Food(int price, int amount) {
    	this.price = price;
        this.amount = amount;
    }
    
    public static Food getInstance() {
        return instance;
    }
}

 

이런 방식을 통해 하나의 객체를 재사용하여 메모리를 관리할 수 있습니다.

3. 하위 타입을 반환할 수 있다.

class Food {
    private int price;
    private int amount;

    Food(int price, int amount) {
        this.price = price;
        this.amount = amount;
    }

    public static Food getMeat(int price, int amount) {
        return new Meat(price, amount);
    }

    public static Food getFish(int price, int amount) {
        return new Fish(price, amount);
    }
}
public class Fish extends Food {

    Fish(int price, int amount) {
        super(price, amount);
    }
}
public class Meat extends Food {
    Meat(int price, int amount) {
        super(price, amount);
    }
}

 

위와 같은 방식과 같이 다형성을 통해 반환할 객체의 인스턴스를 자유롭게 선택할 수 있습니다.

4. 매개변수에 따라 다른 객체를 반환할 수 있다.

분기문을 통해 매개변수로 들어오는 값에 따라 반환형을 선택할 수 있습니다.

class Food {
    private int price;
    private int amount;

    Food(int price, int amount) {
        this.price = price;
        this.amount = amount;
    }

    public static Food getFood(int price, int amount) {
        if (price < 10000) {
            return new Meat(price, amount);
        }
        return new Fish(price, amount);
    }
}

 

정팩메를 지양하는 이유

코드 파악의 어려움

만약 정팩메를 사용한다고 하면 가급적 생성자는 private으로 선언해야 한다고 생각합니다. 만약 생성자와 정팩메 모두 사용한다면 객체 생성 방식이 일관되지 않아 정확한 의도를 전달할 수 없다고 생각합니다.

그러면 클래스 Food의 생성자를 private으로 선언하고 정팩메를 도입한 상황을 가정하겠습니다.

이 상황에서 다른 개발자(A)가 중간에 프로젝트에 참여하게 되었습니다. 이 개발자 A가 개발을 진행하던 도중 Food를 생성할 상황이 발생했습니다.

이 상황에서 객체를 생성하기 위해 대부분의 개발자는 제일 먼저 생성자를 사용할 것이라고 생각합니다. 그래서 A도 생성자를 통해 Food를 생성하려고 했지만 생성자를 private으로 선언했기 때문에 컴파일 오류가 발생합니다. 그러면 A는 이 객체를 생성할 방법을 찾기 위해 다른 개발자를 찾아가 질문하거나 Food 클래스의 코드를 살펴보며 정팩메를 찾아야 합니다.

저는 이런 과정이 협업에서 발생하는 리소스라고 생각합니다. 이런 리소스를 최대한 줄이는 코드가 좋은 코드라고 생각하기 때문에 저는 정팩메를 최대한 지양하고 있습니다.

 

결론

저는 정팩메의 장점보다 정팩메를 통한 협업의 리소스 증가가 더 크다고 판단해 최대한 정팩메를 지양하고 있습니다.

단, 이 말이 정팩메를 사용하지 않는다를 의미하는 것은 아닙니다. 제가 좋아하는 말중에 은총알은 없다라는 말이 있습니다. 코드에 절대적인 정답은 없다는 뜻입니다. 중요한 것은 자신의 코드에 대한 기준과 그에 대한 명확한 근거라고 생각합니다.

 

저는 위의 코드 파악의 어려움을 근거로 가능한 정팩메의 사용을 지양하고 만약 사용하게 된다면 그 당위성에 대해 동료들에게 PR이나 주석으로 설명해야 한다고 생각합니다.

No Silver Bullet

- Essence and Accident in Software Engineering

'Side Tech Notes' 카테고리의 다른 글

리액터 패턴 / 프로액터 패턴  (1) 2025.07.19
AWS CloudFormation  (0) 2025.05.27
@Transactional과 동시성 제어를 위한 Lock의 관계  (0) 2025.05.23
빌더 패턴이 정말로 좋을까  (0) 2025.03.24
좋은 코드란 무엇일까 (feat. 객체지향)  (0) 2025.02.21
'Side Tech Notes' 카테고리의 다른 글
  • AWS CloudFormation
  • @Transactional과 동시성 제어를 위한 Lock의 관계
  • 빌더 패턴이 정말로 좋을까
  • 좋은 코드란 무엇일까 (feat. 객체지향)
ggio
ggio
개발 공부를 하며 배운 내용을 기록합니다.
  • ggio
    기록을 하자
    ggio
  • 전체
    오늘
    어제
    • 분류 전체보기 (41)
      • SW마에스트로 (5)
      • System Architecture (8)
      • Algorithm (15)
      • Side Tech Notes (7)
      • CS (5)
      • 취준 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Programming
    Algorithm
    ha 아키텍처
    소마
    3PC
    객체지향
    다중화
    코테
    fail back
    소프트웨어 마에스트로
    분산락
    at-least-once
    부트캠프
    프로액터 패턴
    매일메일
    코딩테스트
    비관락
    SW마에스트로
    리트코드
    메시지 큐
    토스 NEXT
    알고리즘
    멀티 코어
    leetcode
    리액터 패턴
    지리적 분산
    시스템 아키텍쳐
    프로그래밍
    fail over
    시스템 설계
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
ggio
정적 팩토리 메서드 (정팩메)의 사용에 대해서
상단으로

티스토리툴바