사용자 디렉터리에서 사용자 통계가 잘못 표시됩니다

결국 이것은 “load more” 동작을 트리거해야 할 시점을 감지하는 데 사용하는 "sentinel"과 사용자 디렉터리 행 렌더링 사이에 발생한 까다로운 "경쟁 조건(race condition)"이었습니다 :exploding_head:

문제

최소 50명의 사용자가 있을 때, /u(사용자 디렉터리) 페이지가 사용자가 아래로 스크롤하기도 전에 첫 로드 시점에 즉시 loadMore를 트리거했습니다. 이로 인해 원치 않는 두 번째 페이지의 결과가 자동으로 로드되었습니다.

근본 원인

초기 페이지 로드 시 타이밍 경쟁 조건:

  1. 사용자가 /u로 이동합니다.
  2. controllers/users가 데이터 로드를 시작합니다 (isLoading: true).
  3. 스피너가 표시되는 ConditionalLoadingSpinner와 함께 템플릿이 렌더링됩니다.
  4. 데이터가 도착하고 isLoadingfalse가 됩니다.
  5. 스피너가 숨겨지고 DirectoryTable이 50명의 사용자를 렌더링하기 시작합니다.
  6. LoadMore sentinel 요소가 DOM에 삽입됩니다.
  7. IntersectionObserver가 생성되고 즉시 관찰을 시작합니다.
  8. 이 시점에서 테이블은 여전히 레이아웃을 계산하고 있으며 전체 높이로 확장되는 중입니다.
  9. 테이블이 확장되기 전, sentinel이 뷰포트에서 잠시 동안 가시 상태가 됩니다(상단에서 약 292px 위치).
  10. Observer가 교차를 감지하여 loadMore를 트리거합니다 :cross_mark:
  11. 테이블이 최종 높이(약 3689px)로 확장됩니다.
  12. Sentinel이 올바른 위치(뷰포트 아래, 약 3959px)로 이동합니다.

Observer가 "너무 성급"했습니다 - 콘텐츠가 레이아웃을 완료하기 전에 관찰을 시작하여, 테이블이 최종 높이에 도달하지 않은 짧은 순간에 sentinel을 감지했습니다.

해결 방법

콘텐츠가 준비될 때까지 Observer 생성을 지연시킵니다:

콘텐츠가 여전히 로드 중일 때 IntersectionObserver가 생성되지 않도록 방지하는 @isLoading 파라미터를 LoadMore에 추가했습니다.

현재 작동 방식

페이지 로드 → isLoading=true → Modifier가 Observer 생성을 건너뜀
             ↓
데이터 로드 완료 → isLoading=false → Modifier가 재실행되어 Observer 생성
             ↓
테이블이 완전히 확장됨 → Sentinel이 올바른 위치(뷰포트 아래)에 위치
             ↓
사용자가 아래로 스크롤 → Sentinel이 뷰포트에 진입 → loadMore 트리거 ✓

5개의 좋아요