본문 바로가기

Personal Posting/Flutter

Flutter 기반 함수형 에러핸들링

에러핸들링 - DALL·E 2025-01-03 23.21.17 생성형 AI 이미지

 

Flutter에서의 함수형 에러 처리
Dart 언어는 에러를 처리하기 위해 try, catch, 그리고 throw와 같은 기본적인 메커니즘을 제공한다. 하지만 함수형 프로그래밍(FP)을 활용하면 더 명확하고 안전한 방식으로 에러를 처리할 수 있다. 이 글에서는 Flutter에서 fpdart 패키지의 Either 타입을 활용한 함수형 에러 처리 방법을 소개한다.

 

함수형 프로그래밍이란?
함수형 프로그래밍(FP)은 다음과 같은 특징을 지닌 프로그래밍 패러다임이다.

  • 순수 함수: 동일한 입력에 대해 항상 동일한 출력을 반환하며, 외부 상태를 변경하지 않음
  • 불변성: 데이터가 변경되지 않으며, 새로운 데이터는 기존 데이터를 복사하여 생성
  • 선언적 스타일: "무엇을" 해야 하는지에 집중하며, "어떻게" 해야 하는지는 추상화

이는 객체지향 프로그래밍(OOP)과 대비된다. OOP는 상태 변화와 명령형 스타일을 기반으로 객체의 데이터와 동작을 정의한다.

Dart와 같은 현대 언어는 FP와 OOP를 모두 지원하므로, 필요에 따라 두 가지 스타일을 혼합하여 사용할 수 있다.

 

예제: 런타임 에러 처리

예를 들어, String 타입의 숫자 값을 double로 변환하려면 다음과 같이 작성할 수 있다.

final value = double.parse('155.50');

 

여기서 만약 숫자가 아닌 값을 입력하면 런타임에서 예외가 발생한다.

final value = double.parse('not-a-number'); // FormatException 발생

 

공식문서에 따르면, double.parse 함수의 시그니처는 아래와 같다.

static double parse(String source);

 

이를 처리하기 위해 try/catch 블록을 사용할 수 있다.

try {
  final value = double.parse('not-a-number');
  // 성공 처리
} on FormatException catch (e) {
  // 에러 처리
  print(e);
}

 

하지만 대규모 코드베이스에서는 어떤 함수가 예외를 던질 수 있는지 파악하기 어려울 수 있다. 이상적으로는 함수 시그니처에서 에러 가능성을 명시적으로 나타내야 한다.

 

Either 타입
fpdart 패키지의 Either 타입은 함수 시그니처에서 성공과 실패를 명시적으로 표현할 수 있도록 도와준다.

import 'package:fpdart/fpdart.dart';

Either<FormatException, double> parseNumber(String value) {
  try {
    return Either.right(double.parse(value)); // 성공 시 반환
  } on FormatException catch (e) {
    return Either.left(e); // 실패 시 반환
  }
}
  • Either.left : 에러를 나타냄
  • Either.right : 성공 값을 나타냄

위 코드에서 Either<FormatException, double>은 이 함수가 FormatException 또는 double 값을 반환할 수 있음을 명확히 보여준다.

 

Result 타입과의 비교

Eithermultiple_result 패키지의 Result 타입과 유사하다.

Result<FormatException, double> parseNumber(String value) {
  try {
    return Success(double.parse(value)); // 성공 시 반환
  } on FormatException catch (e) {
    return Error(e); // 실패 시 반환
  }
}
  • Success Either.right
  • Error ↔ Either.left

다만 Either는 더욱 강력하고 다양한 API를 제공한다.

 

tryCatch 팩토리 생성자

tryCatch 팩토리 생성자를 사용하면 코드를 더욱 간소화할 수 있다.

Either<FormatException, double> parseNumber(String value) {
  return Either.tryCatch(
    () => double.parse(value),
    (e, _) => e as FormatException,
  );
}

 

구현방식

factory Either.tryCatch(
    R Function() run, L Function(Object o, StackTrace s) onError) {
  try {
    return Either.of(run());
  } catch (e, s) {
    return Either.left(onError(e, s));
  }
}
  • 첫 번째 매개변수는 실행할 함수이다.
  • 두 번째 매개변수는 에러와 스택 트레이스를 받아 처리하는 콜백이다.

위 예시에서는 double.parse가 항상 FormatException만 던지므로 안전하게 캐스팅(as FormatException)할 수 있다.

 

결론

Flutter에서도 함수형 프로그래밍을 활용한 에러 처리가 가능하다. 특히, fpdart 패키지의 Either<L, R> 타입은 다음과 같은 장점을 제공한다.

  • 함수 시그니처에 에러 가능성을 명시적으로 표현하여 코드 가독성과 안정성을 높임
  • 컴파일 타임에 에러 처리를 강제하여 런타임 오류를 줄임
  • 다양한 메서드(map, mapLeft, fold, 등)를 통해 데이터를 유연하게 조작 가능

이러한 접근법은 특히 대규모 프로젝트나 복잡한 비즈니스 로직이 포함된 애플리케이션에서 유용하다. FP 스타일로 코드를 작성하면 더 안전하고 유지보수가 용이한 애플리케이션을 개발하는데 도움이 될 것이라 생각한다.

 

아래 링크의 포스팅을 참고하여 정리한 내용입니다. 원문을 확인하고 싶으시면 아래 링크를 확인해주세요.

출처 - https://flutterexperts.com/functional-error-handling-in-flutter/