CS | 싱글톤 패턴, 의존성 주입

happy tiger·2022년 10월 9일
1

CS

목록 보기
3/10
post-thumbnail

싱글톤 패턴이란?

싱글톤 패턴(singleton pattern): 하사용자가 여러 번 객체 생성을 하더라도 클래스로부터 오직 하나의 객체(인스턴스)만 생성되도록 하는 디자인 패턴. 보통 데이터베이스 연결 모듈에 많이 사용된다.
(디자인 패턴: 프로그램을 설계할 때 발생했던 문제점들을 객체 간의 상호 관계 등을 이용하여 해결할 수 있도록 하나의 '규약' 형태로 만들어 놓은 것)

  • 장점
    • 하나의 인스턴스를 만들어 놓고 해당 인스턴스를 다른 모듈들이 공유하며 사용하기 때문에 인스턴스를 생성할 때 드는 비용이 줄어든다.
    • 오직 유일한 객체를 통해서만 어떤 리소스에 접근해야하는 제약이 있는 상황에서 유용하다. 클래스를 사용하는 입장에서 실수롤 여러 번 객체 생성을 시도하더라도 내부적으로 오직 하나의 객체만 생성되고 사용된다.
  • 단점
    • 의존성이 높아진다. 즉 모듈 간의 결합을 강하게 만든다.
    • TDD(Test Driven Development)를 할 때 단위 테스트를 주로 하는데, 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행할 수 있어야 한다. 하지만 싱글톤 패턴은 미리 생성된 하나의 인스턴스를 기반으로 구현하는 패턴이므로 각 테스트마다 '독립적인' 인스턴스를 만들기 어렵다.

예제 코드 with Python

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):         # Foo 클래스 객체에 _instance 속성이 없다면
            print("__new__ is called\n")
            cls._instance = super().__new__(cls)  # Foo 클래스의 객체를 생성하고 Foo._instance로 바인딩
        return cls._instance                      # Foo._instance를 리턴

    def __init__(self, data):
        cls = type(self)
        if not hasattr(cls, "_init"):             # Foo 클래스 객체에 _init 속성이 없다면(instance가 생성된 적이 없다면)
            print("__init__ is called\n")
            self.data = data
            cls._init = True


s1 = Singleton(3)  # __new__is called
s2 = Singleton(4)  # __init__is called
print(s1.data)     # 3
print(s2.data)     # 3
print(s1 is s2)    # True(같은 주소를 가지고 있는 두 객체 s1, s2)

예제 코드에서 알 수 있다시피 s1 = Singleton(3)에서 인스턴스가 생성되었으므로, s2 = Singleton(4)에서 새로운 인스턴스를 생성하지 않고 앞서 만들어진 인스턴스를 가리키게 된다. 고로, s1과 s2는 하나의 객체를 가리키므로 주소와 데이터 모두 동일하다.

의존성 주입

싱글톤 패턴은 사용하기 쉽고 굉장히 실용적이지만 모듈 간의 결합을 강하게 만든다는 즉, 하나의 모듈의 변경사항이 다른 모듈에 영향을 미칠 수 있다는 단점이 있다. 이때 의존성 주입(DI, Dependency Injection)을 통해 모듈 간의 결합을 조금 더 느슨하게 만들어 해결할 수 있다.

앞의 그림처럼 메인 모듈(main mudule)이 '직접' 다른 하위 모듈에 대한 의존성을 주기보다는 중간에 의존성 주입자(dependency injector)가 이 부분을 가로채 메인 모듈이 '간접'적으로 의존성을 주입하는 방식이다.
이를 통해 메인 모듈(상위 모듈)은 하위 모듈에 대한 의존성이 떨어지게 된다. 참고로 이를 '디커플링이 된다'고도 한다.

의존성 주입의 장점

  • 모듈들을 쉽게 교체할 수 있는 구조가 되어 테스팅하기 쉽고 마이그레이션하기도 수월하다.
  • 구현할 때 추상화 레이어를 넣고 이를 기반으로 구현체를 넣어 주기 때문에 애플리케이션 의존성 방향이 일관되고, 애플리케이션을 쉽게 추론할 수 있으며, 모듈 간의 관계들이 조금 더 명확해진다.
  • 낮은 결합도로 변경에 용이하고, 다른 객체와의 협력 관계에 더 집중하게 해준다.

의존성 주입의 단점

  • 모듈들이 더욱더 분리되므로 클래스 수가 늘어나 복잡성이 증가된다.
  • 약간의 런타임 패널티가 생기기도 한다.

의존성 주입 원칙

  1. 상위 모듈은 하위 모듈에서 어떠한 것도 가져오지 않아야 한다.
  2. 둘 다 추상화에 의존해야 하며, 이때 추상화는 세부 사항에 의존하지 말아야 한다.
profile
호기심·끈기·성장·발전·행복·협력 ٩(๑•̀ㅂ•́)و

1개의 댓글

comment-user-thumbnail
2022년 11월 1일

장점 부분 실수롤 이라는 오타가 있습니다.

답글 달기