전에도 언급했던 2023년의 내 첫 프로젝트, MirrorMe가 있다.
내가 이 프로젝트에서 무엇을 했나 PPT 자료들을 뜯어보고 혼자서 구조를 그려보니 아래와 같았다.
더 많은 기능이 있었지만, Backend에 있던 기능들 위주로 관계를 정립해봤다.
전체적인 구조는 위와 같았고, 최대한 깨끗하게 표시하려고 했으나 어렵다
들여다보고 있으니 가장 큰 구조부터 '왜 그렇게 한 걸까...?'... 의문이 들었다. 그래서 우선은 각각의 통신 방법에 대해 얘기해보려고 한다
🌊 각 서버간 통신흐름
하드웨어(라떼판다)와 Front(React), Backend(SpringBoot)가 서로 통신을 제각각으로 하고 있다.
왜 이런 구조를 갖추었을까?
✔️ 하드웨어가 Front와 WebSocket 통신을 했다
당시 하드웨어(라떼판다)는 사용자의 존재 혹은 제스쳐나 음성명령에 따라서 동적인 UI변경이 필요했다.
이때는 솔직하게 말해, 지식의 부족으로 인해 다른 선택지는 고려하지 못했다. 결과적으로 Front를 별도의 서버로 구성하고 이에 대하여 하드웨어와 Front가 WebSocket 형태로 통신하는 방법을 취했다.
지금 다시 고려해본다면, 이를 위해서 최소 두 가지의 방식이 존재했다.
1. 라떼판다 내부에 React를 프로세스를 띄우기
2. (최종결정) 외부에 React 서버를 띄우기
라떼판다 내부에 React를 프로세스로 띄웠다면
- 네트워크 연결이 없어도 된다
- 네트워크 지연이 없으므로 UI 반응이 더욱 빠르다
- 미러의 소프트웨어를 따로 업데이트 해야하므로 관리가 복잡하다
- 내부 PC의 성능에 따라 UI의 복잡성과 성능이 제한된다 (하지만 라떼판다면 충분했을 것 같다)
라떼판다 외부에 React를 별도 서버로 띄우면
- 모든 UI 변경사항이 한 서버에서 관리되므로 업데이트와 유지보수가 용이하다
- 동일한 서버를 여러 스마트 미러에서 사용할 수 있는 확장성을 갖춘다
- 서버와의 연결이 끊어지면 미러가 작동하지 않는다
- 네트워크 지연 발생 시 UI 반응이 느려진다
초기 기획으로는 멀티 디스플레이 스마트미러를 생각하기도 했으니, 라뗴판다 외부에 React 서버를 띄운 것은 적합했던 것 같다.
✔️ 하드웨어가 Backend와 HTTP 통신을 했다
반대로 말해, 하드웨어는 Backend와 Socket 통신을 하지 않았다.
그렇다고 실시간 통신이 필요하지 않았던 것은 아니다. 핵심 기능 중 하나였던 '영상 메시지' 기능은 영상을 하드웨어 측에 저장하고 이를 타 서버에 옮기는 작업이 필요했다.
요구사항 중 하나는 A 사용자가 B에게 '영상 메시지'를 촬영한다면, 그 데이터를 확인하여 B에게 영상메시지가 왔음을 알려줘야한다
이는 Socket을 통해서 필요시에 작업이 들어가는 것이 아니라 CronTab을 통해 Short Polling 방식으로 데이터의 유무를 판별하여 Docker Volume을 통해 데이터를 이동시켰다.
거의 한 1분~3분 간격으로 확인작업을 하고 있었으니, 하루에 사용자당 많아봤자 10번이 되지 않을 영상메시지 기능 때문에 불필요한 작업이 계속 일어나고 있었다고 판단된다.
다시 생각한다면, MQTT혹은 Socket 방식으로 취하는 것이 옳다고 생각한다.
혹은 AWS S3와 같은 스토리지에 영상 메시지를 업로드 시키는 것이 좋았을 것이다.
MQTT 방식을 취한다면
1. 어딘가(SpringBoot든.. 클라우드든.. )에 Mosquitto와 같은 브로커를 설치하고 구성한다 (메시지 전달 역할)
2. 라떼판다와 SpringBoot에서 MQTT 클라이언트를 설정하여 브로커에 연결 후, 메시지 발행 혹은 구독을 한다
3. 사용자가 라떼판다를 통해 영상 메시지 촬영 시, 해당 메시지를 MQTT 브로커에 발행한다
4. Spring Boot가 해당 토픽을 구독하고 있었으므로, 해당 메시지를 즉시 수신 후 필요한 비즈니스 로직을 수행하고 처리한다
WebSocket 방식을 취한다면
1. SpringBoot 내에서 WebSocket 서버를 설정한다
2. 라떼판다에서 WebSocket Client 설정을 한 후, Spring Boot 서버에 연결한다
3. 사용자가 라떼판다를 통해 영상 메시지 촬영 시, WebSocket을 통해 해당 메시지를 Spring Boot 서버로 전송한다
4. Spring Boot가 해당 메시지 수신 후 필요한 비즈니스 로직을 수행하고 처리한다
지금 생각하면.. 라떼판다에서 AWS S3로 영상을 업로드시키고, 해당 url 정보와 타깃 사용자의 정보를 WebSocket과 같은 방법으로 넘기도록 했을 것 같다. 그러나, 더 생각하면 AWS S3 접근의 보안을 위해 Spring Boot와 같은 별도의 게이트 웨이가 존재하는 것이 더 옳을 것 같다.