실시간 통신
Flutter 실시간 통신 (실시간 데이터 전송 및 처리)을 구현하는 방법을 단계별로 설명합니다.
실시간 통신이란?
실시간 통신은 클라이언트와 서버 간의 데이터를 즉시 송수신할 수 있도록 하는 기술입니다. 예를 들어, 실시간 채팅, 주식 가격 업데이트, 게임 데이터 동기화 등에 사용됩니다.
WebSocket의 주요 메서드와 사용법
WebSocket은 클라이언트와 서버 간 실시간 통신을 가능하게 합니다. 이 문서에서는 WebSocket과 관련된 주요 메서드 및 이벤트를 설명합니다. on, emit, broadcast를 중심으로 다룹니다.
WebSocket 주요 메서드
WebSocket은 기본적으로 다음과 같은 메서드와 이벤트를 제공합니다:
on(event, callback)
- 특정 이벤트가 발생했을 때 실행되는 콜백 함수를 정의합니다.
- 서버 및 클라이언트 모두에서 사용할 수 있습니다.
예제 (Node.js 서버)
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', (socket) => {
console.log('클라이언트가 연결되었습니다.');
socket.on('message', (message) => {
console.log(`받은 메시지: ${message}`);
});
socket.on('close', () => {
console.log('클라이언트가 연결을 종료했습니다.');
});
});emit(event, data)
- 특정 이벤트와 데이터를 전송합니다. 이 기능은 기본 WebSocket 프로토콜에 직접적으로 존재하지 않지만, Socket.IO와 같은 라이브러리에서 자주 사용됩니다.
예제 (Socket.IO 서버)
io.on('connection', (socket) => {
console.log('사용자가 연결되었습니다.');
socket.emit('welcome', '서버에서 보낸 환영 메시지');
socket.on('customEvent', (data) => {
console.log(`클라이언트에서 받은 데이터: ${data}`);
});
});Broadcast(브로드캐스트)
broadcast는 메시지를 모든 연결된 클라이언트에게 전송하는 방법입니다.
WebSocket에서 브로드캐스트 구현
기본 WebSocket에서는 브로드캐스트 메서드가 없습니다. 그러나 서버에 연결된 모든 클라이언트를 순회하며 메시지를 전송할 수 있습니다.
예제
server.on('connection', (socket) => {
socket.on('message', (message) => {
server.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(`브로드캐스트 메시지: ${message}`);
}
});
});
});Socket.IO에서 브로드캐스트
Socket.IO는 기본적으로 broadcast 메서드를 제공합니다.
예제
io.on('connection', (socket) => {
socket.on('message', (msg) => {
socket.broadcast.emit('broadcastMessage', `브로드캐스트: ${msg}`);
});
});WebSocket의 추가 메서드 및 이벤트
send(data)
- 서버 또는 클라이언트가 데이터를 전송합니다.
- 데이터는 문자열 또는 바이너리 형식으로 전송할 수 있습니다.
예제
socket.send('안녕하세요!');close()
- 연결을 닫습니다.
- 서버와 클라이언트 모두에서 사용 가능합니다.
예제
socket.close();error
- 에러가 발생했을 때 실행되는 이벤트입니다.
예제
socket.on('error', (error) => {
console.error('에러 발생:', error);
});WebSocket: 실시간 통신
WebSocket은 양방향 통신을 가능하게 하는 표준 프로토콜입니다. Flutter에서 web_socket_channel 라이브러리를 사용하여 간단히 구현할 수 있습니다.
Flutter 프로젝트 생성
- Flutter 설치가 완료되었다면 아래 명령어로 새 프로젝트를 생성합니다.
flutter create realtime_communication
cd realtime_communication- 프로젝트를 열고
pubspec.yaml파일에 다음 의존성을 추가합니다.
dependencies:
web_socket_channel: ^2.3.0- 의존성을 설치합니다.
flutter pub getFlutter 클라이언트 코드 작성
Flutter 클라이언트는 서버와 WebSocket으로 연결하여 메시지를 주고받습니다.
lib/main.dart 파일을 다음 코드로 교체하세요.
import 'package:flutter/material.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: WebSocketExample(),
);
}
}
class WebSocketExample extends StatefulWidget {
@override
_WebSocketExampleState createState() => _WebSocketExampleState();
}
class _WebSocketExampleState extends State<WebSocketExample> {
final WebSocketChannel channel =
WebSocketChannel.connect(Uri.parse('ws://localhost:8080'));
final TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('WebSocket Example')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
StreamBuilder(
stream: channel.stream,
builder: (context, snapshot) {
return Text(snapshot.hasData ? '${snapshot.data}' : 'No messages yet');
},
),
TextField(
controller: _controller,
decoration: InputDecoration(labelText: 'Send a message'),
),
ElevatedButton(
onPressed: () {
channel.sink.add(_controller.text);
_controller.clear();
},
child: Text('Send'),
),
],
),
),
);
}
@override
void dispose() {
channel.sink.close();
super.dispose();
}
}Flutter 애플리케이션을 실행합니다.
flutter runNode.js 서버 작성
Node.js가 설치되어 있다면 프로젝트 폴더에 새로운 Node.js 프로젝트를 생성합니다.
mkdir websocket_server
cd websocket_server
npm init -y
npm install wsserver.js 파일을 생성하고 다음 코드를 추가합니다.
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', (socket) => {
console.log('Client connected');
socket.on('message', (message) => {
console.log(`Received: ${message}`);
server.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(`Echo: ${message}`);
}
});
});
socket.on('close', () => {
console.log('Client disconnected');
});
});
console.log('WebSocket server is running on ws://localhost:8080');서버를 실행합니다.
node server.jsFlutter 앱과 Node.js 서버를 동시에 실행하여 메시지를 주고받아 보세요.
Socket.IO를 이용한 실시간 통신
Socket.IO는 WebSocket보다 더 많은 기능을 제공합니다. 예를 들어, 연결 복구 및 이벤트 기반 메시징을 지원합니다.
의존성 추가
dependencies:
socket_io_client: ^2.0.0Flutter 클라이언트 코드 작성
import 'package:socket_io_client/socket_io_client.dart' as IO;
void main() {
final socket = IO.io('http://localhost:3000', IO.OptionBuilder()
.setTransports(['websocket'])
.build());
socket.onConnect((_) {
print('Connected');
socket.emit('message', 'Hello Server!');
});
socket.on('response', (data) {
print('Received: $data');
});
socket.onDisconnect((_) => print('Disconnected'));
}Node.js 서버 작성
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server);
io.on('connection', (socket) => {
console.log('A user connected');
socket.on('message', (msg) => {
console.log(`Message received: ${msg}`);
io.emit('response', `Server Echo: ${msg}`);
});
socket.on('disconnect', () => {
console.log('A user disconnected');
});
});
server.listen(3000, () => {
console.log('Socket.IO server running on http://localhost:3000');
});WebSocket과 Socket.IO의 차이점
| 특징 | WebSocket | Socket.IO |
|---|---|---|
| 기술 | 기본 프로토콜 | WebSocket 기반 라이브러리 |
| 브라우저 지원 | 제한적 | 광범위 |
| Fallback 지원 | 없음 | Long Polling 지원 |
| 기능 | 기본 메시징 | 이벤트 기반 메시징, 재연결 |