본문 바로가기
카테고리 없음

📚 [Flutter 숙련] 마켓 앱 만들기 Part 05 - 소켓(Socket) 통신과 채팅

by 마이 라이프 저널 2025. 4. 22.

📚 [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 = '';
  }
}

💻 두 가상 기기로 실시간 테스트하기

  1. Flutter: Select Device → 가상 머신 2개 생성
  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" 선택 후 실행

---