반응형

📝Flutter 라이브러리

Http

  • Http
    • Flutter에서 가장 기본적으로 많이 사용되는 HTTP 통신 라이브러리입니다. 간단한 GET, POST 요청을 할 때 주로 사용됩니다.
  • DIO (채택)
    • 복잡한 HTTP 요청이나 응답, 예를 들어 인터셉터, 쿠키 관리, 파일 업로드 및 다운로드 등을 쉽게 처리할 수 있는 강력한 HTTP 클라이언트 라이브러리입니다.

 

Logging

  • Flutter는 프론트이기 때문에 프론트의 경우 따로 로깅을 하지 않는다. 로깅이 필요하면 지원하는 logging 라이브러리를 사용한다. 
  • https://pub.dev/packages/logging

 

상태관리

  • Provider
  • Riverpod (Provider 개선버전) [추천]
  • Bloc [추천이라는데 안 써봐서 모름]
  • GetX [추천이라는데 안 써봐서 모름]
  • MobX
  • Redux
  • Cubit

 

그 외 라이브러리

  • Freezed
    • Freezed에 맞게 코드를 짜고 코드제너레이터를 하면 그 필드에 맞게 생성자나, 직렬화, 역직렬화등에 대한 정보를 만들어줍니다. (보일러플레이트 감소)
  • jsonDecode
    • String으로 온 데이터를 Json으로 변환시켜준다. (DIO하고 Freezed 같이 사용하면 따로 필요 없어보인다.)
  • url_launcher
    • launchUrlString을 통해 페이지 이동이 가능하다.
  • SharedPreferences
    • 사용자 내부 디바이스에 저장 및 활용할 수 있게 도와준다.
  • GoRouter
    • 라우팅을 도와줍니다.
  • permission_handler
    • 권한 요청을 간단하게 해주는 것
  • camera
    • 카메라 사용
  • gallery_saver
    • 갤러리 사용

 

📝IDE 설정 & 안드로이드 스튜디오 Flutter 팁

https://mondaymonday2.tistory.com/1007

 

[Flutter] Flutter 팁 (Save시 Prettier 적용, Flutter Widget Method, Widget Extract, Error 메시지, Widget or Method Hierarc

📝IDE 설정저장할 때 마다 trailing comma 바로 코드 적용 (auto prettier)Format code on save를 통해 저장 시 Prettier가 바로 동작해 정리해준다.  trailing comma에 대한 Weak Warning Message 표시 및 출력linter: rules: re

mondaymonday2.tistory.com

 

 

📝네이밍 컨벤션 & Tip

SnakeCase

  • file_system.dart
  • folder
  • import 'package:angular_components/angular_components.dart' as angular_components;

 

CamelCase

  • class SliderMenu { ... }
  • function
  • function args
  • variable

 

PascalCase

  • typedef Predicate<T> = bool Function(T value);
  • @Foo(anArg)
  • extension MyFancyList<T> on List<T> { ... }

 

Tip

  • 타입캐스팅
    • var map = table.asMap(); 또는 toMap이긴한데 얕은복사냐 깊은복사냐에 따라 다르다고하다 그냥 to로 쓰자 귀찮다
  • bool 변수는 긍정이름 선호
    • hasData (O)
    • isEmpty (X)
  • 메소드명
    • 행위가 강조되는 경우 downloadData처럼 데이터를 반환하는 경우 get 제거
    • breakfastOrder (O)
    • getBreakfastOrder (X) 
  • 메소드 매개변수
    • add(element) [O]
    • addElement(element) [X]
  • 함수 New 타입 
    • 클래스를 하나 만들지말고 typedef Predicate<E> = bool Function(E element); 이렇게 써라. 너무 남발하면 복잡해지니 자제하면서 알아서 사용
// 좋은 예시
typedef Comparison<T> = int Function(T a, T b);

// 나쁜 예시
typedef int Comparison<T>(T a, T b); // 구식 문법
  • 메서드 체이닝
    • 체이닝을 위해 return에 this를 반환하는것보다는 매서드 케서케이드(..)를 사용하는게 좋다.
// wrong code

class Person {
  String name = '';
  int age = 0;

  Person setName(String name) {
    this.name = name;
    return this; // `this`를 반환
  }

  Person setAge(int age) {
    this.age = age;
    return this; // `this`를 반환
  }
}

void main() {
  var person = Person()
      .setName('Alice')  // 메서드 체이닝
      .setAge(30);       // 메서드 체이닝
  print('Name: ${person.name}, Age: ${person.age}');
}

// right code
class Person {
  String name = '';
  int age = 0;

  void setName(String name) {
    this.name = name;
  }

  void setAge(int age) {
    this.age = age;
  }
}

void main() {
  var person = Person()
    ..setName('Alice')  // 메서드 캐스케이드
    ..setAge(30);       // 메서드 캐스케이드
  print('Name: ${person.name}, Age: ${person.age}');
}
  • 타입 명시화
    • 로컬 변수 타입이 명확하면 생략하는게 좋습니다.
    • Dart 대부분 제네릭 타입인자 추론이 가능하지만 정보가 없으면 타입인자 명시 해야합니다.
// 좋은 예시
var desserts = <List<Ingredient>>[];

// 나쁜 예시
List<List<Ingredient>> desserts = <List<Ingredient>>[];

// ─────────────────────────────────────────────────────────────

// 좋은 예시
var playerScores = <String, int>{}; // 명시적으로 타입 인자 지정
final events = StreamController<Event>();

// 나쁜 예시
var playerScores = {}; // 타입 인자 없음
final events = StreamController(); // 타입 인자 없음
  • 생성자 생성
// 간단한 방식
Point(this.x, this.y);
  • Setter 반환타입 지정하지 않기
// 좋은 예시
set foo(Foo value) { ... }

// 나쁜 예시
void set foo(Foo value) { ... } // 불필요한 반환 타입
  • dynamic 타입 금지
    • 컴파일 타입체크를 비활성하기 때문에 사용하지 않는 게 좋다
  • 함수 매개변수 명시화
    • 매개변수 위치에 따라 받는 것보다는 이렇게 명시해서 데이터를 직접 받는게 안전하고 이해가 쉽다.
class ListBox {
  final bool scroll;
  final bool showScrollbars;

  ListBox({this.scroll = false, this.showScrollbars = false});
}

void main() {
  // 명명된 매개변수를 사용하여 `ListBox` 인스턴스를 생성
  var listBox = ListBox(scroll: true, showScrollbars: true);
}

// 명명된 매개변수를 가진 함수
void createUser({required String name, int age = 18, String? email}) {
  print('Name: $name, Age: $age, Email: $email');
}
  • == 오버라이딩
    • 기본적으로 ==는 참조값 비교하기 때문에 실제값 비교를 위해서는 오버라이딩이 필요하다

 

 

https://dart.dev/effective-dart/style

https://dart.dev/effective-dart/usage

https://dart.dev/effective-dart/design

 

 

📝Flutter 프로젝트 구조

lib/
 ├─ model
     ├─ my_menu
         ├─ my_menu_model.dart
 ├─ repository
     ├─ my_menu
         ├─ my_menu_repository.dart
 ├─ view_model
     ├─ my_menu
         ├─ my_menu_view_model.dart
 ├─ screen
     ├─ my_menu
         ├─ my_menu_screen.dart
 ├─ common
     ├─ enum
	 ├─ exception
     ├─ logger
     ├─ util
 ├─ widget
     ├─ my_menu
          ├─ profile.dart

다양한 구조가 있지만 MVVM 구조가 앱개발할 때 가장 적합한 스타일이라고한다. (iOS / AOS에도 적극 채용중) Rivderpod을 선택했고 Riverpod의 경우 MVVM에 맞게 개발되었기 때문에 MVVM 프로젝트 구조가 적합하다.

 

  • model
    • 데이터의 모델을 의미한다.
  • repository
    • 비즈니스 로직이 들어간다.
  • view_model
    • 화면과 연결하는 부분으로 API통신해서 가져온 데이터를 가공해서 화면에 전달해주는 브릿지 역할을 합니다.
  • screen
    • 사용자가 보는 화면을 의미합니다. view_model에서는 API통신 후 온 데이터에 대한 가공등이 들어가지만 UI관련 로직은 screen에 들어가게 됩니다.
  • common
    • 공통으로 처리하는 부분입니다.
  • widget
    • 화면의 요소를 컴포넌트화 시킨 것입니다.

 

 

 

반응형