Flutter에서 상태 관리는 항상 고민되는 부분입니다. 여러 가지 방법이 있지만, 규모가 커질수록 명확한 구조가 필요한데, 그중 하나가 BLoC(Business Logic Component) 패턴입니다. 이번 글에서는 BLoC 패턴이 무엇인지, 왜 사용하는지, 그리고 실제 코드 예제를 통해 적용하는 방법을 정리해보겠습니다.
BLoC 패턴이란?
BLoC 패턴은 비즈니스 로직과 UI를 분리하는 아키텍처 패턴입니다. 즉, UI와 상태 관리 로직을 독립적으로 유지하여 유지보수성과 테스트 가능성을 높이는 방식입니다.
BLoC 패턴을 사용하는 이유
- UI와 로직 분리 → UI 코드와 비즈니스 로직을 명확히 구분하여 가독성을 높입니다.
- 일관된 상태 관리 → 이벤트와 상태를 사용해 관리할 수 있어 예측 가능한 코드 작성이 가능합니다.
- 테스트가 용이 → UI와 로직을 분리했기 때문에 비즈니스 로직을 별도로 테스트하기 쉽습니다.
BLoC 패턴을 사용하면 데이터 흐름을 이벤트(Event) → BLoC → 상태(State) 형태로 관리할 수 있습니다.
BLoC 패턴의 주요 개념
BLoC 패턴은 크게 이벤트(Event), 상태(State), 그리고 BLoC 세 가지 요소로 구성됩니다.
1. 이벤트 (Event)
사용자의 입력이나 특정 동작을 의미합니다. 예를 들어, 버튼을 클릭하면 IncrementEvent가 발생하는 것처럼 동작을 정의할 수 있습니다.
2. 상태 (State)
BLoc이 처리한 결과를 UI에 전달하는 데이터입니다. 예를 들어, count 값을 저장하는 CounterState 같은 형태로 사용됩니다.
3. BLoC (Business Logic Component)
이벤트를 받아서 상태를 변경하는 핵심 역할을 합니다. 이벤트를 감지하고 로직을 처리한 후 새로운 상태를 UI로 전달합니다.
BLoC 패턴 적용하기 (예제)
간단한 카운터 앱을 만들어 BLoC 패턴을 어떻게 적용하는지 알아보겠습니다.
1. 이벤트 정의하기
import 'package:equatable/equatable.dart';
abstract class CounterEvent extends Equatable {
const CounterEvent();
}
class IncrementEvent extends CounterEvent {
@override
List<Object> get props => [];
}
class DecrementEvent extends CounterEvent {
@override
List<Object> get props => [];
}
이벤트는 Equatable을 상속받아 객체 비교가 가능하도록 만듭니다.
2. 상태(State) 정의하기
import 'package:equatable/equatable.dart';
abstract class CounterState extends Equatable {
const CounterState();
}
class CounterValue extends CounterState {
final int count;
const CounterValue(this.count);
@override
List<Object> get props => [count];
}
현재 카운트 값을 관리하는 CounterState를 정의했습니다.
3. BLoC 구현하기
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterValue(0));
@override
Stream<CounterState> mapEventToState(CounterEvent event) async* {
if (event is IncrementEvent) {
yield CounterValue((state as CounterValue).count + 1);
} else if (event is DecrementEvent) {
yield CounterValue((state as CounterValue).count - 1);
}
}
}
이제 BLoC에서 이벤트를 감지하고 상태를 변경하는 역할을 합니다.
4. UI에 BLoC 연결하기
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider(
create: (_) => CounterBloc(),
child: CounterScreen(),
),
);
}
}
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('BLoC Counter')),
body: Center(
child: BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
if (state is CounterValue) {
return Text('Count: ${state.count}', style: TextStyle(fontSize: 24));
}
return CircularProgressIndicator();
},
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
child: Icon(Icons.add),
),
SizedBox(height: 8),
FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
child: Icon(Icons.remove),
),
],
),
);
}
}
BLoCProvider로 CounterBloc을 주입하고, BlocBuilder를 사용하여 상태 변화를 감지하여 UI를 업데이트합니다.
BLoC 패턴을 활용한 상태 관리의 장점
- 비즈니스 로직과 UI 분리 → 유지보수가 쉬워집니다.
- 상태 흐름이 명확 → 이벤트 → BLoC → 상태의 흐름이 직관적입니다.
- 테스트 가능 → UI 없이 로직을 테스트할 수 있습니다.
마무리
Flutter에서 상태 관리는 중요한 요소이며, 프로젝트가 커질수록 체계적인 상태 관리가 필요합니다. BLoC 패턴은 UI와 로직을 명확히 분리하고, 이벤트 기반의 상태 관리를 제공하여 유지보수성과 확장성을 높이는 강력한 방법입니다.
오늘도 그럼 즐코 빡코 !
'Flutter' 카테고리의 다른 글
Flutter Secure Storage (2) | 2025.03.04 |
---|---|
Flutter에서 애니메이션 (1) | 2025.03.02 |
Flutter 3.29 & Dart 3.7 업데이트 (1) | 2025.02.27 |
PopupMenuButton (팝업 메뉴 버튼) (0) | 2025.02.27 |
Flutter의 렌더링 파이프라인: Build 단계 이해하기 (0) | 2025.02.25 |