본문 바로가기

✏️/Flutter

[flutter] BLoC 🎲 pattern intro

728x90

플러터로 앱 개발하면서 자주 사용하고 있는 패턴인 BLoC에 대해서 오늘은 간단하게 정리 겸 ~~~ 해서 글을 써보겠다.

 

 

Bloc State Management Library

Official documentation for the bloc state management library. Support for Dart, Flutter, and AngularDart. Includes examples and tutorials.

bloclibrary.dev

(개인적으로 로고가 너무 맘에 든다..)

 

BLoC pattern

 

BLoC 공홈을 보면 다음과 같이 설명이 되어 있다.

Bloc makes it easy to separate presentation from business logic, making your code fast, easy to test, and reusable.


대충 해석해보면, 비즈니스 로직과 분리를 통해 쉽고 빠르게 개발할 수 있다는 내용인데..
뭐 문장으로서는 이해가 되지만 안 와닿는다... 그러므로 하나씩 뜯어보자 ㄱㄱ!!

1. Presentation 
사용자 입력 및 어플리케이션 수명주기 이벤트를 처리하고, 하나 이상의 블록 상태를 기반으로해서 렌더링

class PresentationComponent {
    final Bloc bloc;

    PresentationComponent() {
        bloc.add(AppStarted());
    }

    build() {
        // render UI based on bloc state
    }
}

build() 함수 내에서 BLoC의 state 기반으로 이벤트를 처리하고, UI를 보여준다.
State - BLoC 사이간 통신의 경우 BLoC 내 라이브러리 클래스를 통해 쉽게 접근해서 사용 할 수 있다. (e.x. BlocBuilder, BlocProvider.. )

 

2. Business Login
간단하게 이야기 하면, 사용자인터페이스(Presentation 레이어)와 데이터 레이어 사이의 다리
Presentation의 이벤트 작업에 대한 알림을 받고 다음 사용할 Presentation 레이어에 대해 새 상태를 구축하고 저장소와 통신
>> BloC to BloC 또는 Cubit to Cubit 등 통신하는 부분이 이에 해당

class MyBloc extends Bloc {
  final OtherBloc otherBloc;
  StreamSubscription otherBlocSubscription;

  MyBloc(this.otherBloc) {
    otherBlocSubscription = otherBloc.listen((state) {
        // React to state changes here.
        // Add events here to trigger changes in MyBloc.
    });
  }

  @override
  Future<void> close() {
    otherBlocSubscription.cancel();
    return super.close();
  }
}

 

3. Data
데이터베이스, 네트워크 요청 및 기타 비동기 데이터 소스와 상호작용 하는 곳

- Repository : 여러 데이터 공급자와 상호 작용하고 결과로 비즈니스 로직에게 전달하기 전 데이터에 대한 변환을 수행

class Repository {
    final DataProviderA dataProviderA;
    final DataProviderB dataProviderB;

    Future<Data> getAllDataThatMeetsRequirements() async {
        final RawDataA dataSetA = await dataProviderA.readData();
        final RawDataB dataSetB = await dataProviderB.readData();

        final Data filteredData = _filterData(dataSetA, dataSetB);
        return filteredData;
    }
}

- Data Provider : 일반적으로 CRUD 작업을 수행하기 위해 API 호출

class DataProvider {
    Future<RawData> readData() async {
        // Read from DB or make network request etc...
    }
}

 

전체적인 구조를 살펴보았다! 약간 네이티브 단에서 이야기하는 MVVM 패턴과 유사해보이기도 하다..!

다음 글은 이 패턴을 기준으로 해서 어떻게 사용하는지, 그리고 꼭 알아야할 것은 무엇인지에 대해서 한번 글을 작성해보겠다.