@hurraey/interval-virtualizer

中文文档
0.1.0发布于 2026/11/01MITTypeScriptESM + CJS零依赖

숫자 구간의 겹침 조회와 청크 기반 화면 범위 계산을 제공하는 TypeScript 라이브러리

原始使用文档
文档目录8 节
  1. 설치
  2. 구간 조회
  3. 조회 방식과 비용
  4. 화면 범위 계산
  5. React 연결
  6. 공개 API
  7. 개발과 검증
  8. 라이선스

Interval Virtualizer

숫자 축 위의 구간 데이터에서 화면과 겹치는 항목을 찾는 TypeScript 라이브러리입니다. 오디오·비디오 타임라인, 일정, 문자 범위처럼 시작·종료 좌표가 있는 데이터에 사용할 수 있습니다.

구간 조회와 화면 범위 계산은 React나 DOM에 의존하지 않습니다. React 18·19용 구독 훅은 별도 진입점으로 제공합니다.

설치

Node.js 20 이상을 지원하며 ESM과 CommonJS, TypeScript 타입을 제공합니다.

npm install @hurraey/interval-virtualizer

React 훅을 사용할 때는 애플리케이션에 React 18.2 이상 또는 React 19가 필요합니다. 순수 계산 API만 사용하면 React를 설치할 필요가 없습니다.

구간 조회

import { createIntervalIndex, queryIntervals } from '@hurraey/interval-virtualizer';

const clips = [
  { id: 'background', start: 0, end: 100 },
  { id: 'effect', start: 75, end: 78 },
  { id: 'later', start: 110, end: 120 },
];

const index = createIntervalIndex(clips);
const result = queryIntervals(index, { start: 70, end: 80 });

console.log(result.intervals.map((clip) => clip.id));
// ['background', 'effect']
  • 시작 좌표와 종료 좌표는 같은 단위를 사용합니다. 초, 프레임, 픽셀, 문자 위치 모두 가능합니다.
  • 조회 범위의 경계에 닿는 구간과 길이가 0인 구간도 포함합니다. 겹침 조건은 start <= range.end && end >= range.start입니다.
  • 결과는 입력 순서를 유지하며 원래 객체를 반환합니다. 입력 배열을 정렬하거나 수정하지 않습니다.
  • 음수 좌표를 지원합니다. 유한한 숫자가 아닌 좌표와 end < start인 항목은 인덱스에서 제외합니다.
  • 잘못된 조회 범위에는 빈 배열과 inspectedIntervalCount: 0을 반환합니다.

인덱스는 생성 시점의 좌표를 보관합니다. 항목을 추가·삭제하거나 시작·종료 좌표를 바꾸면 다시 생성해야 합니다. 스크롤과 줌만 바뀌면 같은 인덱스를 재사용합니다.

조회 방식과 비용

시작 좌표순으로 정렬한 배열에서 이진 탐색으로 후보의 끝을 찾습니다. 각 하위 구간의 최대 종료 좌표를 저장한 세그먼트 트리를 따라가며, 화면 전에 모두 끝난 구간은 건너뜁니다.

인덱스 생성에는 정렬 비용과 항목 수에 비례하는 메모리가 필요합니다. 조회 후 입력 순서를 복원하는 정렬도 수행하므로 전체 조회가 항상 O(log N)에 끝나는 것은 아닙니다.

inspectedIntervalCount는 실제로 내려가 검사한 개별 항목 수입니다. 이진 탐색 비교, 트리 노드 방문, 정렬 비용이나 실행 시간을 나타내지 않습니다.

화면 범위 계산

import { getVirtualViewportRange } from '@hurraey/interval-virtualizer';

const range = getVirtualViewportRange({
  offset: 4_100,
  viewportSize: 800,
  contentSize: 10_000,
  chunkSize: 1_000,
  overscanChunks: 2,
  padding: 8,
});

console.log(range);
// { start: 1992, end: 7008 }

offset은 현재 스크롤 위치이고 viewportSize와 contentSize는 각각 화면과 전체 콘텐츠의 크기입니다. chunkSize는 조회 범위를 묶는 단위입니다. 같은 청크 안에서는 작은 스크롤 변화에도 같은 범위를 반환할 수 있습니다.

overscanChunks는 양옆에 추가할 청크 수이며 기본값은 0입니다. 소수는 내림합니다. padding은 청크 바깥에 더할 여유 크기이며 기본값은 0입니다. 청크 수를 제외한 옵션은 모두 같은 좌표 단위를 사용합니다.

결과는 콘텐츠 범위를 넘지 않습니다. 화면·콘텐츠·청크 크기가 0 이하이거나 입력이 유효하지 않으면 null을 반환합니다.

픽셀 범위를 초 단위 인덱스에 조회하려면 두 경계를 초당 픽셀 수로 나눠 사용합니다.

React 연결

@hurraey/interval-virtualizer/react의 useVirtualViewportRange는 브라우저에서 사용합니다. 서버 렌더링용 스냅샷은 제공하지 않습니다. Next.js 등에서는 클라이언트에서 마운트된 영역에 연결하세요.

import { useCallback, useRef } from 'react';
import { useVirtualViewportRange } from '@hurraey/interval-virtualizer/react';

export function ScrollRange() {
  const offsetRef = useRef(0);
  const listenersRef = useRef(new Set<() => void>());
  const subscribe = useCallback((listener: () => void) => {
    listenersRef.current.add(listener);
    return () => {
      listenersRef.current.delete(listener);
    };
  }, []);

  const range = useVirtualViewportRange({
    offsetRef,
    subscribe,
    viewportSize: 800,
    contentSize: 10_000,
    chunkSize: 1_000,
    overscanChunks: 1,
  });

  return (
    <div
      style={{ width: 800, overflowX: 'auto' }}
      onScroll={(event) => {
        offsetRef.current = event.currentTarget.scrollLeft;
        listenersRef.current.forEach((listener) => listener());
      }}
    >
      <div style={{ width: 10_000 }}>{range ? `${range.start} ~ ${range.end}` : '화면 크기 측정 전'}</div>
    </div>
  );
}

스크롤을 처리하는 쪽에서 ref를 먼저 갱신한 뒤 구독자에게 알립니다. subscribe는 구독 해제 함수를 반환해야 합니다. 훅은 계산된 범위가 같으면 같은 스냅샷 객체를 반환하며, 언마운트할 때 구독을 해제합니다.

DOM 크기 측정, 스크롤 이벤트 등록, requestAnimationFrame 예약, 실제 UI 렌더링은 사용하는 애플리케이션에서 담당합니다. 선택 중인 항목을 화면 밖에서도 유지하는 정책 역시 애플리케이션에서 처리합니다.

공개 API

  • createIntervalIndex<T extends Interval>(intervals) - 구간 인덱스를 생성합니다.
  • queryIntervals(index, range) - { intervals, inspectedIntervalCount }를 반환합니다.
  • getVirtualViewportRange(options) - { start, end } 또는 null을 반환합니다.
  • useVirtualViewportRange(options) - React에서 외부 스크롤 알림을 구독합니다. /react에서 가져옵니다.

루트 진입점은 Interval, IntervalIndex, IntervalQueryRange, IntervalQueryResult, VirtualViewportOptions 타입을 제공합니다. /react는 VirtualViewportSubscriptionOptions 타입을 제공합니다.

개발과 검증

저장소 루트에서 실행합니다.

npm ci
npm run check

구간 조회·화면 범위·React 구독 테스트, 타입 검사, ESM·CommonJS 빌드와 실제 패키지 설치 검증을 실행합니다. 패키지 설치 검증은 임시 디렉터리에서 실행하고 종료 시 삭제합니다.

라이선스

MIT

版本与发布记录

@hurraey/interval-virtualizer 共发布 2 个版本,首次发布于 2026/11/01;过去 12 个月发布了 2 个版本。

版本发布日期距今
0.1.0latest2026/11/012 天前
0.0.0-stage2026/11/012 天前

关于 @hurraey/interval-virtualizer 的常见问题

@hurraey/interval-virtualizer 是什么?

숫자구간의겹침조회와청크기반화면범위계산을제공하는打印稿라이브러리

如何安装 @hurraey/interval-virtualizer?

在项目目录运行 npm install @hurraey/interval-virtualizer,或使用 pnpm add / yarn add / bun add。

@hurraey/interval-virtualizer 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@hurraey/interval-virtualizer 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@hurraey/interval-virtualizer 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@hurraey/interval-virtualizer 可以商用吗?

@hurraey/interval-virtualizer 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@hurraey/interval-virtualizer 还在维护吗?

最新版本 0.1.0 发布于 2026/11/01(2 天前);至今共发布 2 个版本,其中过去 12 个月发布了 2 个;首次发布于 2026/11/01。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。