INEEDACHACHA

Flutter Network Module => Swift Moya Style로 만들어보기 본문

Flutter/전환실록

Flutter Network Module => Swift Moya Style로 만들어보기

INEEDACHACHA 2025. 6. 13. 09:27

api_service.dart

import 'package:network_module_sample/network_foundation/network_interface.dart';

class Host {
  // TODO: SecretClient를 추후에 구현해서 환경별로 baseURL을 바꿔준다.
  static String get baseURL => "https://jsonplaceholder.typicode.com";
}

// HTTP Method Enum
enum HttpMethod { get, post, put, delete }

enum MyApi with TargetType {
  getUsers,
  getUserDetail,
  createUser;

  @override
  String get baseUrl => Host.baseURL;

  @override
  String get path {
    switch (this) {
      case MyApi.getUsers:
        return "/users";
      case MyApi.getUserDetail:
        return "/users/1";
      case MyApi.createUser:
        return "/users";
    }
  }

  @override
  HttpMethod get method {
    switch (this) {
      case MyApi.getUsers:
      case MyApi.getUserDetail:
        return HttpMethod.get;
      case MyApi.createUser:
        return HttpMethod.post;
    }
  }

  @override
  Map<String, dynamic>? get headers => {
    "Content-Type": "application/json; charset=UTF-8",
  };

  @override
  dynamic get body {
    switch (this) {
      case MyApi.createUser:
        return {
          "name": "John Doe",
          "username": "johndoe",
          "email": "john@example.com",
        };
      default:
        return null;
    }
  }

  @override
  Map<String, dynamic>? get queryParams => null;
}
  • enum을 extension해서 TargetType을 구현하는 것이 불가능하다.
  • enum을 Swift 처럼 사용하려고 하면 안 된다.
  • 테스트 겸 구현이지만, 목적에 맞는 도구인가 에 대한 고민이 필요하다.
  • Moya Style에 의존하지 않고, dio + retrofit의 가장 클래식한 형태가 필요하다.
  • https://github.com/Moya/Moya

network_interface.dart

import 'package:network_module_sample/network_foundation/api_service.dart';

mixin TargetType {
  String get baseUrl;
  String get path;
  HttpMethod get method;
  Map<String, dynamic>? get headers;
  dynamic get body;
  Map<String, dynamic>? get queryParams;
}

network.dart

import 'package:dio/dio.dart';
import 'package:network_module_sample/network_foundation/network_interface.dart';

class NetworkManager {
  final Dio _dio = Dio();

  Future<Response> request(TargetType api) async {
    try {
      _dio.options.baseUrl = api.baseUrl;

      final options = Options(
        method: api.method.name.toUpperCase(),
        headers: api.headers,
      );

      return await _dio.request(
        api.path,
        options: options,
        data: api.body,
        queryParameters: api.queryParams,
      );
    } catch (e) {
      rethrow;
    }
  }
}