BLoC for Flutter 왜 이렇게 만들지?

#1. BLoC의 구조 및 전파

Business Logic Component 를 사용한다는 것은 무엇인가

Business Logic 을 표현하고 정리하는 수단이 어떻게 되는지,
구조적인 결론을 가지고 있어야 정리가 된다.

기본적인 BLoC 사용법은 DOM 배치 자체로부터 시작한다.

1. BLoC Render pipe

다이어그램으로 관계 파이프를 그려본다.

1111111

graph TB; BLoCClass[BLoC]; subgraph BLoCProvider[BLoC Provider]; end; BLoCBuilder[“BLoC Builder(Renderer)”]; BLoCProvider –>|소유| BLoCBuilder; BLoCProvider –>|소유| button; DOMOwn(DOM 소유관계);


graph TB;
BLoCClass[BLoC];
subgraph BLoCProvider[BLoC Provider];
end;
BLoCBuilder[“BLoC Builder(Renderer)”];
BLoCProvider –>|소유| BLoCBuilder;
BLoCProvider –>|소유| button;
DOMOwn(DOM 소유관계);

222222

sequenceDiagram Alice->>John: Hello John, how are you? John–>>Alice: Great! Alice-)John: See you later!

333333333

graph TB;   BLoCClass[BLoC];   subgraph BLoCProvider[BLoC Provider];   end;   BLoCBuilder[“BLoC Builder(Renderer)”];   BLoCProvider –>|소유| BLoCBuilder;   BLoCProvider –>|소유| button;   DOMOwn(DOM 소유관계);

2. BLoC event propagation

BLoC 를 이용해서 provider 휘하의 builder 에 이벤트를 전파한다.

graph TB subgraph BLoCProvider[BLoC Provider] BLoCBuilder[“BLoC Builder(Renderer)”] end BLoCclass[BLoC] button -.->|emit| BLoCclass -.->|re-render| BLoCBuilder triggerEvent(Event 전파 관계)

3. BLoC event propagation 특성

BLoC 의 이벤트 전파의 특성에 따라 구조선정이 좌지우지된다

기본적인 BLoC를 사용했을 때, 이벤트가 연속적으로 겹쳐져서 발생할 때, 두번째 이벤트가 큐잉되지 않고 드롭되는 현상이 있었다.
랜더링이라는 interrupt 가 연속적으로 빠르게 호출되는 것이 바람직하지 않을 순 있다.
큐잉까지 해가면서 빠르게 그릴 이유가 없어보이긴 하지만,
프레임레이트가 좋아지거나 여러가지 발전이 있을 법도 한데
그렇게 처리하지 않는 이유는
native code와 연동해야 랜더링 성능에 개입할 듯 하고,
그렇게 하면서 dart로 module을 만들면,
복잡한 것에 비해 개발비용이 비싸기 때문으로 보인다. 효율도 별로 안나올 듯.
추측해봤다.

4. 이벤트 전파를 위한 구조

event를 겹쳐진다고 표현할 정도로 연속적으로 발생시킬 수 있는 경우를 배제하고 설계해야 한다.
전통적인 dataflow 방식보다는 context를 분리하고 context간의 연결을 BLoC으로 연결해야 한다.

클린아키텍쳐에서 다루는 use case 로 상징되는 context 와 BLoC은 다른 개념으로 봐야한다.

이름만 들어보면 Business logic에 대한 온전한 표현으로 보이거나 느껴져야 하는데 실제 BLoC는 그것과는 거리가 멀다
다음글 프론트앤드 설계 포스트 – 참조 링크

#2. 코드 snippet

BLoC 자체를 provider와 같이 사용하고, Provider를 scope 하기 위해서 Context tree 에 provider root를 작성하여 기입한다.


class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {

    return MultiBlocProvider(
      providers: [
        BlocProvider<EntityCubit>(
          create: (BuildContext context) => EntityCubit(Period.year1),
        ),
      ],
      child: materialWidget,
    );
  }
}