iOS - Socket.IO 데이터 통신

이한솔·2024년 7월 9일
0

iOS 앱개발 🍏

목록 보기
51/54

Socket.IO 데이터 통신

JavaScript로 서버를 구현하고, Swift로 클라이언트를 구현해서 Socket.IO를 이용해 데이터를 주고 받는 과정에서 엄청 고생을 했다.
그래서 서버와 클라이언트 간에 데이터를 주고받는 방법을 정리하려고 한다!



String 타입 데이터

클라이언트 (Swift)

보낼 때
String 타입의 데이터는 클라이언트에서 별다른 처리 없이 바로 전송할 수 있고, 데이터를 받을 때는 아래와 같이 처리한다.

let stringData = "한솔"
socket.emit(SocketEvent.test.rawValue, stringData)

받을 때
서버로부터 수신된 데이터가 포함된 배열인 data를 String 타입으로 타입캐스팅해서 사용한다.

socket.on("test") { data, ack in
    if let message = data[0] as? String {
        print("서버에서 받은 데이터: \(message)")
    }
}

// 서버에서 받은 데이터: 한솔

서버 (JavaScript - Node.js)

서버에서도 클라이언트로부터 String 데이터를 받아서 그대로 다시 보낼 수 있다.

socket.on('test', stringData => {
    console.log(stringData); // 한솔
    socket.emit('test', stringData);
});


Array 타입 데이터

클라이언트 (Swift)

보낼 때

let arrayData = ["한", "솔"]
socket.emit(SocketEvent.test.rawValue, arrayData) 

받을 때

socket.on("test") {data, ack in
       if let message = data[0] as? [String] {
          for i in message {
              print("서버에서 받은 데이터 :", i)
          }
       }
}

// 서버에서 받은 데이터 : 한
// 서버에서 받은 데이터 : 솔

서버 (JavaScript - Node.js)

socket.on('test', arrayData => {
  console.log(arrayData); // ['한', '솔']
  socket.emit('test', arrayData)
});


Dictionary 타입 데이터

클라이언트 (Swift)

보낼 때

let dictionaryData = ["name" : "한솔"]
socket.emit(SocketEvent.test.rawValue, dictionaryData)

받을 때

socket.on("test") { data, ack in
       if let dict = data[0] as? [String: Any],
          let name = dict["name"] as? String {
           print("서버에서 받은 데이터: \(name)")
          }
}

// 서버에서 받은 데이터: 한솔

서버 (JavaScript - Node.js)

socket.on('test', dicData => {
  console.log(dicData); // { name: '한솔' }
  socket.emit('test', dicData)
});


객체 데이터

클라이언트 (Swift)

보낼 때
클라이언트에서 객체를 서버에 전송하려면 해당 객체가 SocketData 프로토콜을 준수해야 한다. SocketData 프로토콜을 준수해야 객체가 소켓을 통해 전송 가능한 형태로 변환될 수 있다.

// Model
struct Chat: SocketData {
    let message: String
    let sender: String
    
    // SocketData 프로토콜 준수
     func socketRepresentation() -> SocketData {
         return ["message": message, "sender": sender]
     }
    
}


// 서버에 보내는 코드
let chatData = Chat(message: "안녕", sender: "한솔")
socket.emit(SocketEvent.test.rawValue, chatData)

받을 때
SocketData 프로토콜을 준수하기 때문에 객체 그대로 서버에 전송해도,서버에서 다시 받을 때는 딕셔너리 형태로 받아야한다.

socket.on(SocketEvent.test.rawValue) { data, ack in
   if let dict = data[0] as? [String: Any],
      let message = dict["message"] as? String,
      let sender = dict["sender"] as? String {
       let receivedChat = Chat(message: message, sender: sender)
       print("서버에서 받은 데이터: \(receivedChat)")
      }
}

// 서버에서 받은 데이터: Chat(message: "안녕", sender: "한솔")

서버 (JavaScript - Node.js)

클라이언트에서 전송한 객체가 SocketData 프로토콜을 준수하기 때문에 딕셔너리 형태로 전송된다. 받은 딕셔너리를 개별 변수로 사용하거나, 딕셔너리 자체를 사용할 수도 있다.

socket.on('test', (data) => {
 const { message, sender } = data;
 console.log(message, sender); // 안녕 한솔
 socket.emit('test', message) 
});


socket.on('test', (data) => {
 console.log(data); // { sender: '한솔', message: '안녕' }
 socket.emit('test', data) 
});


객체 배열 데이터

클라이언트 (Swift)

보낼 때
객체 배열을 딕셔너리 배열로 변환하여 전송해야한다.

let chatDatas = [Chat(message: "안녕", sender: "한솔"),
                         Chat(message: "빠잉", sender: "한솔")]
let chatArray = chatDatas.map { $0.socketRepresentation() }
socket.emit(SocketEvent.test.rawValue, chatArray)

받을 때
data를 [[String: Any]] 타입의 배열로 다운캐스팅한다.
각각의 요소가 [String: Any] 형식의 딕셔너리인 객체 배열을 의미한다.
다운캐스팅 한 뒤 각 딕셔너리를 Chat 객체로 변환해서 사용한다.

socket.on(SocketEvent.test.rawValue) { data, ack in
   if let array = data[0] as? [[String: Any]] {
       let receivedChats = array.map { dict -> Chat in
           let message = dict["message"] as! String
           let sender = dict["sender"] as! String
           return Chat(message: message, sender: sender)
           }
           for chat in receivedChats {
               print("서버에서 받은 데이터: \(chat.message) - \(chat.sender)")
           }
    }
}

서버에서 JSON 형식으로 보낸 데이터는 파싱해서 사용해야한다.

socket.on(SocketEvent.test.rawValue) { data, ack in
   if let jsonDataString = data[0] as? String,
      let jsonData = jsonDataString.data(using: .utf8),
      let jsonObject = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
                
      print("서버에서 받은 JSON 데이터: \(jsonObject)")
   }
}

서버 (JavaScript - Node.js)

딕셔너리 타입의 배열 자체를 보내거나, JSON 형식으로 변환해서 보낼 수 있다.

socket.on('test', (data) => {
 console.log(data); // [ { message: '안녕', sender: '한솔' }, { sender: '한솔', message: '빠잉' } ]
 socket.emit('test', data)
});
socket.on('test', (data) => {
 console.log(data); 
 // 데이터를 JSON 형식으로 변환
 const jsonData = JSON.stringify(data);
 socket.emit('test', jsonData);
});

0개의 댓글