본문 바로가기
C.W.K.
Stream
Lesson 07 of 08 · published

실시간 접속 상태와 커서

~11 min · app, presence, cursors

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

커서 위치는 그대로 다 보내지 말고 빈도를 제한해

브라우저의 mousemove 이벤트는 초당 수백 번 발생해. 모두 WebSocket 으로 보내면 연결이 포화되고 서버 자원도 낭비돼. 초당 20~30회로 제한해. 특히 점 사이를 보간하는 CSS 전환을 함께 쓰면 사람의 눈에는 그 이상이 필요하지 않아.

접속 상태도 특별한 메시지일 뿐이야

‘사용자 X 가 온라인’이 메시지 하나고 ‘사용자 X 가 오프라인’이 다른 메시지이며 ‘사용자 X 의 커서가 문서 Y 의 (100,200) 에 있음’도 또 다른 메시지야. 별도의 특별한 접속 상태 프로토콜은 없어. 애플리케이션이 해석하는 자료형 있는 메시지일 뿐이지. Figma 는 presence, Slack 은 user.status라고 부르지만 전송 모양은 같아.

Code

클라이언트: 커서 빈도 제한과 다른 사용자 그리기·javascript
let lastSent = 0;
const THROTTLE_MS = 50; // 20 Hz

document.addEventListener('mousemove', (e) => {
  const now = Date.now();
  if (now - lastSent < THROTTLE_MS) return;
  lastSent = now;
  ws.send(JSON.stringify({
    type: 'presence.cursor',
    data: { x: e.clientX, y: e.clientY },
  }));
});

const cursors = new Map(); // userId -> element
ws.on('presence.cursor', ({ user_id, color, x, y }) => {
  let el = cursors.get(user_id);
  if (!el) {
    el = document.createElement('div');
    el.className = 'live-cursor';
    el.style.background = color;
    el.style.position = 'fixed';
    el.style.transition = 'transform 50ms linear';
    document.body.appendChild(el);
    cursors.set(user_id, el);
  }
  el.style.transform = `translate(${x}px, ${y}px)`;
});

External links

Exercise

서로 다른 사용자로 브라우저 탭 두 개를 열어 실시간 커서를 만들어. 20Hz 로 빈도를 제한하고 CSS 전환을 더해. 마우스를 움직였을 때 다른 탭의 커서가 50ms 미만의 지연으로 따라오는지 확인해. 제한을 5Hz 로 낮췄을 때도 전환을 켜 둔 상태에서 시각적 차이를 느낄 수 있는지 비교해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.