오늘 데일리 미팅은 학습로그 회고 시간. 조이와 함께 상속과 조합에 대하여 이야기하고 있었다.

제이슨이 갑자기 나타나 던진 질문.

“싱글턴과 정적 클래스의 차이가 뭔가요?”

그 순간의 내 생각

  • 싱글턴 패턴은 그래도 객체를 생성한다.

    객체지향 프로그래밍이란 협력을 위해 객체들 사이에 메시지를 주고 받는다. 싱글턴 패턴은 협력에 참여하는 객체지만 협력에서 하나만 존재해야되는 객체를 위해 제한을 두는 디자인 패턴이다. 하지만 정적 클래스는 단순히 서로 연관된 메소드를 묶어두기만 할 뿐, 객체가 아니고 데이터 처리 관점에서 보는 절차적 프로그래밍에 가깝다. ‘클래스는 객체의 팩토리이며, 객체를 만들고, 추적하고, 적절한 시점에 파괴한다’라는 관점에서 봤을 때, 싱글턴 패턴은 객체의 생성을 하나로 제한하는 역할을 한다는 점에서 문제가 없다고 생각했다.

  • 싱글턴 패턴은 코드 상에서 의존 관계를 명확하게 보여준다.

    한 객체가 다른 객체를 생성하거나 다른 객체의 메소드를 호출하는 경우를 의존한다고 표현한다. 만약 싱글턴 패턴의 객체를 사용할 때는 메소드 내에서 사용하기 위해서 객체를 생성하거나 파라미터로 전달 받아야 하기 때문에, 의존 관계를 명확하게 알 수 있다.

      void myMethod(Singleton singleton) {
      	singleton.methodA();
      }
    
      // 또는
    
      void myMethod() {
      	Singleton singleton = Singleton.valueOf();
      	singleton.methodA();
      }
    

    하지만 정적 클래스의 경우에는 객체의 생성, 파라미터로 넘길 필요없어서 의존 관계를 파악하기가 쉽지않다.

      void myMethod() {
      	MyUtils.methodA();
      }
    

실제로 어떤 차이점이 있는가

결론부터 말하자면 실제로도 싱글턴 패턴이 정적 클래스보다 선호된다고 한다. 그 이유를 알아보자.

  • 테스트 가능성

    싱글턴 패턴은 상태를 가질 수 있고, 생성과 파괴 시기를 선택할 수 있어 여러 가지 테스트를 하는데 문제가 없지만, 정적 클래스의 경우는 테스트마다 영향을 받을 수 있어 어려움을 느낀다. 또한 스태틱 클래스는 mocking이 불가능하거나 구현에 제한이 있기때문에 테스트에 한계가 있다.

  • 확장성

    싱글턴 패턴은 상속을 할 수 있다. 따라서 기존의 클래스 특징과 같이 상속을 이용하여 다형성과 확장성을 구현할 수 있다.

  • 인터페이스의 구현

    “유연한 프로그램을 만드려면 인터페이스를 타입으로 사용하라” 라는 말이 있다. 나중에 새롭게 구현된 클래스가 생겨도 추가적인 코드 수정없이 사용이 가능하기 때문이다. 이 이상은 이 글의 주제와 벗어나니 ‘Effective Java 3rd Edition’ 책의 ‘Item64 객체는 인터페이스를 사용해 참조하라’를 참고하도록 한다. 싱글턴 패턴은 정적 클래스와 달리, 이 인터페이스의 구현이 가능하다. 인터페이스를 구현해주고 그 객체의 생성을 클래스에서 한 개로 제한하는게 싱글턴 패턴이다.

사실 싱글턴 패턴도 안티 패턴이다

위의 내용으로 차이점을 정리하려고 했는데 제이슨이 슬랙으로 약간의 힌트를 던져줬다. 놀랍게도 거기에 있는 내용들은 위의 내용들을 반박하고 있다.

  • 의존성이 메소드 시그니처에 의해 노출되지 않는다.

    싱글턴 패턴은 어차피 하나의 인스턴스를 가지기 때문에 인터페이스의 구현에서 싱글턴 객체의 의존성을 숨겨버릴 수 있다. 이는 싱글턴 패턴의 수정이 있을 경우에 의존 관계인 메소드를 파악하는데 문제가 될 것이다.

  • 단위 테스트를 만들기 어렵다.

    싱글턴 패턴은 애플리케이션의 수명 동안 상태를 유지한다. 따라서 싱글턴 객체의 테스트 실패로 인해 다른 테스트들에 영향을 주는 상황이 발생할 수 있다. 따라서 단위 테스트를 만들기 어렵다.

그럼 어떻게 구현하라고

컨트롤러에 의존성 주입을 하는 것이다. ‘의존성 주입’이 무슨 뜻인지 이해를 돕기위해서 링크를 참고하기를 바란다. 내가 이해한 내용을 정리해보자면, 일단 실제로 하나만 존재하는 객체를 클래스 내에서 제한할 필요가 없다. 또한 컨트롤러에 생성자를 통해 단일 객체의 종속성을 주입시킨다.

참고 자료

https://medium.com/@karmanno/why-are-static-embers-and-methods-bad-for-object-oriented-design-b4d0c141512c

https://volosoft.com/blog/Prefer-Singleton-Pattern-over-Static-Class

https://www.yegor256.com/2016/06/27/singletons-must-die.html

최범균 (2013). 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴

댓글남기기