Singleton Design Parttern
🤔 Flutter에서 정말 Thread Safety가 필요할까?
많은 개발자들이 "Flutter는 Single Thread 아닌가?"라고 생각하지만, 실제로는 여러 상황에서 동시성 문제가 발생할 수 있습니다.
📍 동시성 문제가 발생하는 실제 상황들
1. async/await를 사용한 비동기 초기화
가장 흔한 상황입니다. 데이터베이스나 API 클라이언트를 초기화할 때:
dart
class ApiClient {
static ApiClient? _instance;
static Future<ApiClient> getInstance() async {
if (_instance == null) {
// 네트워크 호출이나 파일 I/O 등 시간이 걸리는 작업
await Future.delayed(Duration(seconds: 1));
_instance = ApiClient._internal();
}
return _instance!;
}
}
// 문제 상황: 앱 시작 시 여러 화면에서 동시 호출
void main() async {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
UserProfile(), // ApiClient.getInstance() 호출
PostList(), // ApiClient.getInstance() 호출 (동시에!)
CommentList(), // ApiClient.getInstance() 호출 (동시에!)
],
),
),
);
}
}결과: 3개의 서로 다른 ApiClient 인스턴스가 생성될 수 있음!
2. Isolate를 사용하는 경우
dart
3. 앱 라이프사이클 이벤트 처리
dart
⚡ 실제 테스트로 문제 확인하기
dart
🎯 상황별 해결책
1. Completer를 사용한 해결 (권장)
dart
2. 동기적 생성 + 비동기 초기화 (심플)
dart
3. GetIt 패키지 사용 (최고 권장)
yaml
dart
4. Provider와 함께 사용
dart
📊 성능 비교와 권장사항
🎯 결론 및 Best Practice
✅ 권장사항
간단한 싱글톤: 동기적 생성 + 별도 초기화 메서드
복잡한 의존성: GetIt 패키지 사용
앱 시작 시: 모든 싱글톤을 미리 초기화
테스트: 항상 동시성 테스트 코드 작성
❌ 피해야 할 것
async/await 없이 비동기 싱글톤 구현
앱 실행 중 동적 싱글톤 생성
Isolate간 싱글톤 공유 시도
💡 핵심 포인트
Flutter는 Single Thread이지만, async/await와 Future를 사용하면 동시성 문제가 발생할 수 있습니다. 특히 앱 시작 시 여러 위젯에서 동시에 싱글톤을 요청할 때 Race Condition이 발생하기 쉽습니다.
Last updated