본문 바로가기
Flutter

플러터에서 BLoC 패턴 사용 방법 및 장단점

by Maccrey Coding 2024. 7. 30.
728x90
반응형

 

플러터는 빠른 개발 속도, 풍부한 기능, 아름다운 UI를 제공하며 모바일 앱 개발 분야에서 큰 인기를 얻고 있습니다.

하지만, 복잡한 앱 개발 시에는 코드 구조, 유지 관리, 테스트 등 여러가지 어려움에 직면할 수 있습니다.

이러한 어려움을 해결하고 효율적인 앱 개발을 위해 디자인 패턴을 활용하는 것이 중요합니다.

디자인 패턴은 소프트웨어 개발에서 반복적으로 발생하는 문제를 해결하기 위한 재사용 가능한 솔루션입니다.

플러터에는 MVC, MVP, BLoC 등 다양한 디자인 패턴이 있으며, 각 패턴마다 장점과 단점, 그리고 사용 방법이 존재합니다.

이 블로그에서는 플러터에서 흔히 사용되는 디자인 패턴 중 하나인 BLoC 패턴에 대해 심층적으로 분석하고, 장점과 단점, 그리고 사용 방법을 자세히 설명합니다.

1. BLoC 패턴이란 무엇인가?

BLoC (Business Logic Component) 패턴은 비동기 이벤트 기반 아키텍처를 사용하여 UI와 비즈니스 로직을 분리하는 디자인 패턴입니다.

핵심적으로 다음과 같은 세 가지 요소로 구성됩니다.

  • BLoC (비즈니스 로직 구성 요소): 비즈니스 로직을 담당하는 클래스입니다. 이벤트 스트림을 구독하고, 이벤트에 대한 응답으로 새로운 이벤트를 발행합니다.
  • Event (이벤트): BLoC와 UI 간의 상호 작용을 나타내는 객체입니다. UI에서 발생한 사용자 입력이나 시스템 이벤트를 나타냅니다.
  • State (상태): BLoC의 현재 상태를 나타내는 객체입니다. UI에 표시될 데이터를 포함합니다.

BLoC 패턴은 다음과 같은 특징을 가지고 있습니다.

  • 비동기: BLoC는 비동기 이벤트 기반 아키텍처를 사용하여 UI와 비즈니스 로직을 분리합니다. 이는 UI 스레드를 차단하지 않고 비동기 작업을 수행할 수 있도록 합니다.
  • 단방향 데이터 흐름: BLoC는 UI에서 BLoC로만 데이터가 흐르는 단방향 데이터 흐름을 사용합니다. 이는 코드 결합도를 낮추고 테스트를 용이하게 합니다.
  • 테스트 가능성: BLoC 패턴은 단위 테스트와 위젯 테스트를 통해 쉽게 테스트할 수 있습니다.

2. BLoC 패턴의 장점

BLoC 패턴을 사용하면 다음과 같은 장점을 얻을 수 있습니다.

  • 명확한 역할 분담: UI, BLoC, Event, State 각각의 역할이 명확하게 분리되어 있어 코드를 이해하기 쉽고 유지 관리성이 높아집니다.
  • 단결된 결합: UI와 BLoC이 직접 연결되지 않고 Event/State를 통해 연결되기 때문에 코드 결합도가 낮아 유연성이 높아집니다.
  • 테스트 용이: BLoC, Event, State를 별도로 테스트할 수 있어 코드의 품질을 향상시키는 데 도움이 됩니다.
  • 변경 용이: BLoC만 변경하면 UI에 영향을 미치지 않기 때문에 코드 변경이 용이합니다.
  • 비동기 작업 처리 용이: 비동기 이벤트 기반 아키텍처를 사용하여 비동기 작업을 쉽게 처리할 수 있습니다.

3. BLoC 패턴의 단점

BLoC 패턴을 사용하면 다음과 같은 단점도 존재합니다.

  • 코드 복잡성 증가: MVC 패턴보다 코드가 다소 복잡해질 수 있습니다.
  • 보일러플레이트 코드 증가: BLoC, Event, State 클래스를 만들고 관리해야 하는 보일러플레이트 코드가 증가합니다.
  • 초보자가 이해하기 어려움: 처음에는 BLoC 패턴의 개념을 이해하기 어려울 수 있습니다.

4. 플러터에서 BLoC 패턴 사용 방법

플러터에서 BLoC 패턴을 사용하려면 다음 단계를 따릅니다.

 

1. BLoC, Event, State 클래스를 만듭니다.

  • BLoC 클래스: 비즈니스 로직을 담당하는 클래스입니다.
    • Stream<State> 타입의 속성을 가지고 있어 UI에 상태 변경을 알립니다.
    • Event 타입의 이벤트를 구독하고, 이벤트에 대한 응답으로 새로운 이벤트를 발행합니다.
  • Event 클래스: BLoC와 UI 간의 상호 작용을 나타내는 객체입니다.
    • UI에서 발생한 사용자 입력이나 시스템 이벤트를 나타냅니다.
  • State 클래스: BLoC의 현재 상태를 나타내는 객체입니다.
    • UI에 표시될 데이터를 포함합니다.
// BLoC 클래스
class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterState(count: 0)) {
    on<CounterEvent>(
      (event, emit) {
        if (event is IncrementEvent) {
          emit(state.copyWith(count: state.count + 1));
        } else if (event is DecrementEvent) {
          emit(state.copyWith(count: state.count - 1));
        }
      },
    );
  }
}

// Event 클래스
enum CounterEvent { increment, decrement }

// State 클래스
class CounterState {
  final int count;

  CounterState({required this.count});

  CounterState copyWith({int? count}) {
    return CounterState(count: count ?? this.count);
  }
}
 

2. UI에서 BLoC를 사용합니다.

  • Provider 패키지를 사용하여 BLoC 인스턴스를 UI에 제공합니다.
  • StreamBuilder 위젯을 사용하여 BLoC의 상태 스트림을 구독하고 UI를 업데이트합니다.
  • BlocProvider 위젯을 사용하여 BLoC를 자손 위젯에 제공합니다.
// UI 코드
class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Provider<CounterBloc>(
      create: (context) => CounterBloc(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('BLoC Pattern Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              StreamBuilder<CounterState>(
                stream: context.watch<CounterBloc>().stream,
                initialData: CounterState(count: 0),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Text('Count: ${snapshot.data!.count}');
                  } else {
                    return CircularProgressIndicator();
                  }
                },
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  ElevatedButton(
                    onPressed: () {
                      context.read<CounterBloc>().add(IncrementEvent());
                    },
                    child: Text('Increment'),
                  ),
                  SizedBox(width: 10),
                  ElevatedButton(
                    onPressed: () {
                      context.read<CounterBloc>().add(DecrementEvent());
                    },
                    child: Text('Decrement'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}
 

이 예제는 플러터에서 BLoC 패턴을 사용하는 기본적인 방법을 보여줍니다.

실제 프로젝트에서는 상황에 맞게 코드를 수정해야 할 수 있습니다.

5. BLoC 패턴 활용을 위한 추가 팁

  • Flutter Bloc, Cubit 패키지 활용: BLoC 패턴을 더욱 효율적으로 구현하는 데 도움이 되는 Flutter Bloc, Cubit 패키지를 활용할 수 있습니다.
  • 테스트 코드 작성: 단위 테스트와 위젯 테스트를 작성하여 코드의 품질을 보장합니다.
  • 코드 리팩토링: 코드를 정기적으로 리팩토링하여 코드의 명확성과 유지 관리성을 유지합니다.
  • BLoC 패턴의 변형: 상황에 맞게 BLoC 패턴을 변형하여 사용할 수 있습니다. 예를 들어, 여러 BLoC를 하나의 State Management 클래스로 결합하거나, BLoC 대신 Redux와 같은 다른 State Management 라이브러리를 사용할 수 있습니다.

6. BLoC 패턴 대안

플러터에는 BLoC 패턴 외에도 다양한 아키텍처 패턴이 존재합니다.

프로젝트의 특성에 맞는 적절한 패턴을 선택하는 것이 중요합니다.

  • MVC (Model-View-Controller): View, Model, Controller를 분리하여 코드를 구성하는 패턴입니다. BLoC 패턴보다 간단하지만, View와 Model이 직접 연결되기 때문에 코드 결합도가 높아질 수 있습니다.
  • MVVM (Model-View-ViewModel): ViewModel이 View와 Model 사이의 중개 역할을 수행하는 패턴입니다. BLoC 패턴과 유사하지만, ViewModel 클래스가 추가적으로 필요하기 때문에 코드가 다소 복잡해질 수 있습니다.
  • Redux: 단방향 데이터 흐름과 몰입형 상태 관리를 기반으로 하는 State Management 라이브러리입니다. BLoC 패턴보다 복잡하지만, 대규모 프로젝트에서 효과적으로 사용할 수 있습니다.

7. 결론

플러터에서 BLoC 패턴은 코드를 명확하고 테스트하기 쉽게 만들고, 유지 관리성을 향상시키는 데 도움이 되는 강력한 도구입니다.

하지만, 모든 프로젝트에 적합한 것은 아니므로, 프로젝트의 특성을 고려하여 신중하게 선택해야 합니다.

 

BLoC 패턴을 사용해야 하는 경우

  • 코드의 명확성과 유지 관리성이 중요한 대규모 프로젝트를 개발하는 경우
  • 단위 테스트와 위젯 테스트를 통해 코드를 철저하게 테스트해야 하는 경우
  • 비동기 작업을 처리해야 하는 경우

BLoC 패턴을 사용하지 않아도 되는 경우

  • 간단하고 빠르게 개발해야 하는 소규모 프로젝트를 개발하는 경우
  • 테스트가 중요하지 않은 프로젝트를 개발하는 경우
  • 코드의 복잡성을 줄이고 싶은 경우

BLoC 패턴은 다양한 장점을 가지고 있지만, 단점도 존재합니다.

따라서, 프로젝트의 특성을 면밀히 분석하고 장단점을 비교하여 BLoC 패턴을 사용할지 결정해야 합니다.

 

Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.

 

Tester Share [테스터쉐어] - Google Play 앱

Tester Share로 Google Play 앱 등록을 단순화하세요.

play.google.com

 

728x90
반응형