Socket 통신이란 무엇일까
- 네트워크를 통해 서버, 클라이언트 양쪽에 링크를 생성 후 그 링크를 통해 데이터를 주고 받는 양방향 통신입니다.
- 서버에 임의 포트번호를 설정한 상태에서 클라이언트에서 해당 포트로 접속을 시도하면 서버와 클라이언트가 해당 포트번호로 서로 연결되어 있는 상태가 됩니다.
- 서로 연결 되어 있는 상태이므로 데이터를 서로 전달하고 받을 수 있는 상태가 됩니다.(양방향으로 연결 되어 있으니 실시간으로 데이터 전달이 가능합니다.)
- 서버와 연결되어 있는 소켓과 클라이언트에서 연결되어 있는 소켓은 같은 소켓이지만 역할이 다릅니다.
- 서버와 연결되어 있는 소켓에서는 클라이언트쪽에서 들어온 요청을 처리해주는 역할을 합니다.
- 클라이언트와 연결되어 있는 소켓에서는 서버 소켓에 요청을 해주는 역할을 합니다.
- 실시간으로 데이터를 서버와 클라이언트 간 전달해야 할 때 사용됩니다.(ex 실시간 채팅)
- 소켓 통신에는 두가지 방법이 있습니다. 볼륨이 크니 밑에 간단히 정리해 놓았습니다.
- TCP
- UDP
SocketIO란 무엇일까
- websocket 프로토콜을 지원하는 네트워킹 라이브러리입니다.
- WebSocket은 서버와 브라우저 사이에 전이중 및 지연이 낮은 채널을 제공해주는 통신 프로토콜입니다.
- 비동기 방식이며 실시간으로 간단하게 데이터를 주고받을 수 있게 만든 라이브러리입니다.
- 서버는 대표적으로 Node.js를 지원해준다고 합니다.
- SocketIO는 TCP 연결을 유지하고 있어 사용자의 배터리를 많이 소모할 수도 있다고 공식 문서에 적혀 있습니다.

TCP(스트림 소켓)
- TCP는 Transmission Control Protocol(전송 제어 프로토콜)의 약자입니다.
- 연결형 프로토콜로써 연결이 성공한 후부터 통신이 가능합니다.
- 나눠진 데이터의 손실 여부를 판단한 후 재조립하는 과정을 추적합니다.
- 쉽게 말해 패킷이 안정적으로 가지 못할 경우 캐치한 후 다시 안정적으로 보내준다고 생각하면 될 것 같습니다.
- 패킷을 수신할때마다 ACK(acknowledge)라는 별도 패킷을 재전송해주고 만약 재전송을 받지 못하면 일정 시간 후 다시 해당 패킷을 재전송하여 안정성을 높혀줍니다.
- ACK가 오지 않는 경우로는 불안정한 IP
- 받는 쪽이 ACK를 보내야 하는 것을 인지한지 못하는 상태
- ACK를 재전송해주며 체크해주므로 신뢰할 수 있는 프로토콜입니다.
- 별도의 재전송 과정을 거치므로 UDP보다 속도가 떨어지는 단점이 있습니다.
- Three Way Hand Shaking을 사용합니다.
UDP(데이터그램 소켓)
- UDP는 User Datagram Protocol의 약자입니다.
- TCP와는 다르게 비연결형 프로토콜로써 연결 없이 통신이 가능합니다.
- 메시지를 패킷으로 나누고 받는쪽에서 재조립하는 과정이 없습니다.
- 상대방과 연결이 되어있지 않고 소켓을 개설한 후 데이터를 그냥 보내준다고 생각하면 됩니다.
- 따라서 안정적이지 않은 프로토콜입니다.
- 1 ~ 5%의 데이터를 유실할 수 있다고 합니다.
- 우선 오늘 글은 TCP, UDP가 주된 내용이 아닌 SocketIO이니 간단히만 정리하고 넘어가겠습니다!
- 간단히 요약해보자면 TCP는 신뢰할 수 있지만 속도가 UDP보다는 느리고
- UDP는 TCP보다는 속도가 빠르지만 신뢰할 수 없는 특징을 가지고 있다고 생각하면 될 것 같습니다.
SLP 채팅에서 Swift SocektIO 사용 이유
- SocketIO를 사용한 SLP 프로젝 정리는 -> https://s2ung.tistory.com/31에 되어 있습니다.
- 그럼 이 프로젝트의 채팅 기능에서 단순히 서버를 연결하지 않고 SocketIO를 사용한 이유는 무엇일까요?
- 채팅은 말 그대로 실시간으로 통신이 되어야 합니다.
- 매번 데이터를 받아올 때마다 API 호출 없이 클라이언트1 <-> 서버 <-> 클라이언트2가 서로 연결되어 있어야합니다.
- http 통신은 비연결성 단방향 통신이므로 클라이언트가 서버에 응답을 요청하고 응답값을 받았을 때 연결이 끊어지게 됩니다.
- 실시간 채팅 기능을 위해선 데이터를 받아올 때마다 클라이언트가 서버에 요청을 보내는 것이 아니라(단방향)
- 서버에서도 데이터를 클라이언트가 요청한 시점 외에도 자체적으로 전달해줄 수 있어야 합니다.(양방향)
- 메시지의 데이터가 유실되면 안 되니 신뢰성이 높고 데이터가 유실되지 않는 TCP를 사용하는 것이 적합하다고 생각해서 사용하게 되었습니다.

Swift SocketIO 사용
- SLP에서 작성한 코드를 뜯어봅시다.

- 우선 SocketIOManager class를 생성해준 후 socket 통신할 URL을 선언해줍니다.
- SocketManager 타입인 manager에 통신할 url, 구성방법을 선언해줍니다.
- socketIOCleint 타입인 socket에 위에 선언한 manager의 소켓을 넣어줍니다.
- 위와 같이 defaultSocket을 사용해도 되고 직접 선언해줘도 됩니다.
- 한 어플에서 여러가지 소켓통신이 일어날 수도 있으니 소켓을 담는 룸을 나눠준다고 생각하면 될 것 같습니다.

- manager와 socket을 선언한 socket을 .on method를 통해 .connect 됐을 때 SOCKET IS CONNECTED라는 문구와 data, ack를 출력하고 changesocketid라는 이름으로 UserDefaults에 담겨 있는 id 데이터를 송신해줍니다.
- disconnect 됐을 때는 SOCKET IS DISCONNECTED라는 문구와 data, ack를 출력해줍니다.

- socket.on("chat") 메서드는 "chat"이라는 이름으로 emit된 메세지를 수신 받는 것입니다.
- 한마디로 나에게 온 채팅의 데이터들을 getDataRelay에 넣어준것입니다.
- socekt.connect() 메서드를 사용하여 설정한 주소로 소켓을 연결을 시도해주는 establishConnection이라는 함수를 선언해줍니다.
- socekt.disconnect() 메서드를 사용하여 연결을 끊어주는 closeConnection 함수를 선언해줍니다.

- 데이터를 송신받을 View의 ViewModel에 SocketIOManager() 타입의 manager을 생성해준 후


- viewDidLoad 되는 시점에 선언해둔 establishConnection을 호출해 소켓 연결을 시도해줍니다.
- 또한 viewDidDisappear되는 시점에 closeConnection을 호출해 소켓 연결을 끊어줍니다.

- 아까 getDataRelay에 담아준 채팅 정보들을 사용할 렘 혹은 구조체들에 넣어주면 끝!
'IS' 카테고리의 다른 글
iOS Swift 공식 문서 Study - Property(프로퍼티) (0) | 2023.03.14 |
---|---|
iOS Swift 공식 문서 Study - Class, Struct 구조체 (0) | 2023.03.09 |
iOS Swift - 개인 앱 출시 프로젝트 - FURY (0) | 2023.02.28 |
iOS Swift - Rx Input Output pattern (0) | 2023.02.26 |
iOS Swift 카카오 소셜 로그인(Kakao Social Login) (0) | 2023.02.13 |