“온라인에도 즉각적이고 활발한 커뮤니티 활동을 위해”
오프라인 수업뿐 아니라 온라인에서도 빠르고 활발한 소통으로 소셜 활동을 이어 나갈 수 있도록 실시간 알림 기능을 구현했습니다.
USER는 본인이 가입한 ‘사랑방에 올라온 새 글’과 ‘본인의 글에 달린 댓글’을 실시간으로 확인할 수 있습니다.
CP는 본인의 ‘강의에 달린 리뷰’ 알림을 실시간으로 확인할 수 있습니다.
실시간 알림 기능
* CP 페이지 우측 바 ‘Notification’
* USER 페이지 우측 바 ‘알림 아이콘’
각 페이지의 우측 바를 통해 알림 목록으로 접근이 가능합니다.
* 새로운 리뷰가 등록됐을 때의 CP 알림 목록 업데이트
알림 목록에 접근하면 이전 알림을 DB에서 불러옵니다.
이후 업데이트가 있을시, CP와 USER는 새로운 알림이 등록되는 것을 실시간으로 확인할 수 있습니다.
•
알림 예시
CP | 강의 새 리뷰 알림 | ${강의명}에 새 리뷰가 등록되었습니다. : ${리뷰 내용} |
USER | 가입 사랑방 새 글 알림 | ${사랑방명}에 새 글이 등록되었습니다. : ${새 글 제목} |
사랑방 내가 쓴 글 댓글 알림 | ${글 제목}에 새 댓글이 등록되었습니다. : ${댓글 내용} |
•
알림 기능 처리 과정 (ex. 밴드 새 글 등록)
◦
가입 밴드 새 글 등록
◦
새 글의 유효성 검사
◦
밴드와 멤버 정보 조회
◦
알림 생성: 밴드 멤버의 유효성을 검사하고, 각 멤버에게 보낼 알림 객체를 생성
◦
생성 알람 DB 저장
◦
저장된 알림을 Redis Pub/Sub을 통해 채널에 발행
◦
해당 채널을 구독하는 서버는 구독된 메시지를 받아 해당 사용자들의 소켓에 알림 전달
◦
알림 목록에서 실시간으로 해당 알림 업데이트
사용 기술
•
Socket io
◦
알림 기능이 단방향이긴 하나 읽음, 안읽음 그리고 클릭 시 해당 게시물로의 연결과 같은 알림 후 상호작용을 추후 포함할 예정이기에 확장성이 높은 양방향 통신인 Socket.IO를 선택했습니다.
•
Redis pub/sub
◦
선정 이유
▪
알림 service뿐만 아니라 리뷰 서비스, 커뮤니티 서비스 등 다양한 서비스에서 데이터를 주고받는 여러 서비스 아키텍처를 사용하며, 여러 서버에 실시간으로 다른 서버에 전달하는 수평적 확장성의 필요가 있었습니다.
▪
추후 사용자에게 대규모 알림시스템과 같은 비동기 작업 처리가 필요한 기능이 개발될 수도 있는 것을 고려하여 선택하게 되었습니다.
◦
다른 대안
▪
Redis Stream
•
메시지의 내구성, 재처리, 순서 보장, 확장성과 같은 이유로 Redis Stream을 고민하였습니다.
•
특히 연결되어 있지 않는 동안 순서대로 쌓아두었다가 연결되면 실시간으로 전달 해주는 부분, 일정 시간 후 데이터가 자동으로 삭제된다는 점으로 인해 비중을 두고 고려해 보았습니다.
•
그러나 아래의 이유로 Redis pub/sub을 선택하게 되었습니다.
◦
Redis Stream의 복잡한 설정으로 인한 적용 리소스가 훨씬 많이 든다는 점.
(현실적인 시간 제약 문제)
◦
실제로 접속해있지 않은 상태에서는 순서 보장과 같은 부분이 크게 메리트가 없다는 점
◦
놓친 이전 알림은 DB로도 대체 가능하다는 점
알림 테이블 구성
알림을 받는 대상이 CP와 USER로 나뉘며, 알림의 종류도 다양(리뷰, 게시글, 댓글 등)했기 때문에 알림 테이블을 어떻게 설계하면 효율적으로 관리할 수 있을지 고민했습니다.
추후 알림 클릭 시 해당 글로 연결 등과 같은 기술을 도입할 예정이기에 관련 정보를 담고 있어야 하며, 일관성과 무결성도 유지되어야 하는 상황이었습니다.
•
문제
◦
CP와 USER
▪
CP 같은 경우 데이터베이스가 따로 빠져있기 때문에 외래키 제약조건을 걸 수가 없었습니다.
◦
다양한 알림 종류
▪
각각 연결되어야 하는 테이블이 모두 달랐습니다.
▪
해당하는 컬럼을 무한히 생성해 내기엔 확장성이 떨어지는 상황입니다.
▪
알림을 확인하면 삭제되는 일회성에 가까운 기능이기에, 해당 부분에 해당하는 테이블을 따로 생성하는 것은 낭비라고 판단했습니다.
•
선택 : 다형성 관계 테이블 생성
◦
선택 이유
▪
새로운 알림 유형이나 관련 엔티티가 추가될 때, 테이블 구조를 변경할 필요 없이 ENUM에 값을 추가하는 것만으로 확장이 가능합니다.
▪
다양한 유형의 알림과 관련 엔티티를 유연하게 관리할 수 있습니다.
▪
알림의 수신자, 유형, 관련된 엔티티가 명확하게 구분되어 관리됩니다.
◦
선택 해결 과제
▪
다형성 관계에서의 데이터 무결성을 애플리케이션 레벨에서 관리해야 하므로, 철저한 검증이 필요했습니다. → 해당 부분을 처리하는 Validator를 생성해 주었습니다.
▪
관련 엔티티를 참조할 때 다형성 필드를 사용해야 하므로, 쿼리가 복잡해질 수 있었습니다.
→ 성능 최적화를 위해 인덱스를 생성하여 관리해주었습니다.