Post

싱글톤 패턴

싱글톤 패턴

싱글톤 패턴(Singleton Pattern): 언제, 왜, 어떻게 써야 할까

개요

싱글톤 패턴은 전역에서 동일한 인스턴스를 공유할 수 있도록 보장하는 디자인 패턴이다. 한 번 생성된 객체는 앱이 종료될 때까지 유지되며, 이후 모든 접근은 동일한 인스턴스를 참조한다. Swift, Objective-C 등에서 자주 사용되며, 설정, 네트워크 통신, 캐시 등 상태를 공유해야 하는 기능에 주로 활용된다.


목적

  • 하나의 인스턴스만 존재해야 하는 경우 사용
  • **전역 접근(global access)**이 필요할 때 유용
  • 인스턴스 생성 비용이 크거나, 여러 객체 간 데이터 일관성 유지가 중요한 경우

구현 방법 (Swift 예제)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final class UserManager {
    static let shared = UserManager()

    private init() { }

    var currentUser: String?

    func login(user: String) {
        currentUser = user
    }

    func logout() {
        currentUser = nil
    }
}

사용 예

1
2
UserManager.shared.login(user: "sangjin")
print(UserManager.shared.currentUser) // sangjin
  • static let shared는 앱 전체에서 접근 가능한 인스턴스를 생성
  • private init()으로 외부에서 new를 막아 단 하나의 인스턴스만 존재하도록 제한

실제 적용 사례

1. 네트워크 레이어

1
2
3
4
5
6
7
8
final class APIClient {
    static let shared = APIClient()
    private init() {}

    func request(endpoint: String) {
        // URLSession 코드
    }
}
  • 매번 새로운 인스턴스를 생성하지 않고, 하나의 APIClient를 공유해 사용
  • URLSession, 토큰 등 상태를 공유해야 하는 경우 유용

2. 설정값 또는 캐시 저장소

1
2
3
4
final class Settings {
    static let shared = Settings()
    var isDarkMode: Bool = false
}
  • 앱 내 다양한 화면에서 동일한 설정 값 접근 가능

장점

  • 메모리 낭비 방지: 한 번만 생성되므로 리소스 절약
  • 데이터 일관성 보장: 여러 객체에서 동일한 인스턴스를 공유
  • 글로벌한 접근 가능: 전역에서 쉽게 접근

단점과 주의점

  • 테스트 어려움: 전역 인스턴스는 유닛 테스트 시 mocking이 어렵다
  • 의존성 주입(Dependency Injection)과 충돌: DI 패턴과 상충될 수 있음
  • 상태 관리 어려움: 공유 상태가 많아질수록 예측하기 어려운 버그 발생 가능

대안

  • 테스트 가능성을 높이기 위해 의존성 주입을 사용하는 것이 더 유연한 방식일 수 있음
  • 진짜로 “하나만 있어야 하는가?”를 항상 자문할 것

프로젝트 적용 예 (사용자 경험 기반)

내가 개발한 앱 중에서 싱글톤을 적용한 사례는 다음과 같다:

✅ Notion-Mind

  • 문제: 노션 DB 동기화와 캐싱 상태를 앱 전역에서 관리할 필요가 있었음
  • 해결: CacheManager를 싱글톤으로 구현해 데이터 상태 공유 및 중복 요청 방지

✅ Infixel

  • 문제: 로그인 상태, 차단 유저 목록 등 공유 상태 필요
  • 해결: UserSessionManager, BlockListManager를 싱글톤으로 관리

마무리

싱글톤은 강력하지만, 잘못 쓰면 의존성과 전역 상태로 인해 유지보수가 어려워진다. 정말 전역에서 공유해야 하는 상태인가? 테스트 가능성을 포기할 만큼 필요한가? 스스로에게 질문하고 신중하게 사용하는 게 중요하다.

This post is licensed under CC BY 4.0 by the author.