두 요소 스크롤 동기화

const box1 = document.getElementById('box1')
const box2 = document.getElementById('box2')

let isSyncing = false

function syncScroll(source, target, sourceWidth, targetWidth) {
  const ratio = source.scrollLeft / (source.scrollWidth - sourceWidth)
  target.scrollLeft = ratio * (target.scrollWidth - targetWidth)
}

box1.addEventListener('scroll', () => {
  if (!isSyncing) {
    isSyncing = true
    syncScroll(box1, box2, 1280, 640)
    isSyncing = false
  }
})

box2.addEventListener('scroll', () => {
  if (!isSyncing) {
    isSyncing = true
    syncScroll(box2, box1, 640, 1280)
    isSyncing = false
  }
})

isSyncing 플래그로 무한 이벤트 루프 방지

#532

네트워크를 가정하고 캐시를 끼워맞추지 말고, 처음부터 로컬을 본진으로. UI는 항상 로컬(IndexedDB)을 보고, 서버는 동기화 대상으로 내려간다.

캐시는 “네트워크가 1순위”라는 전제 위에 덧대는 임시방편 — 무효화·로딩 상태·페이지네이션이 전부 거기서 파생된다. 로컬을 본진으로 뒤집으면 그 파생 문제들이 통째로 사라지고 “동기화” 하나로 응축된다.

신선했던 지점은 이게 all-or-nothing이 아니라 난이도가 단계적으로 점프한다는 것:

  • 읽기 전용 = 재다운로드만. 충돌 없음. 지금 당장 가능.
  • 쓰기 = optimistic + outbox로 대부분.
  • 사용자별 분산 = 여기서부터 분산 시스템(Git 모델).

→ 읽기 전용 앱이면 오늘 시작할 수 있다.

#561