네트워크 환경 체크

topics 500-모바일개발 501 Flutter 0_SubTopics/504 네트워킹
types 레퍼런스 실습
tags #flutter #network #connectivity
references www.youtube.com/watch pub.dev/packages/connectivity_plus

네트워크 환경 체크

Flutter 앱에서 네트워크 연결 상태를 체크하는 방법이다.

Why 네트워크 체크

오프라인에서도 앱이 동작해야 하거나, 네트워크 상태에 따라 다른 UI를 보여줘야 할 때 필요하다.

  • WiFi, 모바일 데이터, 연결 없음 상태 감지
  • 네트워크 끊김 시 사용자에게 알림
  • 오프라인 모드 전환

설치

# <span id="pubspecyaml"></span>pubspec.yaml
dependencies:
  connectivity_plus: ^5.0.2
flutter pub get

기본 사용법

현재 연결 상태 확인

import 'package:connectivity_plus/connectivity_plus.dart';

Future<void> checkConnectivity() async {
  final result = await Connectivity().checkConnectivity();

  switch (result) {
    case ConnectivityResult.wifi:
      print('WiFi 연결됨');
      break;
    case ConnectivityResult.mobile:
      print('모바일 데이터 연결됨');
      break;
    case ConnectivityResult.ethernet:
      print('이더넷 연결됨');
      break;
    case ConnectivityResult.none:
      print('연결 없음');
      break;
    default:
      print('알 수 없는 연결 상태');
  }
}

실시간 연결 상태 감지 (Stream)

class NetworkService {
  final Connectivity _connectivity = Connectivity();
  StreamSubscription<ConnectivityResult>? _subscription;

  void startListening(void Function(ConnectivityResult) onChanged) {
    _subscription = _connectivity.onConnectivityChanged.listen(onChanged);
  }

  void stopListening() {
    _subscription?.cancel();
  }
}

왜 Stream을 쓰냐면: 네트워크 상태는 언제든 바뀔 수 있다. 앱이 실행 중일 때 WiFi가 끊기거나 모바일 데이터로 전환될 수 있기 때문에 지속적으로 감시해야 한다.

Riverpod 연동

// network_provider.dart
@riverpod
Stream<ConnectivityResult> connectivity(ConnectivityRef ref) {
  return Connectivity().onConnectivityChanged;
}

@riverpod
class NetworkStatus extends _$NetworkStatus {
  @override
  bool build() {
    // 네트워크 상태 변화 감지
    ref.listen(connectivityProvider, (prev, next) {
      next.whenData((result) {
        state = result != ConnectivityResult.none;
      });
    });
    return true; // 초기값: 연결됨
  }
}

UI에서 사용

class HomeScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final isConnected = ref.watch(networkStatusProvider);

    return Scaffold(
      appBar: AppBar(
        title: Text('홈'),
        actions: [
          if (!isConnected)
            Icon(Icons.wifi_off, color: Colors.red),
        ],
      ),
      body: isConnected
          ? MainContent()
          : OfflineMessage(),
    );
  }
}

실제 인터넷 연결 확인

주의: connectivity_plus는 네트워크 인터페이스 상태만 확인한다. WiFi에 연결되어 있어도 실제 인터넷이 안 될 수 있다.

실제 인터넷 연결을 확인하려면:

import 'dart:io';

Future<bool> hasInternetConnection() async {
  try {
    final result = await InternetAddress.lookup('google.com');
    return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
  } on SocketException catch (_) {
    return false;
  }
}

또는 internet_connection_checker 패키지 사용:

dependencies:
  internet_connection_checker: ^1.0.0+1
import 'package:internet_connection_checker/internet_connection_checker.dart';

final bool isConnected = await InternetConnectionChecker().hasConnection;

오프라인 배너 위젯

class OfflineBanner extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final isConnected = ref.watch(networkStatusProvider);

    if (isConnected) return SizedBox.shrink();

    return MaterialBanner(
      content: Text('인터넷 연결이 없습니다'),
      leading: Icon(Icons.wifi_off),
      backgroundColor: Colors.orange,
      actions: [
        TextButton(
          onPressed: () async {
            // 재시도 로직
          },
          child: Text('재시도'),
        ),
      ],
    );
  }
}

관련 문서