Study/Dart,Flutter

22. [Flutter] 알면 매우 정말 너무 좋은 패키지들 [1부]

코딩 잘 할거얌:) 2024. 3. 13. 00:54
반응형

Clean architecture에 대해서 포스팅하다가 좋은 패키지들에 대한 내용 소개가 필요할 거 같아 작성하게 되었다.


 

 

사용하기 좋은 패키지

1. Freezed 

https://pub.dev/packages/freezed

 

freezed | Dart package

Code generation for immutable classes that has a simple syntax/API without compromising on the features.

pub.dev

Clean architecture에서 Domain Layer는 애플리케이션의 핵심 비즈니스 논리를 포함해서 외부 프레임워크나 라이브러리에 의존하지 않아야 하며, 데이터모델을 불변으로 만들어 안정성을 높이는 게 중요하다.

이 Freezed 패키지는 데이터모델을 불변으로 만들어준다. 우선 왜 불변이 필요하냐 라는걸 들어가기 전에, 불변 프로그래밍(Immutable Programming)의 중요성에 대해서 설명이 필요하다.

https://adabeat.com/fp/immutability-in-functional-programming/

 

Immutability in Functional Programming - Ada Beat

Immutability in Functional Programming. Learn how immutability enhances code predictability, thread safety, and state management.

adabeat.com

간단하게 이야기하자면, 

불변프로그래밍이라는 것은, 객체가 생성된 후에는 그 상태를 변경할 수 없도록 하는 프로그래밍 패러다임이다. 복잡한 애플리케이션 개발에서 아주 중요한 역할을 하는데, 코드의 예측 가능성을 높이는데 큰 도움이 된다.

예측이 가능하다, 즉 불변객체는 생성 후 변경할 수 없으므로 코드의 동작을 예측하기가 더 쉬워지며,

상태변경으로 인한 부작용이 적으며,

멀티스레드 환경에서 객체의 상태가 변경되지 않으므로 동시성 문제를 방지하는데 큰 도움이 되며,

새로운 객체는 필요할때만 생성하므로 효율적으로 메모리 관리하가 편하다. 

이렇게 불변프로그래밍을 지향하는 코드를 작성하는 데에 있어 Freezed가 아주 적합한 도구라고 할 수 있다.

여담으로 Freezed를 사용하면, json_serializable, Equatable을 따로 사용하지 않아도 된다는 장점이 있다. (Json_serializable은 서버와 주고받는 데이터 형식, Json을 class(객체) 간 변환을 편하게 해주는 패키지이다. Equatable은 객체 동등성, == 을 재정의 해주는 패키지이다.) 

2. Get_it 

https://pub.dev/packages/get_it

 

get_it | Dart package

Simple direct Service Locator that allows to decouple the interface from a concrete implementation and to access the concrete implementation from everywhere in your App"

pub.dev

get_it은 의존성 주입할때 좀 더 편리하게 사용할 수 있는 패키지이다. 

설명이 길어질 수 있어서 추후 관련 내용을 포스팅하면 링크를 달아서 더 자세하게 알 수 있도록 하겠다. 일단 코드로 비교해 주자면,

/// get_it을 쓰지 않는다면
/// 다음과같이 매번 선언을 하고 사용해야한다.

class MyApp extends StatelessWidget {
  final MyServiceA serviceA = MyServiceA();
  final MyServiceB serviceB = MyServiceB();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: ElevatedButton(
            onPressed: () {

              serviceA.getAll();
              
              serviceB.getFiltedData();
            },
            child: Text('데이터 가져오기'),
          ),
        ),
      ),
    );
  }
}

/// get_it을 쓰는경우.
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              // GetIt을 사용하여 서비스 A 및 서비스 B 인스턴스를 가져와 작업 수행
              GetIt.instance<MyServiceA>().getAll();
              GetIt.instance<MyServiceB>().getFiltedData();
            },
            child: Text('Do Something'),
          ),
        ),
      ),
    );
  }
}

이렇게 차이가 나지만, 이 내용은 추후 다시 설명하도록 하겠다. 하지만 쓰면 정말 편한 패키지 중 하나이다.

 

3. Chopper (http, dio, retrofit...)

https://pub.dev/packages/chopper

 

chopper | Dart package

Chopper is an http client generator using source_gen, inspired by Retrofit

pub.dev

Chopper는 API 요청을 편리하게 작성할 수 있는 패키지이다. API호출뿐만 아니라 json 처리도 편리하게 할 수 있으며, 데이터 들어오는 것을 interceptor 해서 처리하거나 Converters가 있어서 데이터 변환에도 아주 편리하다. 이와 비슷한 패키지로는 http, dio, retofit 등이 있고 각 패키지들도 장단점이 있으므로 한 번씩 경험해 보기 바란다. (개인적으로 간단하게 사용하기엔 dio가 편했다.)

Chopper는 공식문서가 잘 되어있는 편이라, Interceptor는 어떻게 쓰는지, Converter는 어떻게 활용하는지 자세히 있어서 써보면 좋은 패키지 중 하나라고 생각한다.

아래는 실제로 내가 사용한 코드 중 일부이다.

각 서버마다 구축되어 있는 방식, 오류 던져주는 방식 모두 다 다르므로 참고만 하기 바란다.

4. dartz

https://pub.dev/packages/dartz

 

dartz | Dart package

Functional Programming in Dart. Purify your Dart code using efficient immutable data structures, monads, lenses and other FP tools.

pub.dev

dartz는 Either이라는 것을 사용할 수 있는 패키지이다. Either이란, 두 가지의 반환타입을 가질 수 있게 도와준다.

dart언어에서는 항상 하나의 타입만 반환이 가능하다. 하지만 Either를 사용하면 두 가지 타입을 반환할 수 있도록 도와줘서 성공했다면 Right, 실패했다면 Left로 반환하게 된다.

 

https://medium.com/nerd-for-tech/better-error-handling-with-either-type-in-dart-b91bef20d716

아래 코드를 보자

유저의 데이터를 삭제하는 Usecase이다. Either <ErrorModel, bool>을 반환하여, return right를 하면 bool을 반환하고, return left를 하면 ErrorModel을 반환하는 방식이다.

개인적으로 타입을 하나만 반환하는 것에 굉장히 답답했는데, 이걸로 해소가 되는 거 같아 너무나도 사이다스러운 패키지였다.

개인적으로 dartz를 쓴다면 아래 extension은 꼭 쓰도록 하자 굉장히 편리하다.

import 'package:dartz/dartz.dart';

/// [EitherX]는 Dartz 라이브러리의 [Either] 타입에 대한 확장(extension)입니다.
extension EitherX<L, R> on Either<L, R> {
  /// [Either]의 값이 [Right]인 경우 해당 값을 반환합니다.
  ///
  /// 사용 예:
  /// ```dart
  /// final result = Right(42);
  /// final value = result.asRight(); // 42
  /// ```
  R asRight() => (this as Right).value;

  /// [Either]의 값이 [Left]인 경우 해당 값을 반환합니다.
  ///
  /// 사용 예:
  /// ```dart
  /// final result = Left('Error occurred');
  /// final error = result.asLeft(); // 'Error occurred'
  /// ```
  L asLeft() => (this as Left).value;
}

추천할 패키지는 너무너무너무 많지만 우선 화면에 필요한 패키지들과 쓰면 좋은 정도(?)의 패키지들은 추후 포스팅하도록 하겠다.

728x90