통조림

[Flutter] Dio 활용해서 HTTP통신 구현하기(1) - Dio 생성하기 본문

Software/Flutter

[Flutter] Dio 활용해서 HTTP통신 구현하기(1) - Dio 생성하기

고랭지참치 2024. 4. 2. 23:39

앱을 개발하다보면 네트워크 통신 기능을 개발할 상황이 생깁니다.
Flutter는 HTTP프로토콜을 http라이브러리를 통해 네트워크 통신을 지원하고 있습니다.

Http 라이브러리만을 통해서 네트워크 통신 기능을 개발할 수 있지만 보일러플레이트 코드의 양이 많아 유지보수가 어렵습니다. 이를 개선하기 위해 Dio 패키지를 사용할 수 있습니다.

Dio패키지는 타임아웃, 인터셉터, 파일 업/다운로드, 요청취소와 같은 강력한 기능을 제공해주기 때문에 Dio를 사용해서 쉽고 빠르게 네트워크 통신 기능을 구현할 수 있습니다 :)

 

Dio 객체 생성하기

Http 통신을 위해 반복적으로 사용할 Dio 객체를 전역으로 생성합니다.
connectTimeout, receiveTimeout, baseUrl등을 BaseOptions 파라미터에 담아 생성할 수 있습니다.

final Dio dio = Dio(
  BaseOptions(
    contentType: Headers.jsonContentType,
    connectTimeout: const Duration(milliseconds: 5000),
    receiveTimeout: const Duration(milliseconds: 3000),
  ),
);

 

생성한 Dio로 http통신 시도해보기

https://jsonplaceholder.typicode.com/todos/1

위 샘플 api url을 사용하겠습니다. 위 url은 다음과 같은 데이터를 리턴합니다.

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

다음으로 비동기 메소드인 dio.get()를 호출해 데이터를 받아옵니다.

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  static const String apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
  String todo = '';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () async {
                  final response = await dio.get(apiUrl);
                  setState(() {
                    todo = response.data.toString();
                  });
                },
                child: const Text('GET TODO'),
              ),
              Text(
                'TODO: $todo',
                textAlign: TextAlign.center,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

위 코드를 실행하면 아래와 같은 결과를 얻을 수 있습니다.

위 스크린샷에 나와있는 것처럼 예상했던 데이터가 로그에 찍히고 화면에 노출되는 것을 확인할 수 있습니다.

 

Dio에 인터셉터 추가하기

초장에서 설명했던 것처럼 Dio의 강력한 기능중 하나는 인터셉터입니다.
Dio에서 제공하는 Intercepter클래스를 상속받는 커스텀 인터셉터 클래스를 생성한 뒤
onRequest, onResponse, onError 메소드를 구현할 수 있습니다.

class CustomInterceptor extends Interceptor {
  CustomInterceptor();

  // api 요청 보낼때
  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    logger.d('[REQUEST] ${options.method}] ${options.uri}');
    return super.onRequest(options, handler);
  }

  // api 응답 받을때
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    logger.d(
        '[RESPONSE] ${response.requestOptions.method}] ${response.requestOptions.uri}');
    return super.onResponse(response, handler);
  }

  // api 통신 중 에러 발생했을때
  @override
  void onError(DioException err, ErrorInterceptorHandler handler) async {
    logger.e(
        '[ERROR] ${err.requestOptions.method}] ${err.requestOptions.uri}  StatusCode:${err.response?.statusCode}, ${err.message}, ${err.type}');
  }
}

생성한 인터셉터를 dio객체를 생성할 때, interceptors.add() 메소드로 주입합니다.

final Dio dio = Dio(
  BaseOptions(
    contentType: Headers.jsonContentType,
    connectTimeout: const Duration(milliseconds: 5000),
    receiveTimeout: const Duration(milliseconds: 3000),
  ),
)..interceptors.add(CustomInterceptor());

인터셉터 메소드 확인하기


API 콜을 Dio로 보냈을 때 위와 같은 로그가 찍히는 것을 확인할 수 있습니다.

전체 코드 깃허브
https://github.com/KoreanTuna/Dio-Study