실시간 공동 편집을 이벤트 기반의 STOMP 소켓통신으로 구현

초록·2023년 11월 23일
0
post-thumbnail

동시 편집이 필요해!

스크린샷 2023-02-11 오후 5 25 05

담배200은 매장별로 담배목록을 공유하며 재고를 입력함으로써 재고 검수를 수행하는 서비스입니다. 같은 매장에서 근무하는 근무자들끼리 같은 담배목록을 공유하는 것은 물론이고 같이 동시에 검수할 수 있으면 좋겠다 싶어서 동시편집 기능을 적용하기로 결정했습니다. 구글 스프레드시트를 동시에 편집하는 것과 비슷한 기능이라고 생각하시면 되겠습니다.

어떤 기술을 쓰지?

주된 플로우가 약 200개항목의 담배 목록에서 각 담배의 재고를 입력하거나 순서를 재조정하는 것인데, 이 앱에서는 그러한 편집이 1-2초에 한 번씩 일어납니다. 동시 편집 기능을 구현하기 위해, HTTP 통신의 polling이나 long-polling으로 구현하기엔 실시간성이 부족해지고 잦은 HTTP 통신으로 인해 서버 리소스가 많이 소모되는 문제가 있었습니다.

RPC도 고려했지만 Stomp 라이브러리를 활용한 웹소켓 통신이 현재 서비스 규모를 고려했을때 적정하고 간단해서 Stomp를 사용했습니다.

Stomp는 메시지를 FRAME이라는 형태로 구조화해 헤더와 바디, 메시지 타입을 명시할 수 있고, 자바 라이브러리를 통해 쉽게 메시지를 들여다보고 조작할 수 있습니다. 그리고 pub/sub 메커니즘을 기반으로 동작할 수 있기 때문에, 실시간 통신에 적합했습니다.

담배200에는 이렇게 적용했어요!

담배 목록은 매장단위로 공유가 되는데, 같은 담배 목록 페이지에 들어와 있으면 같은 채널을 구독하고 새로운 이벤트에 반응하도록 구현했습니다.

담배200의 경우, 담배 목록 페이지에 들어오면 아래 6가지 채널을 구독하도록 되어있습니다.

sub/store/{store_id}/cigar_num // 담배 재고 변경
sub/store/{store_id}/initialize_count // 담배 재고 빈 값으로 초기화
sub/store/{store_id}/add_cigar // 담배 추가
sub/store/{store_id}/delete_cigar // 담배 삭제
sub/store/{store_id}/modify_cigar // 담배 정보 수정
sub/store/{store_id}/reorder // 담배 순서정보 변경

메시지를 발송할 땐 아래 채널로 보냅니다.

pub/store/cigar_num
pub/store/initialize_count
pub/store/add_cigar
pub/store/delete_cigar
pub/store/modify_cigar
pub/store/reorder

예를 들어 담배 재고값을 변경하면, pub/store/cigar_num에 재고값 변경 메시지를 보내고, 그 내용이 DB에 반영되어 정상처리되면, sub/store/{store_id}/cigar_num을 구독하고 있는 사람들(같은 담배 목록페이지에 있는 사람들)에게 재고값이 변경되었다는 메시지를 보냅니다. 브라우저는 그 메시지를 받고 DOM 내용을 변경하는 것이죠.

💡 이렇게 바꿔도 좋겠어요

지금 생각해보면, 이렇게 채널을 기능별로 6가지로 나누게 되면 서버와 총 6개의 채널을 구독해야 하고 이는 일종의 커넥션을 형성하고 유지해야하는 불필요성이 존재한다고 생각됩니다. 차라리 pub/store/{store_id}, sub/store/{store_id} 이렇게 2개 채널을 통해 구독/발행하고, 기능 내용은 헤더같은 걸로 명시해서 보내도 되지 않나 싶긴 합니다.

관련 코드

📁 소켓 디렉토리
🔗 소켓 활용 컨트롤러

profile
몰입하고 성장하는 삶을 동경합니다

0개의 댓글