-
flutter - Bloc, Cubit, Stream개발 2022. 10. 6. 21:40
Bloc
표현층과 비즈니스로직을 분리하고 코드를 빠르고 재사용 가능하게 짤 수 있는 플러터 아키텍처다. Bloc을 이해하려면 먼저 Stream에 대한 개념을 짚고 넘어가야한다.
Stream
비동기적인 데이터들의 연속을 말한다. 파이프 안에 흐르는 물로 비유할 수 있는데 흐르는 물이 비동기적 데이터고 그 물을 둘러싸는 파이프가 Stream이라고 볼 수 있다. Dart의 코드로 표현하면 다음과 같다.
Stream<int> countStream(int max) async* { for (int i = 0; i < max; i++) { yield i; } }
Stream을 소비(Consume) 하는 코드도 만들 수 있다. 비동기로 값을 리턴하기 위해 async 를 붙이고 Future로 리턴한다.
Future<int> sumStream(Stream<int> stream) async { int sum = 0; await for (int value in stream) { sum += value; } return sum; }
Cubit
Cubit은 BlocBase의 클래스중 하나로 상태를 관리하고 변경된 정보를 UI에 전달하는 역할을 한다. Cubit은 함수를 통해서 상태의 변화를 노출한다.
class CounterCubit extends Cubit<int> { CounterCubit() : super(0); void increment() { addError(Exception('increment error!'), StackTrace.current); emit(state + 1); } @override void onChange(Change<int> change) { super.onChange(change); print(change); } }
Cubit 내에서 관리하는 데이터 타입은 int 뿐만 아니라 다양한 형태의 클래스가 될 수도 있다. 오버라이드 함수 onChange를 통해서 cubit의 변화를 감지할 수 있다. emit 함수를 통해 상태 변화를 업데이트한다.
Bloc
Bloc은 상태 변화를 함수가 아니라 이벤트에 의존한다. Cubit과 비슷한 역할을 하지만 함수가 아니라 이벤트에 의존한다는 측면에서 차이가 있다. 사진을 보면 UI 에서 전달하는 텍스트가 function에서 event로 바뀐 것을 확인 할 수 있다. 이외에도 추가 기능이 더 있어 Cubit의 발전된 형태라고 볼 수 있다.
abstract class CounterEvent {} class CounterIncrementPressed extends CounterEvent {} class CounterBloc extends Bloc<CounterEvent, int> { CounterBloc() : super(0) { on<CounterIncrementPressed>((event, emit) => emit(state + 1)); } @override void onChange(Change<int> change) { super.onChange(change); print(change); } @override void onTransition(Transition<CounterEvent, int> transition) { super.onTransition(transition); print(transition); } }
Bloc은 함수 단위가 아니라 이벤트 단위기 때문에 변화가 생길 때마다 이벤트가 동반된다. 이건 onTrasition 콜백으로 확인 할 수 있다
CounterCubit, CounterBloc이 UI 단과 어떻게 상호작용하는지 확인하려면 아래 예제 페이지를 확인해보면 좋다.
Cubit vs Bloc
Cubit은 간단함이 장점이다. 코드양이 적고 스테이트를 지정하고 노출할 함수만 띄워주면 되기 때문에 개발하기 편하다. 반대로 Bloc은 이벤트를 관리하는 함수도 만들어야해 boilerplate 코드가 많다.
Bloc은 추적할 수 있다는 장점이 있다. 상태 변화에 따라서 어떤 이벤트가 영향을 미쳤는지 기록 할 수 있다. 그리고 비즈니스 로직을 추상화 할 수 있는 장점도 있다. UI 단에서는 비즈니스 로직에 구체적으로 어떤 함수가 있었는지 알지 않아도 되기 때문에 분리가 가능하다. 추가로 Bloc을 사용하면 buffer, debounceTime, throttle 같은 반응형 오퍼레이터를 추가로 사용할 수 있는 장점이 있다. 검색같은 기능을 넣을 때 이런게 있으면 유용하긴하다.
'개발' 카테고리의 다른 글
typeorm - definition, entity (0) 2022.11.29 flutter - BlocWidget (0) 2022.10.06 typescript interface/type (0) 2022.09.07 REST, REST API, RESTful (0) 2022.09.02 nextjs 스크롤 저장 기억하기 (0) 2022.08.09