1. Rollbar가 해결하는 문제점
Rollbar-flutter는 순수 Dart로 구현되어 있어 코드 재사용성이라는 큰 장점을 제공합니다. Flutter SDK가 네이티브 SDK에 의존하는 Bugsnag와 달리, Rollbar는 Dart 레이어에서 네트워크 통신, 데이터 저장, 예외 처리 로직을 모두 처리합니다. 이는 Android, iOS 등 각 플랫폼마다 중복된 네트워크 및 저장소 로직을 별도로 구현할 필요가 없음을 의미합니다. 결과적으로 개발 및 테스트 비용을 절감할 수 있습니다.
Rollbar는 예외 데이터를 가공하는 방식을 추상화하여 개발자에게 높은 자유도를 제공합니다. 예외를 마치 생선처럼 생각하면, Catcher는 담백하게 찌고 Bugsnag는 진하게 조리는 반면, Rollbar는 사용자가 직접 조리법을 선택할 수 있도록 기본 재료(원시 예외 데이터)를 제공합니다.
또한, 예외 처리 과정에서 발생하는 I/O 작업(데이터 직렬화, 저장, 암호화, 전송)은 메인 isolate의 UI 렌더링 성능에 영향을 줄 수 있습니다. Rollbar는 이러한 무거운 작업을 별도의 하위 isolate(crash isolate)에서 처리하도록 지원하여 애플리케이션의 반응성을 유지합니다.
마지막으로, Bugsnag와 유사하게 사용자 행동 경로(Breadcrumb)를 기록하여 문제 발생 지점까지의 컨텍스트를 추적할 수 있습니다. 다만, Bugsnag가 자동 및 수동 경로 생성을 모두 지원하는 반면, Rollbar는 수동 추가만 지원하지만 Breadcrumb 유형(error, navigation, widget, log)을 세분화하여 이벤트 성격에 맞게 구분할 수 있습니다.
2. 설치 및 기본 설정
pubspec.yaml에 의존성을 추가합니다:
dependencies:
rollbar_flutter: ^0.3.0-beta
flutter pub get 명령을 실행한 후, 다음과 같이 초기화합니다:
import 'package:rollbar_flutter/rollbar.dart';
Future<void> main() async {
const config = Config(
accessToken: 'YOUR-ROLLBAR-ACCESSTOKEN', // Rollbar 계정에서 발급
package: 'rollbar_flutter_example');
await RollbarFlutter.run(config, () {
runApp(const MyApp());
});
}
요구 사항
- Dart SDK >= 2.7.0
- Flutter >= 1.20.0
- Rollbar 계정
3. 아키텍처 분석
RollbarFlutter.run() 메서드를 통해 진입점을 분석합니다. Config 객체는 네 가지 핵심 구성 요소를 정의합니다:
- Notifier: 예외 이벤트를 메인 스레드 또는 하위 스레드에서 처리할지 결정합니다.
- Transformer: 원시 예외 데이터(
Event)를 변환(Data)하는 역할을 합니다. - Wrangler: 변환된 데이터를 최종 전송 형식(
Payload)으로 한 번 더 가공합니다. - Sender:
Wrangler가 생성한Payload를 실제로 Rollbar 서버로 전송합니다.
FlutterError.onError와 runZonedGuarded를 통해 예외를 수집한 후, Rollbar.error() 메서드가 호출됩니다. 이 메서드는 예외를 Event 객체로 감싸 Notifier.notify()에 전달합니다. 기본 설정에서는 IsolatedNotifier가 사용되므로, 이 Event는 자동으로 하위 isolate로 전달되어 처리됩니다.
하위 isolate 내부에서는 다음과 같은 순서로 작업이 진행됩니다:
- 데이터베이스 정리:
Telemetry객체를 통해 캐시된 Breadcrumb와 오래된 Event를 정리합니다. - 데이터 변환 및 래핑:
Transformer와Wrangler를 통해 Event → Data → Payload 순서로 가공됩니다. - 전송:
Sender가 최종 Payload를 HTTP 요청으로 전송합니다.
4. 예외 데이터 가공 과정
예외 데이터 가공은 세 단계로 이루어집니다:
- Event → Data 변환: 원시 예외(
Error+StackTrace)에 OS 정보, Dart 버전, 패키지명, 환경 정보 등 부가 데이터를 추가합니다. - 개발자 정의 변환:
Transformer.transform()메서드를 오버라이드하여 데이터 암호화, 필드 추가/삭제 등 커스텀 로직을 수행할 수 있습니다. - Payload 생성:
Wrangler가 최종 전송 가능한 형식으로 데이터를 래핑합니다.
기본 Transformer는 NoopTransformer로, 아무런 변환 없이 입력 데이터를 그대로 반환합니다. 필요에 따라 transform 메서드를 재정의하여 사용자 정의 변환기를 구현할 수 있습니다.
5. 스레드 전환 메커니즘
스레드 전환은 Notifier 추상 클래스를 통해 제어됩니다:
abstract class Notifier {
static const version = '0.4.0-beta';
static const name = 'rollbar-dart';
Sender get sender;
Wrangler get wrangler;
Telemetry get telemetry;
FutureOr<void> notify(Event event);
FutureOr<void> dispose();
}
기본값인 IsolatedNotifier는 Isolate.spawn()을 통해 새로운 하위 isolate를 생성하며, AsyncNotifier는 메인 isolate에서 동기적으로 처리합니다. 하위 isolate에서 처리할 경우 얻는 이점은 다음과 같습니다:
- 데이터베이스 작업 분리: Telemetry의 읽기/쓰기/삭제 작업이 UI 스레드를 차단하지 않습니다.
- 데이터 변환 부담 경감: 복잡한 Transformer 로직이나 Wrangler의 직렬화 과정이 UI에 영향을 주지 않습니다.
- 전송 안정성 향상: 예외가 대량으로 발생할 때, 전송 과정의 네트워크 지연이 앱 성능에 미치는 영향을 최소화합니다.
6. 설계 패턴 분석
단일 책임 원칙 (Single Responsibility Principle)
Notifier: 실행 컨텍스트(스레드) 관리Transformer: 데이터 변환Wrangler: 최종 포맷 래핑Sender: 데이터 전송 (HTTP, 파일 등)Telemetry: 로컬 데이터베이스 관리
플러그 가능한 설계 (Pluggable Architecture)
각 모듈은 생성자 주입 방식으로 결합되며, Config 객체에서 기본 구현체를 제공하거나 사용자 정의 구현체로 교체할 수 있습니다:
const Config({
this.notifier = IsolatedNotifier.spawn,
this.wrangler = DataWrangler.new,
this.transformer = NoopTransformer.new,
this.sender = PersistentHttpSender.new,
});
이는 개방-폐쇄 원칙(Open-Closed Principle)을 잘 따르며, 핵심 로직을 수정하지 않고도 확장이 가능합니다.
7. 추가 고려 사항
- 데이터 직렬화 및 로컬 저장소 관리 로직은
Telemetry클래스에서 자세히 다루고 있으므로, 필요시 참고하세요. - Android의
PlatformException과 같이 다중 StackTrace를 포함하는 예외 처리 방식이 구현되어 있습니다. - Dart 2.15의 생성자 분리(Constructors tear-off) 기능을 활용하여 코드를 간결하게 구성하고 있습니다.
8. 알려진 이슈
- Rollbar-flutter는 아직 베타 버전이므로, Flutter 프로젝트 생성 시 Rollbar 아이콘이 선택 목록에 없을 수 있습니다. 이 경우 아이콘 선택 없이 진행하고, example 프로젝트에서 직접 AccessToken을 설정하여 테스트할 수 있습니다.
- AccessToken이 잘못된 상태에서 전송 실패한 데이터가 로컬에 캐시되면, 이후 올바른 Token으로 수정해도 전송되지 않을 수 있습니다. 이때는 앱 데이터를 삭제하거나 재설치하여 캐시를 초기화해야 합니다.
9. 장점과 단점
장점
- 하위 isolate를 활용한 비동기 예외 처리로 UI 성능 보장
- Dart 레이어에서 데이터베이스 캐싱 및 큐 관리 지원
- 다중 StackTrace 예외 처리 (Android PlatformException 등)
- 명확한 모듈 분리와 Config 기반의 확장성
- 사용자 행동 경로(Breadcrumb) 수동 기록 기능
단점
- Breadcrumb 자동 수집(네비게이션, 네트워크 요청 등)은 지원되지 않아 수동 구현이 필요하며, 이는 Bugsnag 대비 불편함
- 내부 저장소로 sqlite3를 사용하는데, 이는 네이티브 채널을 통한 구현이므로 완전한 순수 Dart 구현이 아님. Hive 같은 순수 Dart 솔루션으로 대체 가능성 검토 필요