[flutter] get_it를 사용하여 플러터 앱에서 파일 업로드와 다운로드를 어떻게 처리하는가?

이번 블로그 포스트에서는 플러터 앱에서 파일 업로드와 다운로드를 처리하는 방법에 대해 알아보겠습니다. 우리는 get_it 패키지를 사용하여 의존성 주입을 구현할 것입니다. 의존성 주입을 사용하면 코드의 유연성과 재사용성을 개선할 수 있습니다.

get_it 패키지 설정하기

먼저, get_it 패키지를 프로젝트에 추가해야 합니다. 이를 위해 pubspec.yaml 파일을 열고 get_it: ^x.x.x와 같은 형식으로 의존성을 추가합니다. 그런 다음 터미널에서 flutter pub get 명령을 실행하여 패키지를 가져옵니다.

의존성 주입 클래스 생성하기

의존성 주입을 사용하기 위해 DependencyInjector 클래스를 생성하겠습니다. 이 클래스는 앱의 시작 시점에서 한 번만 초기화됩니다.

import 'package:get_it/get_it.dart';

class DependencyInjector {
  static final GetIt injector = GetIt.instance;
  
  static void init() {
    injector.registerSingleton<FileRepository>(FileRepositoryImpl());
  }
}

위의 코드에서 FileRepository는 파일 업로드와 다운로드를 처리하는 인터페이스입니다. FileRepositoryImpl은 이 인터페이스의 구현체입니다. 여기서는 단순히 registerSingleton 메서드를 사용하여 의존성을 등록합니다.

파일 업로드 및 다운로드 구현하기

의존성 주입을 설정했으므로 이제 파일 업로드와 다운로드를 처리하는 클래스를 작성할 수 있습니다. 아래 예제에서는 FileService 클래스를 구현하였습니다.

import 'dart:io';

import 'package:path_provider/path_provider.dart';
import 'package:dio/dio.dart';

abstract class FileRepository {
  Future<String> uploadFile(File file);
  Future<File> downloadFile(String url);
}

class FileRepositoryImpl extends FileRepository {
  final Dio _dio = Dio();

  @override
  Future<String> uploadFile(File file) async {
    String fileName = file.path.split('/').last;

    FormData formData = FormData.fromMap({
      "file": await MultipartFile.fromFile(file.path, filename: fileName),
    });

    Response response = await _dio.post(
      "https://example.com/upload",
      data: formData,
    );

    return response.data['url'];
  }

  @override
  Future<File> downloadFile(String url) async {
    Directory directory = await getTemporaryDirectory();
    String filePath = '${directory.path}/${url.split('/').last}';

    await _dio.download(url, filePath);

    return File(filePath);
  }
}

위의 코드에서 uploadFile 메서드는 주어진 파일을 서버로 업로드하고 업로드된 파일의 URL을 반환합니다. downloadFile 메서드는 주어진 URL로부터 파일을 다운로드하고 파일 객체를 반환합니다.

파일 업로드 및 다운로드 사용하기

이제 파일 업로드와 다운로드를 사용하는 방법을 알아보겠습니다.

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

class FileUploader extends StatefulWidget {
  @override
  _FileUploaderState createState() => _FileUploaderState();
}

class _FileUploaderState extends State<FileUploader> {
  final FileRepository _fileRepository = DependencyInjector.injector<FileRepository>();

  File _selectedFile;

  Future<void> _uploadFile() async {
    if (_selectedFile == null) return;

    String url = await _fileRepository.uploadFile(_selectedFile);

    // 업로드된 파일의 URL 사용하기
  }

  Future<void> _downloadFile() async {
    String url = "https://example.com/sample-file.jpg"; // 다운로드할 파일의 URL

    File downloadedFile = await _fileRepository.downloadFile(url);

    // 다운로드된 파일 사용하기
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("File Uploader"),
      ),
      body: Column(
        children: [
          RaisedButton(
            onPressed: () async {
              File file = await ImagePicker.pickImage(source: ImageSource.gallery);
              setState(() {
                _selectedFile = file;
              });
            },
            child: Text("Select File"),
          ),
          RaisedButton(
            onPressed: _selectedFile != null ? _uploadFile : null,
            child: Text("Upload File"),
          ),
          RaisedButton(
            onPressed: _downloadFile,
            child: Text("Download File"),
          ),
        ],
      ),
    );
  }
}

위의 예제에서는 _uploadFile 메서드를 호출하여 선택한 파일을 업로드하고 _downloadFile 메서드를 호출하여 파일을 다운로드합니다. 파일의 처리는 FileRepository 클래스에서 수행되며, 의존성 주입을 통해 이를 구현체로 주입받습니다.

결론

이제 get_it 패키지를 사용하여 플러터 앱에서 파일 업로드와 다운로드를 처리하는 방법을 알아보았습니다. 의존성 주입을 통해 코드를 더 유연하고 재사용 가능하게 만들 수 있습니다.