TIL/CS(feat. Swift)

디자인 패턴 훑어보기_싱글톤 패턴

여의도사노비 2023. 2. 5. 22:45
728x90

싱글톤 패턴

싱글톤 패턴(Singleton Pattern)은 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴이다. 보통 데이터베이스 연결 모듈에 많이 사용한다. 주로 공통된 객체를 여러개 생성해서 사용해야하는 상황(*데이터 베이스에서 커넥션 풀, 스레드풀, 캐시, 로그 기록 객체 등)에 많이 쓰인다.

 

 

장점

  • 객체를 생성할 때마다 메모리 영역을 할당받아야 한다. 하지만 한번의 new를 통해 객체를 생성한다면 메모리 낭비를 방지할 수 있다.
  • 싱글톤으로 구현한 인스턴스는 '전역'이므로, 다른 클래스의 인스턴스들이 데이터를 공유하는 것이 가능하다.

 

단점

  • 싱글톤 인스턴스가 너무 많은 일을 하거나, 많은 데이터를 공유시킬 경우 다른 클래스의 인스턴스들 간 결합도가 높아져  "개방=폐쇄" 원칙을 위배한다.(개방 폐쇄 원칙이란: 기존의 코드를 변경하지 않으면서, 기능을 추가할 수 있도록 설계가 되어야한다는 객체 지향 설계 원칙)
  • TDD(Test Driven Development)를 할 때 걸림돌이 된다. TDD를 할 때 단위 테스트를 주로 하는데, 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행할 수 있어야 한다. 하지만 싱글톤 패턴은 미리 생성된 하나의 인스턴스를 기반으로 구현하는 패턴이므로 각 테스트마다 '독립적인' 인스턴스를 만들기가 어렵다.

 

싱글톤 패턴을 사용하다 보면 2번 단점에 해당하는 결합도 문제가 생길 수 있다. 이러한 문제를 해결하기 위해 의존성 주입이라는 방법을 활용한다. 의존성 주입이란 메인 모듈이 '직접' 다른 하위 모듈에 대한 의존성을 주기보다, 중간에 의존성 주입자가 이 부분을 가로채 메인 모듈이 간접적으로 의존성을 주입하는 방식이다. 이를 통해 메인 모듈은 하위 모듈에 대한 의존성이 떨어지게 된다.

 

이로 인해 모듈들을 쉽게 교체할 수 있는 구조가 되어 테스팅하기 쉽고 마이그레이션하기도 수월하다. 또한 구현할 때 추상화 레이어를 넣고 이를 기반으로 구현체를 넣어 주기 때문에 애플이케이션 의존성 방향이 일관되고, 쉽게 추론할 수 있으며, 모듈간의 관계들이 조금 더 명확해진다.

 

하지만 한편으로는 의존성 주입으로 인해 클래스 수 증가하고 이로 인해 복잡성 증가할 수 있다. 또한 런타임 패널티가 발생 가능하다.

 

이미지 참고: '면접을 위한 CS 전공지식 노트', 주홍철

 

Swift로 보는 간단한 예시

class UserInfo {
	// 자신을(UserInfo) 객체로 생성해서 전역변수(TypeProperty)에 할당
    static let shared = UserInfo()

    var id: String?
    var password: String?
    var name: String?

    private init() { }
}

// 뷰컨트롤러는 여러개이지만 각자가 부르는 객체는 동일!
//A ViewController
let userInfo = UserInfo.shared
userInfo.id = "Jack"

//B ViewController
let userInfo = UserInfo.shared
userInfo.password = "0000"

//C ViewController
let userInfo = UserInfo.shared
userInfo.name = "Jeon"

// 아예 새로운 객체를 생성할 수도 있음
// let anotherUserInfo = UserInfo()
// anoterhUserInfo.id = "Jack2"
// 하지만 위의 코드는 현재 private init()이 선언되어 있기 때문에 생성 불가능!
// private init()이 없다면 생성 가능!

(코드 참고: https://babbab2.tistory.com/66)

 

 

싱글톤 패턴은 주로 관리를 목적으로 많이 사용되는데, 실제 코드를 짤때 사용되는 경우는

let screen = UIScreen.main

let application = UIApplication.shared

let notification = NotificationCenter.default

화면, 앱, 노티피케이션 센터 등으로 하나의 객체를 가지고 상태를 관리할 때 주로 사용된다.