본문 바로가기
Design Pattern

[Design Pattern] Singleton Pattern

by Jiseong 2022. 3. 31.

Design Pattern은 역사적으로 프로그래밍을 할 때 자주 발생하는 문제점들을 해결하기 위해 생겨난 구조, 패턴이다.

 

우린 이 공통된 오답노트같은 패턴들을 사용하고, 참조하며 개발을 한다.

 

공통화 덕에 생긴 이점은 동일한 문제에 대해서는 특정 표준 설계법을 사용하여 다른 개발자와 의사소통을 원활하게 하고, 코드가 방대해질 경우 흐름을 파악하는데도 큰 도움이 된다.

 

오늘 알아볼 패턴은 Singleton Pattern 이다.

 

위키백과는 Singleton을 다음과 같이 정의했다.

In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one "single" instance.  This is useful when exactly one object is needed to coordinate actions across the system.
 

한개의 클래스가 생성하는 인스턴스는 단 한개여야 한다.

???

말이 좀 이상함 

 

여튼.. 저 말은 한개의 클래스를 여러번 인스턴스화를 시켜도 생성되는 인스턴스는 단 한개여야 한다. 임을 말한다

 

그렇다면.. 어떨 때 쓰일까?

 

실제로 Swift에서는 싱글톤 패턴으로 이뤄진 중요한 놈들 몇몇이 있다. 

 

그중에 몇가지를 보자면..

  • URLSession shared
  • UserDefaults standard
  • NotificationCenter
  • FileManager default

우리가 허구엇날 쓰는 URLSession,  NotificationCenter 같은 여러곳에서 공통적으로 쓰이는 타입의 인스턴스가 사용하는 곳마다 생겨난다면.. 메모리 낭비일 것이다.

 

이러한 메모리 낭비 등의 상황을 방지하기 위해 생겨난 패턴이다.

 

공통적으로 쓸 데이터를 저장할 창고가 있는데, 이를 쓰는 사람마다 개인적인 창고를 다 만들어버린다면..?

 

창고로 사용할 땅(메모리)은 한정되어 있는데.. 아니 땅이 남아 돌아도 쓰잘데기 없는 자리 차지는 피해야 되겠지

 

이런 상황을..  하나의 창고를 여럿이 공유하게 된다면?

 

이젠 실제 예제를 살펴보자

 

 

Swift Singleton Pattern 구현 방법

class SingleTonPatternExample {
   static let shared = SingleTonPatternExample()
   private init {}
}

간단하다.

 

우린 해당 싱글톤 클래스를 static으로 생성하여 여러 타입이 전역적으로 사용할 수 있게 만들고, private init을 통해 해당 클래스의 새로운 인스턴스화를 막아 클래스가 단 한번만 생성되도록 한다.

 

근데 여기서 문제점이 드러난다.

 

"여러 타입이 전역적으로 사용"

 

이제 장단점을 알아볼거니 이건 아래에서 알아보자

 

 

Singleton Pattern의 장단점

장점

  • 메모리를 단 한번만 사용한다.
    • 객체가 단 한번만 만들어지기 때문에 메모리 관리가 편하고, 한번 만들어진 객체를 재사용할 수 있다.
  • 새로운 인스턴스를 생성하고, 메모리 할당, 초기화 과정이 줄어듦으로 인해 객체 접근 시간이 줄어든다.
  • 어디서든 접근할 수 있기 때문에 쉽게 데이터를 공유할 수 있다.

단점

  • 테스트가 힘들다.
    • 싱글톤 패턴을 이용하여 생성한 객체는 단 한번만 생성이 되야하기 때문에 이니셜라이저를 private하게 만들어 생성을 제한한다. 이 때문에 테스트를 위한 Mock객체를 생성할 수 없게 되고, 관련 로직을 테스트할 수 없는 상황이 발생할 수 있다.
  • 의존성 문제가 있다.
    • 어디서든 접근할 수 있기 때문에 생성이나, 사용을 남발하게 된다면 스파게티 코드가 될 위험성이 크다.
  • 멀티 스레드 환경에서 싱글톤 객체 내부의 데이터를 동기적으로 처리하지 않으면 여러 객체가 동시에 싱글톤 객체에 접근하면서 Race Condition이 발생할 수 있다.
    • 이를 해결하기 위해선 싱글톤 객체 내부 데이터를 접근하는 코드가 동기적으로 수행되도록 DispatchQueue sync를 걸거나 semaphore를 이용하여 데이터에 동시로 접근할 수 있는 객체의 수를 제한하여 예방할 수 있을 것 같다.

 

유의할 점

싱글턴 객체가 다른 객체의 인스턴스를 참조하고 있으면 절대 안된다.

 

필요한 특정 객체의 값을 넘겨받게하여 다른 객체의 리테인 카운트가 오르지 않게 해야한다. 이유는 싱글턴 객체는 계속 살아있으므로.. 싱글턴 객체가 참조하고있는 특정 클래스 인스턴스 또한 살아있겠지..? 

'Design Pattern' 카테고리의 다른 글

[Design Pattern] Coordinator Pattern  (0) 2022.07.29
[Design Pattern] Mediator Pattern  (0) 2022.03.20

댓글