Flutter에서 Dio를 사용한 네트워크 통신 심화 가이드
Dio는 Flutter에서 HTTP 요청을 처리하기 위해 널리 사용되는 강력한 네트워크 라이브러리입니다. 높은 확장성과 풍부한 기능을 제공하여 간단한 API 호출부터 복잡한 네트워크 통신까지 효율적으로 처리할 수 있습니다. 이번 글에서는 Dio를 심화적으로 사용하는 방법을 다룹니다.
1. Dio 기본 설정
Dio 인스턴스를 생성하고 공통 설정을 추가하는 방법입니다.
import 'package:dio/dio.dart';
final dio = Dio(
BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: 5000, // 5초
receiveTimeout: 3000, // 3초
headers: {
'Content-Type': 'application/json',
},
),
);
- baseUrl: 모든 요청의 기본 URL입니다.
- connectTimeout: 서버 연결 제한 시간입니다.
- receiveTimeout: 응답 수신 제한 시간입니다.
- headers: 공통 헤더를 설정합니다.
2. Interceptor로 요청 및 응답 처리
Interceptor는 요청 전/후와 응답 전/후에 실행되는 로직을 정의할 수 있는 강력한 기능입니다.
dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) {
print('요청: ${options.method} ${options.path}');
options.headers['Authorization'] = 'Bearer YOUR_TOKEN';
return handler.next(options);
},
onResponse: (response, handler) {
print('응답: ${response.statusCode} ${response.data}');
return handler.next(response);
},
onError: (DioError e, handler) {
print('에러: ${e.response?.statusCode} ${e.message}');
return handler.next(e);
},
),
);
- onRequest: 요청이 서버로 보내지기 전에 실행됩니다.
- onResponse: 서버 응답을 받은 후 실행됩니다.
- onError: 요청 중 에러가 발생했을 때 실행됩니다.
3. Token 갱신 처리
토큰 만료 시 자동으로 갱신하고 요청을 재전송하는 방법입니다.
class TokenInterceptor extends Interceptor {
@override
void onError(DioError err, ErrorInterceptorHandler handler) async {
if (err.response?.statusCode == 401) { // 인증 오류
// 토큰 갱신
final refreshToken = await _refreshToken();
if (refreshToken != null) {
// 기존 요청 복구
final retryRequest = err.requestOptions;
retryRequest.headers['Authorization'] = 'Bearer $refreshToken';
final response = await dio.request(
retryRequest.path,
options: Options(
method: retryRequest.method,
headers: retryRequest.headers,
),
data: retryRequest.data,
queryParameters: retryRequest.queryParameters,
);
return handler.resolve(response);
}
}
return handler.next(err);
}
Future<String?> _refreshToken() async {
// 토큰 갱신 로직
try {
final response = await dio.post('/auth/refresh', data: {
'refresh_token': 'YOUR_REFRESH_TOKEN',
});
return response.data['access_token'];
} catch (e) {
print('토큰 갱신 실패: $e');
return null;
}
}
}
// Interceptor 추가
dio.interceptors.add(TokenInterceptor());
4. 요청 취소
Dio는 특정 요청을 취소할 수 있는 기능을 제공합니다.
final cancelToken = CancelToken();
void fetchData() async {
try {
final response = await dio.get('/data', cancelToken: cancelToken);
print(response.data);
} catch (e) {
if (CancelToken.isCancel(e)) {
print('요청이 취소되었습니다: $e');
} else {
print('에러 발생: $e');
}
}
}
void cancelRequest() {
cancelToken.cancel('사용자가 요청을 취소했습니다.');
}
5. Multipart File 업로드
파일 업로드는 Dio의 FormData를 사용하여 간단히 처리할 수 있습니다.
void uploadFile(String filePath) async {
final file = await MultipartFile.fromFile(filePath, filename: 'upload.jpg');
final formData = FormData.fromMap({
'file': file,
'description': 'Example file upload',
});
try {
final response = await dio.post('/upload', data: formData);
print('업로드 성공: ${response.data}');
} catch (e) {
print('업로드 실패: $e');
}
}
6. 디버깅과 로깅
Dio의 LogInterceptor를 사용하면 요청과 응답을 쉽게 디버깅할 수 있습니다.
dio.interceptors.add(LogInterceptor(
request: true,
requestBody: true,
responseBody: true,
error: true,
));
7. 유용한 팁
- Retry 플러그인 사용: 네트워크 오류 시 자동으로 재시도할 수 있습니다.
import 'package:dio_retry/dio_retry.dart'; dio.interceptors.add(RetryInterceptor( dio: dio, retries: 3, retryDelays: [ Duration(seconds: 1), Duration(seconds: 2), Duration(seconds: 3), ], ));
- flutter pub add dio_retry
- BaseOptions 재활용: 여러 Dio 인스턴스에서 같은 옵션을 사용할 수 있습니다.
- 에러 핸들링 통일화: 커스텀 에러 클래스를 만들어 응답 오류를 관리하세요.
class ApiException implements Exception {
final String message;
ApiException(this.message);
@override
String toString() => 'ApiException: $message';
}
결론
Dio는 강력한 기능과 유연한 확장성을 제공하여 Flutter 앱의 네트워크 통신을 효율적으로 처리할 수 있습니다. Interceptor, Token 관리, 파일 업로드 등 다양한 기능을 활용하여 복잡한 요구사항도 간단하게 처리할 수 있습니다. 프로젝트 요구사항에 맞게 Dio를 최적화하여 사용해 보세요.
'Flutter' 카테고리의 다른 글
Flutter에서 Push Notification 심화 가이드 (0) | 2025.01.23 |
---|---|
Flutter TDD (Test-Driven Development) 심화 가이드 (0) | 2025.01.23 |
Flutter에서 SQLite 사용하기 (0) | 2025.01.21 |
Flutter 프로젝트에서 Fastlane 설정하기 (1) | 2025.01.20 |
Flutter에서의 애니메이션 제작 기법 (0) | 2025.01.20 |