Spring Service에서 객체 생성 책임을 분리해야 하는 이유 – 실무에서 Factory 패턴을 도입한 회고
2025. 5. 29. 13:37
728x90

– 에스크로 서비스 개발 중 도입한 Factory 패턴 회고


도입: 기능 구현은 끝났지만, 찝찝했던 코드

에스크로 거래를 등록하는 기능을 만들던 중이었다.
비즈니스 흐름은 단순했다.
거래 등록 요청을 받아 EscrowTransaction 객체를 만들고, 이를 저장소에 저장하면 되는 구조였다.

초기 코드는 다음과 같았다.

public Long registerTransaction(TransactionRegisterCommand command) {
    EscrowTransaction transaction = new EscrowTransaction(
        command.getBuyerId(),
        command.getSellerId(),
        command.getItemId(),
        command.getAmount(),
        command.getDescription()
    );

    transactionRepository.save(transaction);
    return transaction.getId();
}

겉보기엔 아무런 문제 없어 보였다.
하지만 시간이 지나면서, 똑같은 방식으로 new 키워드로 객체를 생성하는 코드가 여기저기서 반복되기 시작했다.


불편함의 시작: 중복, 책임, 확장성

처음엔 이 정도 중복은 괜찮다고 생각했다.
그런데 비슷한 구조의 객체가 계속 생기고, 도메인 로직이 점점 복잡해지자 Service 코드가 지저분해졌다.

그때 다음과 같은 의문이 들었다.

“Service는 정말 이 객체들을 직접 생성해야 할까?”

그 질문을 중심으로 코드를 다시 들여다보니, 다음과 같은 문제가 눈에 들어왔다.

1. 책임이 뒤섞여 있었다

  • Service는 본래 트랜잭션 흐름을 제어하고 도메인을 조합하는 역할이다.
  • 그런데 EscrowTransaction 객체를 생성하는 책임까지 갖고 있었다.

2. 중복 생성 로직이 도처에 퍼져 있었다

  • 생성자 파라미터가 길어지자 복사-붙여넣기로 Service마다 객체를 만들고 있었다.
  • 생성 방식이 바뀌면 영향을 받는 코드가 너무 많았다.

3. 테스트와 유지보수도 힘들어졌다

  • 객체 생성 로직이 분산되어 있어 단위 테스트가 어려웠다.
  • 추후 정책이 바뀌면 Service 코드를 하나하나 고쳐야 했다.

구조 개선: 객체 생성 책임을 Factory로 분리하기

객체 생성이 여기저기 흩어져 있으면 응집도가 떨어진다.
그래서 Service는 객체를 생성하는 게 아니라 요청만 하도록 바꾸기로 했다.
이때 선택한 방식이 바로 Factory 패턴이다.

 EscrowTransactionFactory

@Component
public class EscrowTransactionFactory {

    public EscrowTransaction create(TransactionRegisterCommand command) {
        return new EscrowTransaction(
            command.getBuyerId(),
            command.getSellerId(),
            command.getItemId(),
            command.getAmount(),
            command.getDescription()
        );
    }
}

 Service에서의 변경

public Long registerTransaction(TransactionRegisterCommand command) {
    EscrowTransaction transaction = transactionFactory.create(command);
    transactionRepository.save(transaction);
    return transaction.getId();
}

단지 한 줄이 바뀌었을 뿐인데, 의미 있는 변화가 생겼다.


개선 효과: 작은 리팩토링, 큰 변화

이 방식의 효과는 의외로 컸다.

항목 기존 방식 Factory 도입 후
객체 생성 책임 Service가 직접 생성 Factory로 책임 분리
코드 중복 여러 Service에 new 반복 Factory에서 일관 생성
변경 대응 생성자 변경 시 Service 수정 Factory만 수정
테스트 용이성 파라미터 조합 테스트 어려움 Factory 단위 테스트 가능
 

회고: 실무에서 느낀 Factory 패턴의 가치

이전에는 “Factory는 복잡한 도메인에만 쓰는 패턴”이라고 생각했다.
하지만 막상 실무에서 객체 생성 책임이 섞여버리니, 유지보수가 점점 피로해졌다.

특히 에스크로 트랜잭션처럼 생성 조건이 많고, 생성 방식이 바뀔 가능성이 있는 도메인이라면
Factory를 별도로 분리해두는 것이 장기적인 유지보수에 훨씬 유리하다는 걸 체감했다.

또한, 이렇게 책임을 분리하면 단위 테스트도 명확해지고,
Factory 내부에서 정책이 바뀌더라도 Service는 전혀 영향을 받지 않는다.


정리 요약

  • Service가 도메인 객체를 직접 생성하는 것은 책임 분리 원칙(SRP)을 위반할 수 있다.
  • Factory 패턴을 도입하면 생성 책임을 위임하고, Service는 흐름 제어에만 집중할 수 있다.
  • 중복 제거, 가독성 향상, 테스트 용이성, 유지보수성까지 긍정적인 영향을 준다.
반응형