본문 바로가기

iOS

소켓통신과 Sendbird

swift와 RestAPI 글에서 마지막 부분에 etc.에 가볍게 socketAPI에 대해서 소개하였었다.

그리고 사실 그것은 전부 이 글을 쓰기위한 복선이었다!

전의 이미지 캐싱 글에서도 언급했듯이 프로젝트를 만들면서 공부할 목적으로 RxSwift와 RxCocoa를 이용하여 데이팅 앱을 만들고 있다.

그 중심 기능은 두 가지로 스와이프로 유저들을 like, pass 할 수 있고 채팅까지만 구현하는 간단한(사실 안 간단했다) 프로젝트를 기획했다.

사실 필자도 채팅 구현을 위해서는 소켓통신을 이용해야한다는 사실은 알고 있었지만, 그 이유가 서버와 클라이언트 사이에 양방향 통신이 가능하기 때문이라는 정도로만 알고 있고, 꼭 socket 통신을 이용해야만 하는건지, 다른 방식이 뭐가 있는 지에 대해서는 전혀 몰랐기 때문에 현재까지 공부한 내용과 나의 소켓통신 실패담을 공유하고 Sendbird를 소개하고자 한다.

 

1. 소켓통신? 양방향 통신?

시작에 앞서 swift와 RestAPI 블로그 글에서 다루었던 내용을 읽고 들어오면 좋을 것이라고 생각한다.

위 블로그 내용을 짧게 요약한 내용을 소개하자면, api는 프로그램들(서버와 클라이언트) 사이의 통신(법)이라고 소개하였다. 그 통신법에는 여러 종류가 있는데 SocketAPI 혹은 소켓통신은 그 중 한 방법으로 양방향 통신을 지원하여 클라이언트와 서버 간에 데이터를 주고받을 수 있다. 그런데 여기서 의문점이 있을 것이다.
**RestAPI가 HTTP를 기반으로 한 단방향통신(이전의 종업원, 직원 비유 참고바람)이라고 하는데 클라이언트와 서버 간에 데이터를 주고받는 것은 똑같지 않는가? 왜 RestAPI는 양방향 통신이라고 불리지 않는가?**

이 또한 이전 글을 읽고 오면 이해가 쉬울 것인데, RestAPI의 REST 아키텍쳐의 조건 중에 하나는 stateless함이다. 즉 클라이언트와 서버 간의 세션 상태를 유지하지 않는다는 것이다. 따라서 클라이언트는 각 요청에서 필요한 모든 정보를 포함하여 서버에게 보내야 한다.

하지만 SocketAPI는 클라이언트와 서버 모두 독립적으로 데이터를 주고받을 수 있다. 즉 종업원의 비유같이 고객이 요청을 해야만 응답을 하는 형태가 아니라는 것이다.

 

****근데 왜 Socket이라고 명명하였을까?(개인적인 의견)

socket이라는 영단어는 사실 한국어로도 소켓이라고 번역이 되는데, 프라모델 조립이나 제작에 대한 취미가 있는 사람들은 자주 들어봤을 것이다. 소켓은 어떤부분과 이어질 수 있도록 확장되어있는 "구멍" 혹은 "연결부"를 의미한다. 따라서 이 소켓이라는 구멍을 통해서 밖으로 데이터를 내보내거나 밖에서 데이터를 소켓 안으로 빨아들일 수 있기 때문에 Socket이라고 불리는 것 같다.

2. TCP/IP? WebSocket? SocketIO?

이제 소켓과 소켓통신이 뭔지는 알겠어서 더 공부하려고 보면 웹소켓과 TCP/IP 소켓 이렇게 두 통신방법이 나올 것이고, 채팅기능을 구현하기 위해서는 SocketIO라는 것을 이용하게 될 것이다. 각각이 무엇을 의미하는 지에 대해 알아보자.

 

-  TCP/IP

이 블로그 자체가 필자가 이해하지 못한 내용을 억지로 복사해서 글을 작성하는 것을 극도로 경계하기 때문에, 설명이 많이 빈약할 수 있다는 점을 인지해주길 부탁드립니다.
TCP/IP 소켓은 IP통신을 기반으로 하여 TCP 송수신 방식을 사용하는 통신방법이라고 한다. IP는 우리가 아는 그 IP이고, TCP는 Traffic Control Protocol의 약자로 네트워크 상에서 데이터를 안정적으로 전송하기 위한 프로토콜이라고 한다. 그 안정성을 위해  연결을 유지하고, 순서가 굉장히 중요하고(순서를 중시하기에, 멀리 떨어진 위치의 코드가 먼저 실행되어야한다고 하면 오버헤드(추가적으로 메모리, 자원이 소모되는 현상)가 발생할수도 있다), 흐름을 제어(Traffic Control!!)한다고 한다. 반대로 UDP라는 다른 송수신 방식이 있는데 그것은 비연결을 지향하며, 확실한 전달이 보장되지 않는다고 한다.


- WebSocket

위의 내용과 같이, TCP/IP 소켓은 일반적으로 클라이언트와 서버 간에 유지되는 연결을 계속 유지해야 한다는 단점이 있다. 따라서 지속적인 연결을 하고 양방향 통신을 하는데 위와 같은 리소스 사용 및 비용에 대한 단점들을 해소하기 위해 나온 것이 웹소켓이다. 

웹 소켓은 TCP/IP가 여러개의 연결을 유지하는 것과 달리 하나의 연결만 유지하고, TCP/IP가 IP프로토콜을 따르기에 큰 헤더정보를 따르다 보면 오버헤드가 발생하는 것과 달리, 웹소켓은 처음엔 HTTP를 통해 연결을 하고 그 다음에 웹소켓을 사용하기 때문에 헤더의 크기가 상대적으로 작다고 합니다.(이 부분은 사실 제가 경험할 수 있는 부분은 아니기에 그냥 참고만 해주시길 바랍니다)

 

- SocketIO

위 설명과 같이, 그렇게 좋다는 웹소켓을 포함한 다양한 방식의 실시간 웹기술을 쉽게 사용하도록 만들어놓은 api이다!

다음은 데이팅 앱 프로젝트에 만든 SocketIOManager 파일 안에 있는 코드 중의 일부이다. establishConnection() 과 closeConnection() 함수는 각각 소켓을 커넥트하고 디스커넥트하는 함수를 채팅이라는 탭에 들어가고 나올때 불러주며 지속적으로 연결되는 상태에 들어가고 나오게 해준다. 위의 개념만 보았을 때는 상당히 복잡해보이고 어려워 보이는 과정들을 위와같은 아주 간단한 코드들(socket.connect(), socket.disconnect())로 구현할 수 있다.

 

3. 그렇다면 채팅을 위해서는 꼭 socket통신이 필요한것인가?

사실, CS공부를 하다보면 위와 같은 부류의 질문에 대한 대답이 YES였던 적이 없기에 이미 정답은 알고 있었다ㅎㅎ
하지만 공부 결과, 그렇지는 않은데 그렇다고 말 할수 있겠다(개인적인 의견입니다). HTTP 통신에서도 Polling이라는 기술로 실시간이 아닌데 마치 실시간인 것처럼 구현을 해왔다고 한다. 근데 실시간이고 효율적인 통신 방법으로 웹소켓을 쓰는 것이 채팅에 적합하다고 한다.

 

4. 소켓통신 실패담과 sendbird

(소켓통신 실패담을 가장한 커스텀테이블 뷰 실패담...)

Firesbase로 Auth와 Storage를 다 만들고 이제 채팅만 구현하면 된다 싶어서, 블로그를 참고하여 (https://nsios.tistory.com/28) Socket 서버도 만들고채팅을 보여줄 테이블 뷰를 Codebase로도 만들어보고(너무 안되서 갈아엎어서 코드는 없다...ㅋ),
Storyboard로도 만들어보고

계속 빌드해 보았지만, 나에게 돌아오는 것은 앱이 터지는 일 뿐이었다.... 약 3~4일이 넘는 시간동안 이것을 붙잡고 있으니, 조금은 현실적인 길로 들어가기로 타협하였다....ㅎ

Sendbird는 웹소켓 기반의 실시간 채팅을 지원해주는 SDK인데 다양한 플랫폼과 통합이 쉽다고 하고(실제로 유투브를 들어가면 웹, 앱 모든 플랫폼에서의 구현예제를 소개한다), 다양한 기능 + 커스터마이징을 지원한다고 한다.

구현은 위 링크에 있는 차례를 그대로 밟았기 때문에 생략하겠다.... 사실 sendbird가 아주 편리하고 좋은것도 알겠는데 socketIO를 통한 구현에 대한 미련이 아직 사라지지 않는다...