Dio

dio | Dart Packages
http | Dart Packages

Singleton Pattern
JSONPlaceholder

이번 글에서는 Http, Rest API 통신에 사용하는 가장 인기가 많은 라이브러리인 Dio에 대해서 살펴보려고 한다.

API 통신을 할 때에 Flutter에서 대표적으로 사용하는 방법은 http 라이브러리로 통신을 하는 것이다. http 라이브러리는 기본적인 API 통신을 제공하고 응답 받은 json 파일을 dart:convert를 통해서 디코딩해서 사용한다.

Dio 라이브러리는 json 파일이 디코딩된 상태로 리턴되기에 좀 더 편하게 사용할 수 있다는 장점도 있고, 그 외에 Options, Interceptor 통해 다양한 기능을 한 번에 핸들링 할 수 있다는 장점도 있다.

Flutter

API 통신에 사용하는 get, post, delete, put에 대해서는 여기서 다루지 않고 Dio 라이브러리의 사용 법에 대해서만 다루도록 할 예정이다.

Dio 라이브러리를 세팅하는 방법은 여러 방법이 있겠지만, Singleton 구조로 생성하여 Interceptor를 상속받아 세팅하고 설정하는 부분에 대해서 알아보자.

dependencies

dependencies:
	dio: ^5.0.0

Dio

Dio의 기본 사용 구조이다.

get

Dio _dio = Dio();
await _dio.get($url);

post

Dio _dio = Dio();
Map<String, dynamic> _data = {
	"test" : 1,
    "test2" : 2,
};
await _dio.post($url,data:_data);

put

Dio _dio = Dio();
Map<String, dynamic> _data = {
	"test" : 1,
    "test2" : 2,
};
await _dio.put($url,data:_data);

delete

Dio _dio = Dio();
Map<String, dynamic> _data = {
	"test" : 1,
    "test2" : 2,
};
await _dio.delete($url,data:_data);

Dio Services

Dio를 세팅하기 위해 DioServices 객체를 싱글톤으로 생성하였다. 싱글톤은 객체의 인스턴스를 제한하여 기존 인스턴스를 리턴하여 하나의 인스턴스만 생성하도록 하는 패턴이다.

DioServices 객체가 API 호출시마다 인스턴스화 될 필요가 없고, 한 번 인스턴스가 진행되면 기존 객체를 가져다 사용하면 되기에 싱글톤 패턴을 사용한다.

BaseOptions 부분을 보면 baseUrl을 넣어 주면 Dio로 API 호출시 baseUrl은 작성하지 않아도 된다.

Timeout에 대해서도 설정하여 해당 타임아웃이 넘어가면 호출을 중지하도록 하여 네트워크 환경에 대한 핸들링을 할 수 있도록 한다.

이외에도 BaseOptions에는 다양한 옵션 파라미터를 제공하기에 필요에 따라서 여기서 세팅해주면 앱 전체에서 Dio 사용시 동일하게 적용된다.

interceptors 부분은 아래에서 계속해서 다루겠다.

class DioServices {
  static final DioServices _dioServices = DioServices._internal();
  factory DioServices() => _dioServices;
  Map<String, dynamic> dioInformation = {};

  static Dio _dio = Dio();

  DioServices._internal() {
    BaseOptions _options = BaseOptions(
      baseUrl: $url,
      connectTimeout: const Duration(milliseconds: 10000),
      receiveTimeout: const Duration(milliseconds: 10000),
      sendTimeout: const Duration(milliseconds: 10000),
      // headers: {},
    );
    _dio = Dio(_options);
    _dio.interceptors.add(DioInterceptor());
  }

  Dio to() {
    return _dio;
  }
}

Dio Interceptor

DioInterceptor 객체를 생성하여 Interceptor 객체를 상속받는다.

Interceptor객체에는 onRequest, onResponse, onError 함수를 오버라이딩하여 재정의해 사용할 수 있는데, 여기에 로그를 출력하도 되고, 상태 핸들링을 하여도 된다.

예를 들어 로그인 관련 토큰이 만료 되었을 때 로그인을 할 수 있도록 해주고 싶다면 onError 부분에 statusCode 중 401 조건을 추가하여 로그인 페이지로 보내주는 작업 등을 할 수 있다.

class DioInterceptor extends Interceptor {
  
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    logger.e("BaseUrl ${options.baseUrl}");
    logger.e("Path ${options.path}");
    logger.e("Parameters ${options.queryParameters}");
    logger.e("Data ${options.data}");
    logger.e("Connect Timeout ${options.connectTimeout}");
    logger.e("Send Timeout ${options.sendTimeout}");
    logger.e("Receive Timeout ${options.receiveTimeout}");
    super.onRequest(options, handler);
  }

  
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    logger.e(response.statusCode);
    logger.e(response.data);
    logger.e("BaseUrl ${response.requestOptions.baseUrl}");
    logger.e("Path ${response.requestOptions.path}");
    logger.e("Parameters ${response.requestOptions.queryParameters}");
    logger.e("Data ${response.requestOptions.data}");
    logger.e("Connect Timeout ${response.requestOptions.connectTimeout}");
    logger.e("Send Timeout ${response.requestOptions.sendTimeout}");
    logger.e("Receive Timeout ${response.requestOptions.receiveTimeout}");
    super.onResponse(response, handler);
  }

  
  void onError(DioError err, ErrorInterceptorHandler handler) async {
    logger.e("Error ${err.error}");
    logger.e("Error Message ${err.message}");
    super.onError(err, handler);
  }
}

자 이제 세팅 작업은 끝이 났다. DioServices 객체를 인스턴스하여 호출을 하면 debug console에 Interceptor에서 세팅한 로그가 출력되는 것을 확인 할 수 있다.

Dio _dio = DioServices().to();
await _dio.get("https://picsum.photos/v2/list");

Git

https://github.com/boglbbogl/flutter_velog_sample/tree/main/lib/library/dio

마무리

HTTP / API에 사용하는 라이브러리인 Dio에 대해서 살펴보았다. Dio 라이브러리는 HTTP 통신시 에러, 응답, 요청 등의 내용을 한 번에 수신하고 처리할 수 있고, 통신 딜레이 타임, URL 세팅 등 다양한 기능을 제공하고 있어 편하게 개발을 할 수 있도록 도와주는 라이브러이다.

직접 사용해 보면서 http 라이브러리와 dio 라이브러리의 차이점을 확인해 보도록 하자.

profile
Flutter Developer

0개의 댓글