개발놀이터

취업한지 만으로 1년을 되돌아보다 본문

기타/회고

취업한지 만으로 1년을 되돌아보다

마늘냄새폴폴 2025. 2. 28. 21:32

작년 2월 14일에 취업하고 현재 회사에서 1년을 채운 뒤 오늘 연봉협상을 마쳐 본격적으로 2년차가 시작되었습니다. 회사에서 1년동안 했던 일들 회고해보도록 하겠습니다. 

 

성능 개선

회사에서는 WebRTC를 이용한 비대면 평가 시스템을 개발하고 있습니다. 제가 투입되었을 당시 오픈소스인 Openvidu를 이용해서 만들어져있었는데 Openvidu가 Kurento 미디어 서버를 기반으로 만들었기 때문에 WebRTC만 사용하는 저희 서비스 입장에선 썩 좋은 선택지는 아니었습니다. 

 

이것도 추후에 포스팅을 하겠지만 WebRTC에 특화된 미디어 서버인 Mediasoup가 있어서 이를 이용해서 서비스를 마이그레이션 했습니다. 그러면서 기능도 추가로 개발하고 프로세스도 다듬으면서 기존 Openvidu에 비해 성능이 많이 향상됐습니다. 

 

저희 서비스는 한명당 세개의 미디어 스트림을 전송하게 되는데 (웹캠, 모바일, 화면공유) 그렇기에 20명이 들어오면 사실 60명이 들어온 것과 비슷한 서버 부하가 생깁니다. 

 

그래서 20명 남짓한 사용자가 들어오니 4코어 컴퓨터가 꽉차버리게 되었습니다. 여기서 영상을 녹화하기 시작하면 20명도 들어오지 못하는 상황이었죠. 

 

이걸 Mediasoup을 기반으로 만든 오픈소스 Edumeet을 이용해서 마이그레이션을 진행했고 그 결과 80명까지 접속가능하게 (실질적으로 240명의 서버 부하) 변경했습니다. 

 

하지만! 여기서 끝나지 않고 성능 개선이 이루어졌습니다. 왜냐하면 4코어 컴퓨터에 80명이면 사실 서비스할만큼 고도화되진 않은 것이라.. 

 

다음 단계

저희 서비스는 일반적인 WebRTC의 흐름을 타지 않습니다. 왜냐하면 수험생은 미디어 스트림을 송신하기만 하고, 관리자는 미디어 스트림을 수신하기만 하기 때문이죠. 

 

하지만 기본적으로 Edumeet, Openvidu 모두 SFU방식으로 연결이 되어있는데 이는 송신과 수신이 쌍으로 이루어 미디어 스트림을 주고 받습니다. 

 

즉, 저희 서비스에서는 수험생은 송신만, 관리자는 수신만 하지만 양쪽으로 미디어 스트림이 전송되고 받고 있었던 것이죠. 

 

때문에 송신만, 수신만 하도록 컨트롤할 수는 없을까? 하는 생각에서 시작되었습니다. 이를 줄이면 트래픽 비용이 절감되지 않을까? 하는 생각이었죠.

 

Mediasoup은 영상을 생성하는 Producer (생산자) 가 어떤 Consumer (소비자) 로 갈 것인지 Router에 적어둡니다. Consumer를 만들고 난 뒤 본격적으로 스트림을 받을 준비를 하는 것이 바로 resume()이라는 메서드를 호출할 때입니다. 

 

이 부분을 찾아서 관리자의 경우에만 resume()을 호출했습니다. 그랬더니 트래픽 비용은 그대로였지만 서버 성능이 너무 좋아져버렸습니다. 간단하게 예시로 설명해보겠습니다. 

 

줌 회의에서 30명이 들어와있는 상황을 가정해봅시다. 

 

화면에 30개의 영상이 보이는데 나를 제외한 29명과 연결되었다는 것을 알 수 있죠. 하지만 그 옆사람도 29명, 옆사람도 29명 29명..29명.. 즉 30개의 연결이 아닌 약 900개의 연결이 된 것입니다. 

 

이 상황에서 관리자는 한명, 수험생은 29명이라고 가정해보면 관리자는 영상을 다 받아야하지만 수험생은 영상을 보내기만 하면 됩니다. 

 

즉, 수험생 화면에서는 자기 자신만 영상이 보이고 나머지 29명의 영상은 보이지 않는것이죠. 반대로 관리자는 모든 영상이 다 보여야하죠. 이렇게 되면 연결이 900개에서 수험생이 보내는 연결 30개, 관리자가 받는 연결 30개 이렇게 60개만 연결이 되고 나머지 840개의 연결에 대한 CPU연산이 필요하지 않게 되는 것이죠. 

 

그래서 서버 성능이 비약적으로 증가하게 된것입니다. 

 

앞으로는..

현재 Edumeet은 클라이언트, 시그널링 서버, 미디어 서버 이렇게 세개로 이루어져 있습니다. 

 

지금의 상황은 하나의 시그널링 서버와 여러개의 미디어 서버가 연결될 수 있습니다. 하지만 만약 사용자가 많아져 시그널링 서버가 많아지면 어떤 브라우저가 어떤 미디어 서버와 연결되어 있는지 시그널링 서버들이 상태를 관리해야합니다. 

 

이런 문제는 서버가 여러대로 늘어나면 생기는 자연스러운 현상입니다. 스프링 부트에서도 세션으로 인증을 관리하면 서버가 늘어나는 경우 Redis를 이용해서 세션서버를 따로 두는 것이 일반적이죠. 

 

시그널링 서버의 상태를 관리하기 위해 Redis의 Pub/Sub 메세징을 이용하는 방법을 떠올릴 수 있을 것 같습니다. 만약 이 방법을 사용하지 않는다면 시그널링 서버간 웹소켓 통신이 떠오르는데 이는 시그널링 서버의 많은 부하가 예상되어 부하를 분산시키기 위해서라도 Redis를 이용하는 것이 좋을 것 같습니다. 

 

또한, 생각해야 하는 점이 바로 scale in을 하는 경우 미디어 서버의 개수가 줄어들게 되는데 그 때 미디어 서버에 연결되어있던 WebRTC들을 남아있을 미디어 서버로 전달해줘야합니다. 저는 이게 Graceful Shutdown처럼 보여서 Graceful Shutdown이라고 부르긴 하는데 이 점을 생각해봐야할 것 같습니다. 

 

마치며..

이제 2년차인만큼 또 열심히 다니면서 성장해보도록 하겠습니다! 포스팅도 열심히 쓰면서 다시 한번 앞으로 나아가보겠습니다. 그럼 다음 포스팅에서 뵐게요!