Flutter 앱을 만들다 보면, 외부 API 서버와 데이터를 주고받는 HTTP 통신이 필수가 됩니다. 물론 Flutter에는 http라는 기본 패키지가 있지만, 에러 처리, 인터셉터, 파일 업로드, 토큰 자동 추가 같은 고급 기능을 구현하려면 Dio 패키지가 훨씬 더 강력한 도구가 됩니다.
이번 글에서는 Dio를 활용해 HTTP 통신을 구현하는 방법을 소개하고, 간단한 코드 예제까지 함께 다뤄볼 거예요. Dio를 처음 접하는 분들에게 왜 Dio를 사용하는지, 어떻게 시작해야 하는지, 그리고 실제로 어떻게 데이터를 주고받는지를 이해하는 데 도움이 되면 좋겠습니다.
Dio란 무엇이고, 왜 사용할까?
Dio는 Dart에서 제공하는 고급 HTTP 클라이언트 라이브러리입니다. Flutter 프로젝트에 Dio를 추가하면 다음과 같은 이점을 누릴 수 있어요:
- 간결한 문법으로 요청/응답 처리
- 자동 JSON 변환
- 인터셉터를 통한 요청/응답 가로채기 가능 (예: 토큰 자동 추가)
- 에러 핸들링이 간편
- FormData, 파일 업로드 지원
- 캐시, 타임아웃, 리다이렉트 제어 등 세밀한 설정 가능
예를 들어 일반적인 http 패키지로는 요청마다 복잡한 처리가 필요했던 부분을, Dio에서는 훨씬 직관적인 문법으로 구현할 수 있습니다. 특히 REST API 연동이 많은 앱에서는 Dio를 쓰는 것이 유지보수에 훨씬 효율적이에요.
Dio 설치 및 기본 사용법
Dio를 프로젝트에 적용하려면 먼저 pubspec.yaml 파일에 의존성을 추가해야 합니다.
// 2025년 4월 14일 기준 최신 버전
dependencies:
dio: ^5.8.0+1
이후 flutter pub get으로 패키지를 설치한 뒤, 아래와 같이 사용할 수 있어요.
1. Dio 객체 생성 및 기본 GET 요청
import 'package:dio/dio.dart';
void main() async {
final dio = Dio(); // Dio 객체 생성
try {
final response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
print(response.data); // JSON 형태로 응답 데이터 출력
} catch (e) {
print('에러 발생: $e');
}
}
이처럼 단 한 줄로 GET 요청을 보낼 수 있고, 응답은 자동으로 JSON 형태로 파싱되어 옵니다.
2. POST 요청 보내기
final response = await dio.post(
'https://jsonplaceholder.typicode.com/posts',
data: {
'title': 'Flutter Dio',
'body': 'Dio는 정말 편리해요!',
'userId': 1,
},
);
print(response.data);
여기서 data:는 서버에 전송할 Map<String, dynamic> 데이터를 의미하며, 서버에서 응답받은 데이터도 response.data로 쉽게 접근할 수 있어요.
3. 응답 데이터 타입 확인하기
print(response.statusCode); // 200 등 상태코드
print(response.headers); // 응답 헤더
print(response.data); // 응답 바디(JSON)
필요한 경우 BaseOptions를 설정해 전역 Dio 인스턴스를 구성할 수도 있고, API 호출에 필요한 토큰을 넣는 것도 가능합니다.
Dio의 고급 기능: 인터셉터, 토큰 관리, 에러 핸들링
Dio는 단순한 요청뿐 아니라, 실무에 필수적인 고급 기능들도 매우 강력하게 지원합니다. 특히 인증 토큰이 필요한 API, 반복되는 요청 패턴, 에러 처리 등을 쉽게 다룰 수 있도록 인터셉터 기능을 제공하죠.
1. 인터셉터(Interceptor)
인터셉터는 모든 요청이나 응답, 에러를 가로채서 사전 처리할 수 있도록 해줍니다.
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
options.headers['Authorization'] = 'Bearer 토큰값';
return handler.next(options); // 요청 계속 진행
},
onResponse: (response, handler) {
// 응답 가공 가능
return handler.next(response);
},
onError: (DioException e, handler) {
print('에러 발생: ${e.message}');
return handler.next(e); // 에러 계속 전달
},
));
이렇게 하면 매 요청마다 토큰을 일일이 붙이지 않아도 되고, 에러나 응답 처리를 일괄적으로 할 수 있어요.
2. 옵션 설정
BaseOptions를 통해 기본 URL, 타임아웃, 헤더 등을 설정할 수도 있습니다.
final dio = Dio(BaseOptions(
baseUrl: 'https://jsonplaceholder.typicode.com',
connectTimeout: const Duration(seconds: 5),
receiveTimeout: const Duration(seconds: 5),
headers: {'Accept': 'application/json'},
));
3. 에러 핸들링
에러 종류에 따라 분기 처리가 가능합니다.
try {
final response = await dio.get('/posts/1');
} on DioException catch (e) {
if (e.type == DioExceptionType.connectionTimeout) {
print('서버 연결 시간 초과');
} else if (e.response?.statusCode == 401) {
print('인증 실패');
} else {
print('예상치 못한 오류 발생: ${e.message}');
}
}
이런 방식으로 실무에서도 흔히 발생할 수 있는 문제들을 구조적으로 처리할 수 있습니다.
마치며...
Dio는 단순한 HTTP 요청을 넘어서, 실무에 필요한 거의 모든 네트워크 기능을 깔끔하게 처리할 수 있는 도구예요. 기본 사용법만 익혀도 충분히 편리하지만, 인터셉터나 에러 핸들링 기능까지 잘 활용하면 훨씬 유연한 코드 구성이 가능해집니다.
특히 전역 상태 관리(Riverpod, Provider 등)와 연계하여 ViewModel에서 Dio를 사용하는 구조를 짜면 유지보수성과 테스트성까지 챙길 수 있으니 꼭 연습해보시길 추천드려요.
세 줄 요약
- Dio는 Flutter에서 강력하고 직관적인 HTTP 통신 라이브러리입니다.
- 기본 GET/POST 요청뿐 아니라, 인터셉터나 토큰 관리, 에러 핸들링까지 가능합니다.
- 실무에서도 자주 쓰이는 만큼, 확실히 익혀두면 큰 도움이 됩니다.
'IT' 카테고리의 다른 글
코딩 몰라도 개발하는 시대, 바이브 코딩 (2) | 2025.04.15 |
---|---|
Firebase를 연동해보자! (0) | 2025.04.15 |
MVVM 아키텍처와 전역 상태 관리 (0) | 2025.04.11 |
Dart 데이터 직렬화와 역직렬화 (0) | 2025.04.10 |
바이브 코딩으로 달라지는 개발 워크플로우 (0) | 2025.04.08 |