Skip to content

redis를 통해 데이터베이스 쿼리 줄이기

ez edited this page Nov 26, 2024 · 8 revisions

현재 프로젝트 구조

현재 저희 프로젝트에서는 실시간 동시 편집을 구현하기 위해 yjs라는 라이브러리와 socket.io를 사용 중입니다.

자세한 설명

아래 그림에서 볼 수 있듯 yjs 라이브러리는 충돌 문제를 해결해주고 클라이언트마다 YDoc이라는 Document를 공유하여 실시간 문서 편집을 구현할 수 있습니다.

image

yjs는 내부적으로 CRDT라는 알고리즘을 사용합니다.

CRDT 알고리즘은 OT 알고리즘과 달리 중앙 서버의 부하를 줄이고 클라이언트 간 P2P 연결을 통해 실시간 동시 편집을 할 수 있게 해주는 알고리즘입니다.

하지만 저희 프로젝트의 경우 문서의 내용을 데이터베이스에 저장하는 과정이 필요했습니다.

다행히 yjs 라이브러리와 socket.io를 사용하면 client들이 공유하는 YDoc이라는 Document를 서버와 함께 사용할 수 있습니다.

즉, 클라이언트끼리 동시 편집을 진행하여 YDoc의 변경 사항이 발생하면 서버에서 이를 감지하여 데이터베이스에 저장할 수 있습니다.

가장 단순하게 구현을 한다면 YDoc의 변경 사항이 발생할 때마다 변경 사항을 데이터베이스에 반영하면 됩니다.

변경 사항이 발생할 때마다 데이터베이스에 반영한다면?

변경 사항이 발생할 때마다 데이터베이스에 반영한다면 당연하게도 데이터베이스에 부하가 많이 발생합니다.

특히 문서 편집 특성 상 타이핑이 발생할 때마다 변경 사항이 발생합니다.

예를 들어 100명의 사람이 한 문서에서 한 번씩 타이핑 한다면 총 100개의 갱신 쿼리가 발생하게 됩니다.

하지만 문서의 특성을 살펴본다면 모든 변경 사항에 대해서 데이터베이스에 갱신을 할 필요는 없습니다.

아래 그림처럼 여러 번의 변경이 발생했다면 가장 마지막에 있는 값만 저장해도 충분합니다.

image

물론 redo나 undo 기능을 사용한다면 변경 내역이 필요할지도 모릅니다.

하지만 yjs 라이브러리 자체에서 redo나 undo 기능을 제공해주고 있고 클라이언트에서 redo나 undo가 발생하면 서버 입장에서는 Document가 변경했다고 인식하기 때문에 굳이 변경 내역을 저장할 필요는 없습니다.

즉, 모든 변경 사항을 반영할 필요 없이 주기적으로 최신 문서 내용만 갱신하면 됩니다.

주기적인 영속화

그렇다면 어떻게하면 주기적으로 데이터베이스에 영속화 할 수 있을까요?

가장 단순한 방식을 생각하면 자바스크립트의 setInterval 함수를 사용할 수 있을 것 같습니다.

1. setInterval로 주기적인 영속화

setInterval을 통해 주기적으로 Y Document의 모든 값을 가져와서 데이터베이스에 저장하는 방식입니다.

image

하지만 다음과 같은 문제점이 존재합니다.

첫 번째, 변경 사항이 없는 문서도 갱신이 발생합니다.

저희 프로젝트는 다양한 문서가 존재할 수 있기 때문에 변경 사항이 없는 문서의 갱신이 발생한다면 굉장히 비효율적인 작업이 됩니다.

image

그렇다고 매번 문서마다 변경 사항 여부를 판단해서 데이터베이스에 저장한다면 역시 비효율적인 작업이 될 것이라고 생각했습니다.

두 번째, WAS가 중단된다면 interval 동안 발생한 변경 사항이 모두 날아가게 됩니다.

WAS의 변경 사항을 새로 배포하기 위해 서버를 내린다면 interval 동안 발생한 변경 사항은 데이터베이스에 반영되지 않습니다.

image

즉, 저희는 두 가지를 구현해야 했습니다.

  1. 오직 변경된 문서만 감지하여 데이터베이스에 반영합니다.
  2. WAS가 중단되더라도 변경 사항을 따로 저장해두었다가 WAS가 다시 실행되면 해당 변경 사항을 데이터베이스에 반영합니다.

이를 구현하기 위해 저희는 redis를 도입하기로 했습니다.

개발 문서

⚓️ 사용자 피드백과 버그 기록
👷🏻 기술적 도전
📖 위키와 학습정리
🚧 트러블슈팅

팀 문화

🧸 팀원 소개
⛺️ 그라운드 룰
🍞 커밋 컨벤션
🧈 이슈, PR 컨벤션
🥞 브랜치 전략

그룹 기록

📢 발표 자료
🌤️ 데일리 스크럼
📑 회의록
🏖️ 그룹 회고
🚸 멘토링 일지

Clone this wiki locally