
📚 [Flutter 숙련] 마켓 앱 만들기 Part 05 - 소켓(Socket) 통신과 채팅
🎯 수업 목표
- 소켓 통신 개념 이해
- Flutter에서 STOMP 기반의 실시간 채팅 구현
📌 소켓 통신 개요
- HTTP: 요청-응답 후 연결 종료. 실시간 기능은 주기적 요청 필요
- WebSocket: 한 번 연결되면 종료 전까지 지속 연결
- SocketJS: HTTP 요청 후 WebSocket으로 업그레이드 (브라우저 호환성↑)
- STOMP: 텍스트 기반 메시징 프로토콜 (pub/sub 구조)
📦 사용 패키지
flutter pub add stomp_dart_client
🧩 ChatRepository에서 소켓 연결
ChatSocket connectSocket() {
StompClient? stompClient;
final chatRoomStream = StreamController(
onListen: () => stompClient?.activate(),
onCancel: () => stompClient?.deactivate(),
);
stompClient = StompClient(
config: StompConfig.sockJS(
url: '$host/ws',
webSocketConnectHeaders: {
"transports": ["websocket"],
'Authorization': bearerToken,
},
onConnect: (frame) {
stompClient?.subscribe(
destination: '/user/queue/pub',
callback: (frame) {
chatRoomStream.add(ChatRoom.fromJson(jsonDecode(frame.body!)));
},
);
},
),
);
return ChatSocket(
messageStream: chatRoomStream.stream,
sendMessage: ({required content, required roomId}) {
stompClient?.send(
destination: '/chat-socket/chat.send',
body: jsonEncode({"content": content, "roomId": roomId}),
);
},
);
}
🧠 ChatGlobalViewModel - 소켓 메시지 처리
void connectSocket() {
chatSocket = chatRepository.connectSocket();
_subscription = chatSocket!.messageStream.listen((newChat) {
handleChat(newChat);
handleChatRooms(newChat);
});
ref.onDispose(() => _subscription?.cancel());
}
void send(String content) {
final currentChat = state.currentChat;
if (currentChat != null) {
chatSocket?.sendMessage(roomId: currentChat.roomId, content: content);
}
}
📨 ChatDetailBottomSheet - 채팅 입력 구현
void onSend() {
if (controller.text.trim().isNotEmpty) {
ref.read(chatGlobalViewModel.notifier).send(controller.text);
controller.text = '';
}
}
💻 두 가상 기기로 실시간 테스트하기
- Flutter: Select Device → 가상 머신 2개 생성
.vscode/launch.json파일 작성
{
"version": "0.2.0",
"configurations": [
{
"name": "Emulator1",
"request": "launch",
"type": "dart",
"deviceId": "emulator-5554"
},
{
"name": "Emulator2",
"request": "launch",
"type": "dart",
"deviceId": "emulator-5556"
}
],
"compounds": [
{
"name": "All Devices",
"configurations": ["Emulator1", "Emulator2"]
}
]
}
👉 VSCode에서 Run and Debug 탭에서 "All Devices" 선택 후 실행
---