[flutter] 플러터에서의 소켓 연결을 통한 파일 전송 방법

플러터(Flutter)는 크로스 플랫폼 모바일 애플리케이션 개발을 위한 프레임워크로, 다양한 기능을 제공합니다. 이 중에서도 소켓을 활용하여 파일을 전송하는 방법은 많은 사용자에게 유용한 기능입니다. 이번 포스트에서는 플러터에서 소켓 연결을 통해 파일을 전송하는 방법을 살펴보겠습니다.

1. 소켓 연결 설정하기

먼저, 소켓 연결을 설정하기 위해 socket_io_client 패키지를 사용합니다. 이 패키지는 플러터 앱에서 소켓 통신을 가능하게 해주는 도구입니다. 다음과 같이 pubspec.yaml 파일에 패키지를 추가합니다.

dependencies:
  socket_io_client: ^1.0.0

이후, 터미널에서 flutter pub get 명령어를 실행하여 패키지를 다운로드합니다.

2. 서버와의 소켓 연결 수립하기

socket_io_client 패키지를 사용하여 서버와의 소켓 연결을 수립합니다. 다음은 연결을 위한 간단한 코드 예시입니다.

import 'package:flutter/material.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;

class SocketPage extends StatefulWidget {
  @override
  _SocketPageState createState() => _SocketPageState();
}

class _SocketPageState extends State<SocketPage> {
  IO.Socket socket;

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

    socket = IO.io('https://example.com', <String, dynamic>{
      'transports': ['websocket'],
    });
    socket.connect();
  }

  @override
  void dispose() {
    socket.disconnect();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Socket Connection'),
      ),
      body: Center(
        child: Text('Socket Connection Established!'),
      ),
    );
  }
}

위의 코드는 SocketPage 클래에서 서버와의 소켓 연결을 설정하는 코드입니다. initState() 메소드에서 socket_io_client 패키지를 사용하여 서버 주소를 입력하고 소켓 연결을 설정합니다. dispose() 메소드에서는 소켓 연결을 해제합니다.

3. 파일 전송 구현하기

파일 전송을 구현하려면 서버와 클라이언트 간의 프로토콜을 정의해야 합니다. 일반적으로 프로토콜은 소켓 통신을 통해 데이터를 주고받는 방식을 설계합니다. 예를 들어, 파일을 전송할 때는 파일 크기, 파일 이름 등의 정보를 먼저 서버로 보내고, 이후에 실제 파일 데이터를 전송합니다.

파일 전송을 위한 프로토콜을 자세하게 설계하는 것은 복잡한 과정이므로 이번 포스트에서는 생략하겠습니다. 대신, socket_io_client 패키지를 사용하여 소켓 통신을 구현하는 방법을 알려드리겠습니다.

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;

class SocketPage extends StatefulWidget {
  @override
  _SocketPageState createState() => _SocketPageState();
}

class _SocketPageState extends State<SocketPage> {
  IO.Socket socket;
  File fileToSend; // 전송할 파일

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

    socket = IO.io('https://example.com', <String, dynamic>{
      'transports': ['websocket'],
    });
    socket.connect();

    // 1. 파일 전송 요청
    socket.on('requestFileTransfer', (data) {
      sendFile();
    });
  }

  @override
  void dispose() {
    socket.disconnect();
    super.dispose();
  }

  void sendFile() {
    // 2. 파일 전송 시작
    socket.emit('startFileTransfer', {
      'fileName': fileToSend.path.split('/').last,
      'fileSize': fileToSend.lengthSync(),
    });

    // 3. 파일 데이터 전송
    List<int> fileBytes = fileToSend.readAsBytesSync();
    int chunkSize = 1024; // 조각 크기
    int offset = 0;
    while (offset < fileToSend.lengthSync()) { 
      int length = chunkSize;
      if (offset + length > fileToSend.lengthSync()) {
        length = fileToSend.lengthSync() - offset;
      }

      List<int> chunk = fileBytes.sublist(offset, offset + length);
      socket.emit('fileChunk', chunk);

      offset += length;
    }

    // 4. 파일 전송 완료
    socket.emit('endFileTransfer');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Socket Connection'),
      ),
      body: Center(
        child: Text('Socket Connection Established!'),
      ),
    );
  }
}

위의 코드는 fileToSend 변수에 전송할 파일을 할당하고, 서버로부터 ‘requestFileTransfer’ 이벤트가 발생하면 sendFile() 메소드를 호출하여 파일 전송을 처리합니다. 여기서는 파일을 1KB씩 조각 내어 전송하고, 전송이 완료되면 ‘endFileTransfer’ 이벤트를 발생시킵니다.

결론

위의 코드를 참고하여 플러터에서 소켓 연결을 통해 파일을 전송할 수 있습니다. socket_io_client 패키지를 사용하여 편리하게 소켓 통신을 구현할 수 있으며, 프로토콜을 정의하여 파일 전송 기능을 구현할 수 있습니다. 플러터의 다양한 기능을 활용하여 원하는 애플리케이션을 개발해보시기 바랍니다.

참고: socket_io_client 패키지