IoT

[Flutter] StreamController 상태 관리를 통한 Memory Leak 개선

너드나무 2024. 7. 15. 18:24
반응형

서론

메모리 누수(memory leak)는 애플리케이션 성능 저하의 주요 원인 중 하나로, 사용자 경험에 악영향을 미칠 수 있습니다.
특히, 파일 다운로드와 같은 반복적인 작업에서 메모리 누수가 발생하면 시스템 자원 고갈로 인해 애플리케이션이 비정상적으로 종료될 수 있습니다.
이번 글에서는 파일 다운로드 기능에서 발생하는 메모리 누수를 해결하기 위한 개선 작업을 소개합니다.

이론적 배경

  • 메모리 누수는 사용하지 않는 메모리 공간이 해제되지 않고 계속 점유되는 현상을 말합니다.
  • 파일 다운로드 과정에서는 스트림(Stream), 컨트롤러(Controller) 등이 올바르게 해제되지 않으면 메모리 누수가 발생할 수 있습니다.
  • 이를 방지하기 위해서는 사용한 자원을 명확하게 해제하고, 적절한 메모리 관리를 수행해야 합니다.
 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com


가설

  1. 파일 다운로드 기능에서 발생하는 메모리 누수를 해결하기 위해, 다음과 같은 방법론을 적용합니다:
    1. 스트림 컨트롤러의 명확한 해제: 사용 후 스트림 컨트롤러를 명확히 해제하여 메모리 누수를 방지합니다.
    2. 상태 관리 최적화: 불필요한 상태 변경을 최소화하고, 상태 관리를 효율적으로 수행합니다.
 

StreamController class - dart:async library - Dart API

A controller with the stream it controls. This controller allows sending data, error and done events on its stream. This class can be used to create a simple stream that others can listen on, and to push events to that stream. It's possible to check whethe

api.flutter.dev


검증

  • 개선 작업을 통해 메모리 누수를 방지함으로써 파일 다운로드 기능의 안정성을 높일 수 있었습니다.
  • 스트림 컨트롤러를 명확히 해제하고, 불필요한 상태 변경을 최소화하여 메모리 사용량을 줄였습니다.
class PageFiledownUIState extends State<PageFiledownUI> {
  // StreamController를 final로 선언하여 불필요한 재할당을 방지하고, 명확히 해제합니다.
  final StreamController<TaskProgressUpdate> progressUpdateStream = StreamController();
  int cntDownload = 0;

  @override
  void initState() {
    super.initState();

    try {
      FileDownloader().updates.listen((update) {
        if (update is TaskStatusUpdate) {
          if (update.task == cont.backgroundDownloadTask) {
            cont.update();
          }
          switch (update.status) {
            case TaskStatus.complete:
              log('DOWNLOAD: Task ${update.task.taskId} success!');
              cntDownload++;
              if (cntDownload >= widget.lists.length) {
                Get.back();
              }
              cont.update();
              break;
            case TaskStatus.canceled:
              log('DOWNLOAD: Download was canceled');
              break;
            case TaskStatus.paused:
              log('DOWNLOAD: Download was paused');
              break;
            default:
              log('DOWNLOAD: Download not successful');
          }
        } else if (update is TaskProgressUpdate) {
          // 다운로드 진행 상황을 업데이트합니다.
          progressUpdateStream.add(update);
        }
      });
    } catch (e) {
      log('Error initializing file downloader: $e');
    }
  }

  @override
  void dispose() {
    // 메모리 누수를 방지하기 위해 StreamController를 명확히 해제합니다.
    progressUpdateStream.close();
    GetIt.I.resetLazySingleton(instanceName: getitID);
    super.dispose();
  }
}

결론

  1. 이번 작업을 통해 파일 다운로드 기능의 메모리 누수를 해결할 수 있었습니다.
  2. 향후에도 지속적인 모니터링과 테스트를 통해 애플리케이션의 메모리 관리를 강화해야 합니다.
  3. 추가적으로, 개발 과정에서 메모리 사용 패턴을 면밀히 분석하여 잠재적인 메모리 누수 요소를 사전에 제거하는 것이 중요합니다.
728x90
반응형