Feature-based Clean Architecture으로 API 통신하기 - 2

개발렬·2024년 11월 3일

Flutter

목록 보기
1/10
post-thumbnail

이번 포스팅에서는 Feature-based Clean Architecture에서 API 통신을 구현하는 방법을 다루겠습니다.

data - model

먼저, 데이터 모델을 정의합니다. PairingModel이라는 이름으로 데이터를 처리하며, freezed를 통해 간결하고 안전하게 코드를 생성합니다.

import 'package:freezed_annotation/freezed_annotation.dart';

part 'pairing_model.freezed.dart';
part 'pairing_model.g.dart';

@Freezed()
class PairingModel with _$PairingModel {
  factory PairingModel({
    @JsonKey(name: "ID") String? id,
    @JsonKey(name: "NAME") String? name,
  }) = _PairingModel;

  factory PairingModel.fromJson(Map<String, dynamic> json) =>
      _$PairingModelFromJson(json);
}

위 코드에서는 PairingModel 클래스에 id와 name 필드를 정의했으며, freezed 패키지가 제공하는 JSON 직렬화/역직렬화 기능을 사용하여 API와의 데이터 매핑을 자동화했습니다.

domain - repositories

PairingRepository는 API 호출 로직을 담고 있습니다. NetWorkRepository 의존성을 주입하여 네트워크 통신을 수행합니다.

import '../../../../../common/network/network_manager.dart';

class PairingRepository {
  final NetWorkRepository netWorkManagerRepository;

  PairingRepository(this.netWorkManagerRepository);

  Future<dynamic> postPairing(String telNo, String gender, String birthYear,
      String residentialArea) async {
    return await netWorkManagerRepository.postResponse(
      domainUrl: "~",
      url: '~',
      data: {
        "TEL_NO": telNo,
      },
      headers: {
        "Content-Type": "application/json",
      },
    );
  }
위의 postPairing 메서드는 전화번호 정보를 서버로 전송하며, 네트워크 레이어와의 결합을 최소화하여 깔끔하게 유지합니다.

domain - usecase

비즈니스 로직을 분리하기 위해 UseCase를 정의합니다. PostParingUseCase는 PairingRepository를 호출해 데이터를 받아오고, 이를 PairingModel로 변환합니다.

import '../../data/models/pairing_model.dart';
import '../repositories/pairing_repository.dart';

class PostParingUseCase {
  final PairingRepository repository;

  PostParingUseCase(this.repository);

  Future<PairingModel> call(String telNo) async {
    final response =
        await repository.postPairing(telNo);
    return PairingModel.fromJson(response);
  }
}

presentations - providers - notifier.dart

PairingNotifier는 StateNotifier를 사용하여 PairingModel의 상태를 관리합니다. postPairing 메서드는 API 호출 후 상태를 업데이트하며, 예외 처리도 포함합니다.

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:homechoice/features/pairing_feature/domain/usecases/set_stb_nikename_use_case.dart';

import '../../data/models/pairing_model.dart';
import '../../domain/repositories/pairing_repository.dart';
import '../../domain/usecases/disconnect_pairing_use_case.dart';
import '../../domain/usecases/fetch_pairing_state_use_case.dart';
import '../../domain/usecases/fetch_stb_pairing_devices_use_case.dart';
import '../../domain/usecases/fetch_tv_apps_use_case.dart';
import '../../domain/usecases/post_pairing_use_case.dart';

class PairingNotifier extends StateNotifier<PairingModel> {
  PairingNotifier(this.repository) : super(PairingModel());

  final PairingRepository repository;

  ///페어링 신규
  Future<void> postPairing(String telNo) async {
    try {
      final datas = await PostParingUseCase(repository)(
          telNo);
      state = state.copyWith(
        id: datas.id,
        name: datas.name,
      );
    } catch (error) {
      state = state.copyWith(isLoading: false);
    }
  }
}

presentations - providers - provider.dart

PairingProvider는 PairingNotifier를 제공하여, UI와 상태 관리를 연결해줍니다.

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:homechoice/features/pairing_feature/domain/repositories/pairing_repository.dart';
import '../../../../../common/network/network_manager.dart';
import '../../data/models/pairing_model.dart';
import 'pairing_notifier.dart';

final PairingProvider =
    StateNotifierProvider<PairingNotifier, PairingModel>((ref) {
  final netWorkManagerRepository = ref.read(netWorkManagerProvider);
  final repository = PairingRepository(netWorkManagerRepository);
  return PairingNotifier(repository);
});

위의 구조는 Feature-based Clean Architecture에서 각각의 책임을 명확히 분리하여 확장성과 테스트 가능성을 높인 예제입니다.

profile
Flutter

0개의 댓글