Dartz

dartz | Dart Package

이번 글은 Dartz라는 Flutter 라이브러리에 대해서 간단하게 살펴보기로 하겠다.

이전 글에서 Freezed Code Generator 사용 방법에 대해서 살펴보았는데, 이번엔 Dartz라는 Data Type 확장 기능을 가지고 있는 라이브러리에 대해서 살펴보도록 하겠다.

블로그에 토이 프로젝트 형식으로 간단한 앱 만들기를 계획하고 있는데, 앱 만들기를 하면서 라이브러리에 대한 글을 작성하면 내용이 너무 복잡해지고 길어질거 같아 프로젝트를 진행하기 앞서 사용 할 라이브러리에 대한 소개를 간략하게 하면 좋을 것 같다는 생각이 들었다.

Flutter는 Dart 언어를 사용하면서 Dart의 데이터 타입을 사용하고 있는데, Dartz 라이브러리에는 기존 Dart 언어에 포함되어 있지 않은 확장된 데이터 타입을 지원한다.

아래서 Dartz의 주요하게 사용하는 기능에 대해서만 소개하도록 하겠다.

Flutter

dependencies:
	dartz: ^0.10.1

Dartz의 간단한 사용 예제이다.
간단하게 API를 호출하는 부분을 작성한 것이다.

생소한 개념인 Either, right, left 등이 보인다. 쉽게 설명해서 Either란 말 그대로 성공, 실패 두 개의 케이스만 제공하는 확장 타입인데, 여기서 성공은 right, 실패는 left로 핸들링 할 수 있다.

아래에서 더 자세히 다뤄보자.

 Future<Either<Failure, Car>> getCarData() async {
    try {
    	...
      if (_response.statusCode == 200) {
      	...
        return right(_car);
      } else if (_response.statusCode == 400) {
      	...
        return left(Failure.emptyMetadataKey);
      } else if (_response.statusCode == 401) {
      	...
        return left(Failure.tokenExpired);
      } else {
        return left(Failure.emptyMetadataKey);
      }
    } catch (error) {
      return left(Failure.networkError);
    }
  }

Either

자 Either 타입에 대해서 더 자세히 알아보자. Either는 '둘 중 하나'라는 뜻으로 생각하면 되는데, 왜 이런 타입을 궂이 써야할까요?
Either를 리턴 받아온 객체에는 더 많은 종류의 핸들링 가능한 타입들과 메소드를 제공하고 있어서 Either를 사용하면 API에러를 처리하기가 매우 쉽고 간결해 진다.

API데이터를 처리할 때는 크게 성공 아님 실패 두 개의 케이스만 존재한다.
성공 중... 실패 중... 이런건 존재할 수 없다. 상태 관리와 헷갈리시면 안됩니다. Either는 그냥 타입입니다.

아래와 같이 리턴 타입을 Either로 정해서 Map형태의 실패, 성공의 데이터 타입을 넣어주면 된다.

실패 데이터 타입을 Failure라는 enum객체로 만들어 주고, 성공에 해당되는 부분에 성공할 때 받아와야 하는 타입을 넣어주면 된다.
물론 실패에 해당되는 부분에 null도 가능하다.

Future<Either<Failure, Car>> getCar() async {
  ...
}
Future<Either<Failure, bool>> getBool() async {
  ...
}
Future<Either<Failure, String?>> getString() async {
  ...
}
Future<Either<Failure, List<Car>>> getArray() async { 
  ...
}

Failure

실패 케이스를 생성할 때는 자유롭게 데이터 타입을 사용하여도 되지만 주로 아래와 같이 케이스를 만든다.

이전 글에서 살펴본 freezed로도 Failure 데이터를 만들 수 있다.


class Failure with _$Failure {
  const factory Failure.networkError() = _NetworkError;
  const factory Failure.tokenExpired() = _TokenExpired;
}
enum Failure { networkError, tokenExpired, emptyMetadataKey }

Success Or Failure

위에서 API로 데이터를 받아왔다고 가정하자 이제 리턴 받은 Either 타입을 실패, 성공에 따라 케이스를 받아줘야 하는데 이 부분은 아래와 같이 .fold 형태로 처리를 해주면 된다.

먼저 Failure 부분을 보면 l 에 해당 되는 부분이 Failure 객체이다.
r은 String?이다.

실패를 했으면 l로 로직이 작동될 것이고, 성공했으면 r에서 로직이 작동될 것이다.

엄청 간단하게 에러 처리를 할 수 있다.

   Either<Failure, String?> _successOrFailure = await getData();
    _successOrFailure.fold(
      (l) {
        // Failure
      },
      (r) {
        // Success
      },
    );

Failure 객체를 freezed로 생성했다면 아래의 .map() 기능을 사용할 수 있으며, .map() 외에도 .wheh(), .maybeMap() 등의 기능도 사용할 수 있다.

 _successOrFailure.fold(
      (l) {
        l.map(networkError: (e) {}, tokenExpired: (e) {});
      },
      (r) {
        // Success
      },
    );

Either 리턴 타입을 처리하는 방법은 .fold 외에도 많은 메소드가 제공되고 있어서 직접 사용해 보시는 것을 추천합니다.

 _successOrFailure.foldLeft(null, (previous, r) => null);
 _successOrFailure.foldRight(null, (r, previous) => null);
 _successOrFailure.all((r) => false);
 _successOrFailure.every((r) => false);
 _successOrFailure.getOrElse(() => null);

마무리

Dartz 라이브러리의 확장 타입은 차차 프로젝트 앱을 개발해 보면서 어떻게 사용해야 하는지에 대하여 깊게 파악하는 글을 작성하도록 하겠다.

한 번씩 테스트 삼아 사용해 보세요 ~ 에러 처리가 너무 편해져요 !!

profile
Flutter Developer

0개의 댓글