Flutter 앱에서 push, pop 등으로 페이지 전달하는 코드 없이 Tab 등으로 위치 다른 페이지가 있을 때, 한 페이지에서 일어난 변화를 다른 페이지가 어떻게 알 수 있을까요?
좌측
우측
전역적으로 처리 등 다양한 방법이 있겠지만 그 중에서도 EventBus를 이용하면 이런 문제를 훨씬 간단하게 해결할 수 있습니다.
오늘은 Flutter에서 EventBus를 활용해 결합성을 낮추고 페이지 간 소통을 쉽게 만드는 방법을 알아보겠습니다.
먼저, EventBus가 무엇인지 짚고 넘어가죠.
간단하게 말해 EventBus는 애플리케이션 내의 다양한 컴포넌트들이 이벤트를 통해 서로 통신할 수 있게 해주는 도구입니다. 이는 특히 서로 직접적인 참조가 없는 컴포넌트 간의 결합성을 낮출 때 유용합니다.
자, 이제 예제 코드와 함께 EventBus의 구현을 살펴봅시다.
event_bus.dart
import 'dart:async';
class EventBus {
static final EventBus _instance = EventBus._internal();
factory EventBus() => _instance;
EventBus._internal();
final _eventController = StreamController<dynamic>.broadcast();
Stream<T> on<T>() =>
_eventController.stream.where((event) => event is T).cast<T>();
void fire(event) => _eventController.add(event);
void dispose() => _eventController.close();
}
위 코드는 EventBus의 기본적인 구조를 보여줍니다. 각 부분을 하나씩 설명해볼게요:
싱글톤 패턴: EventBus 클래스는 싱글톤 패턴으로 구현되었습니다. 이는 어플리케이션 전역에서 하나의 인스턴스만 사용되도록 보장합니다.
StreamController: _eventController
는 이벤트를 관리하기 위해 사용됩니다. .broadcast()
를 사용해 여러 리스너가 동일한 스트림을 구독할 수 있게 합니다.
on() 메서드: 특정 타입의 이벤트를 필터링해서 스트림으로 반환합니다. 이를 통해 특정 이벤트 타입만을 구독할 수 있습니다.
fire(event) 메서드: 새로운 이벤트를 스트림에 추가합니다.
dispose() 메서드: 더 이상 EventBus가 필요 없을 때 스트림을 닫습니다.
이제 EventBus에서 사용할 이벤트 모델을 정의해봅시다. 여기서는 블로그가 생성되는 이벤트를 예제로 들어 설명하겠습니다.
events.dart
class BlogCreatedEvent {
final String blogId;
BlogCreatedEvent(this.blogId);
}
간단하죠? BlogCreatedEvent
클래스는 블로그 생성 시 이벤트를 트리거하기 위한 모델을 정의합니다.
파일 구조는 아래와 같이 참고하세요 !
project_lib/ ├── core/ │ ├── event_bus/ │ │ ├── event_bus.dart │ │ └── events.dart │ └── utils/ │ └── ... ├── data/ │ └── ... └── presentation/ └── ...
EventBus와 이벤트 모델이 준비되었으니, 실제로 이를 어떻게 활용하는지 살펴봅시다.
import 'event_bus.dart';
import 'events.dart';
void createBlog() {
try {
// 블로그 생성 로직
} catch (e) {
// 에러 처리
} finally {
EventBus().fire(BlogCreatedEvent(blogId));
}
}
블로그가 성공적으로 생성되었을 때 EventBus().fire(BlogCreatedEvent(blogId));
를 호출하여 이벤트를 발생시킵니다.
import 'event_bus.dart';
import 'events.dart';
class BlogListViewModel with ChangeNotifier {
BlogListViewModel() {
EventBus().on<BlogCreatedEvent>().listen(_onBlogCreated);
}
void _onBlogCreated(BlogCreatedEvent event) {
// 목록 새로고침 로직
fetchBlogs(isForce: true);
}
void dispose() {
EventBus().dispose();
super.dispose();
}
}
여기서는 EventBus().on<BlogCreatedEvent>().listen(_onBlogCreated);
를 통해 특정 이벤트 타입을 구독하고, 이벤트 발생 시 블로그 목록을 새로고침합니다.
마지막으로, 메모리 누수를 방지하기 위해 dispose()
메서드 내에서 EventBus의 dispose()
를 호출해 스트림을 닫습니다.
EventBus를 이용한 이 패턴의 장점은 페이지 간 결합성을 낮추면서도 서로의 상태 변화를 쉽게 감지하고 반응할 수 있다는 점입니다. Flutter 프로젝트에서 여러 페이지가 상호작용해야 하지만 서로 직접적으로 접근하지 않기를 원할 때, EventBus는 탁월한 해결책이 될 수 있습니다.
이제 여러분도 EventBus를 활용해 더 확장성 높고 유지보수하기 쉬운 Flutter 애플리케이션을 만들어보세요! 🍀
🔥 해당 포스팅은 Dev.POST 도움을 받아 작성되었습니다.