싱글톤 패턴
싱글톤 패턴
싱글톤 패턴(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.