2024년 11월 9일 토요일

Flutter #1

 [Flutter 교육]


Dart2JS

YAML
복사
dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 js: ^0.7.1 json_annotation: ^4.9.0 freezed_annotation: ^2.4.4 dev_dependencies: flutter_test: sdk: flutter # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^3.0.0 build_runner: ^2.4.11 freezed: ^2.5.2 json_serializable: ^6.8.0

1. 모델 정의 (user_model.dart)

Dart
복사
import 'package:freezed_annotation/freezed_annotation.dart'; part 'user_model.g.dart'; part 'user_model.freezed.dart'; class User with _$User { const factory User({ required String id, required String name, required int age, String? email, ([]) List<String> roles, }) = _User; factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); }

해설

@freezed: 불변 객체를 생성하는 어노테이션
_$User: Freezed가 생성하는 믹스인
const factory: 불변 인스턴스 생성을 위한 팩토리 생성자
@Default([]): 기본값 지정
fromJson: JSON 변환을 위한 팩토리 메서드

2. JavaScript 서비스 정의

Dart
복사
('UserService') class UserService { external UserService(); external JSPromise getUserById(String id); external JSPromise updateUser(JSObject user); external JSPromise searchUsers(JSObject criteria); }

해설

@JS(): JavaScript 클래스/함수와 매핑
external: 실제 구현은 JavaScript에 있음을 표시
JSPromise: JavaScript Promise를 나타내는 타입
JSObject: JavaScript 객체를 나타내는 타입

3. 리포지토리 구현

Dart
복사
class UserRepository { final UserService _service = UserService(); Future<User> getUserById(String id) async { try { final JSObject result = await promiseToFuture(_service.getUserById(id)); return User.fromJson(result.dartify() as Map<String, dynamic>); } catch (e) { throw Exception('Failed to fetch user: $e'); } }

해설

promiseToFuture: JS Promise를 Dart Future로 변환
dartify(): JS 객체를 Dart 객체로 변환
as Map<String, dynamic>: 타입 안전성을 위한 캐스팅
에러 처리와 예외 전파

4. 데이터 변환 프로세스

Dart
복사
// JS → Dart final JSObject result = await promiseToFuture(_service.getUserById(id)); return User.fromJson(result.dartify() as Map<String, dynamic>); // Dart → JS final jsUser = user.toJson().jsify();

변환 과정

JavaScript → Dart:
Plain Text
복사
JS Object → JSObject → Dart Map → User 객체
Dart → JavaScript:
Plain Text
복사
User 객체 → Dart Map → JSObject → JS Object

5. 위젯 구현의 주요 포인트

Dart
복사
class _UserManagementWidgetState extends State<UserManagementWidget> { Future<void> _updateUserAge() async { if (_selectedUser == null) return; try { final updatedUser = await _repository.updateUser( _selectedUser!.copyWith(age: _selectedUser!.age + 1) ); setState(() => _selectedUser = updatedUser); } catch (e) { // 에러 처리 } }

해설

copyWith: Freezed가 제공하는 불변 업데이트 메서드
상태 관리: setState를 통한 UI 업데이트
비동기 작업 처리
에러 처리와 사용자 피드백

6. JavaScript 구현

JavaScript
복사
class UserService { async getUserById(id) { const mockUser = { id: id, name: 'John Doe', age: 30, email: 'john@example.com', roles: ['user', 'admin'] }; return mockUser; }

해설

비동기 메서드 (async/await 사용)
Promise 반환
모의 데이터 제공
Dart 모델과 일치하는 데이터 구조

7. 주요 기술적 고려사항

타입 안전성

Dart
복사
// 잘못된 방법 final result = await _service.getUserById(id); // 타입 불안전 // 올바른 방법 final JSObject result = await promiseToFuture(_service.getUserById(id));

메모리 관리

Dart
복사
// 메모리 누수 가능성 element.addEventListener('click', allowInterop(handleClick)); // 올바른 방법 final handler = allowInterop(handleClick); element.addEventListener('click', handler); element.removeEventListener('click', handler);

성능 최적화

Dart
복사
// 비효율적 for (var user in users) { final jsUser = user.toJson().jsify(); // 매번 변환 } // 최적화 final jsUsers = users.map((u) => u.toJson()).toList().jsify(); // 한 번에 변환

8. 베스트 프랙티스

에러 처리
Dart
복사
try { final result = await promiseToFuture(_service.riskyOperation()); } catch (e) { if (e is JSError) { // JavaScript 에러 처리 } else { // Dart 에러 처리 } }
타입 체크
Dart
복사
if (result is! JSObject) { throw TypeError('Expected JSObject'); }
널 체크
Dart
복사
final email = user.email; // Freezed가 제공하는 널 안전성 if (email != null) { // 안전한 처리 }

9. 디버깅 팁

콘솔 로깅
Dart
복사
('console') external void log(dynamic message); // 사용 log(user.toJson()); // JavaScript 콘솔에서 확인
개발자 도구 활용
Dart
복사
// 브레이크포인트 설정 가능한 코드 구조 Future<User> getUserById(String id) async { final result = await promiseToFuture(_service.getUserById(id)); final json = result.dartify(); // 여기서 중단점 설정 return User.fromJson(json); }


출처 : https://cheddar-sparrow-aba.notion.site/Dart2JS-13997e0a8ff3807da3c6d76e0011bd4d



Flutter #0

[Flutter 교육] Dart vs JavaScript 타입 시스템 비교 1. 기본 타입 차이 숫자 타입 // Dart int integerNumber = 42; // 정수 double floatingPoint = 3.14; // 부...