npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@reopt-ai/data-sdk

v0.2.3

Published

DEPRECATED — use @reopt-ai/data-sdk-client (browser/React/Next) and @reopt-ai/data-sdk-server (server components, route handlers, proxy, Node). reopt-data analytics SDK

Readme

@reopt-ai/data-sdk

폐기 예정(deprecated). 이 패키지는 두 개로 나뉘었습니다.

| 쓰던 것 | 바꿀 것 | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | @reopt-ai/data-sdk (브라우저) | @reopt-ai/data-sdk-clientinit/track/identify/pageView 동일 | | @reopt-ai/data-sdk/react | @reopt-ai/data-sdk-client/reactReoptProvider와 훅 동일, autoPageView prop 제거 | | @reopt-ai/data-sdk/nextjs | @reopt-ai/data-sdk-client/nextReoptProvider + <ReoptPageView /> + <ReoptWebVitals /> (usePathname prop 불필요) | | @reopt-ai/data-sdk/node | @reopt-ai/data-sdk-server/nodeapiUrlbaseUrl, batchSize/flushIntervalbatch: { size, intervalMs } |

새 패키지는 device id를 쿠키에 두고(Safari ITP에서 localStorage는 7일이면 사라짐), 서버 컴포넌트·라우트 핸들러·Next proxy.ts용 API를 제공하며, 클라이언트 번들에 서버 패키지가 섞이면 빌드에서 실패합니다. 이 패키지의 기존 localStorage device id는 새 클라이언트가 첫 로드에서 자동으로 이어받습니다.

0.2.x는 동작 호환 릴리스입니다(내부 엔진만 data-sdk-core로 교체). 두 마이너 뒤 제거됩니다.

reopt-data 분석 플랫폼용 클라이언트 SDK입니다.

설치

npm install @reopt-ai/data-sdk
# 또는
pnpm add @reopt-ai/data-sdk

사용법

브라우저 (바닐라 JavaScript/TypeScript)

import { init, track, identify, pageView, enableAutoPageView, close } from "@reopt-ai/data-sdk";

// 초기화
init({
  writeKey: "your-write-key",
  baseUrl: "https://data.reopt.app", // 필수 — reopt-data 오리진
  debug: true, // 선택사항, 디버그 로그 활성화
  // deviceId: "anonymous-device-id", // 선택사항, 미지정 시 SDK가 생성/저장
});

// 이벤트 트래킹
const queued = track("button_click", { buttonId: "signup", location: "header" });
console.log(queued.eventId, queued.queued);

// 객체 형태로도 가능
track({
  name: "purchase",
  properties: { product: "Pro Plan", price: 99 },
  profileId: "user-123", // 선택사항
});

// 사용자 식별
identify({
  profileId: "user-123",
  email: "[email protected]",
  firstName: "John",
  properties: { plan: "pro" },
});

// 페이지뷰 트래킹
pageView();
pageView({ path: "/custom-path", title: "Custom Title" });

// 자동 페이지뷰 (SPA에서 라우트 변경 감지)
const cleanup = enableAutoPageView();
// cleanup() 호출로 비활성화

// 테스트, micro frontend teardown 등에서 명시 정리
await close();

React

import { ReoptProvider, useTrack, useIdentify, useReopt, useTrackOnMount } from "@reopt-ai/data-sdk/react";

// 1. Provider로 앱 감싸기
function App() {
  return (
    <ReoptProvider
      config={{
        writeKey: "your-write-key",
      }}
      autoPageView={true} // 자동 페이지뷰 트래킹
    >
      <MyApp />
    </ReoptProvider>
  );
}

// 2. Hook 사용
function SignupButton() {
  const track = useTrack();

  return <button onClick={() => track("signup_clicked", { source: "landing" })}>Sign Up</button>;
}

// 3. 사용자 식별
function LoginHandler() {
  const identify = useIdentify();

  const handleLogin = (user) => {
    identify(user.id, { name: user.name, email: user.email });
  };

  return <button onClick={handleLogin}>Login</button>;
}

// 4. 마운트 시 트래킹
function ProductPage({ productId }) {
  useTrackOnMount("product_viewed", { productId });

  return <div>Product Details</div>;
}

// 5. 전체 API 접근
function AdvancedComponent() {
  const { track, identify, pageView, reset, flush } = useReopt();

  // ...
}

Node.js (서버사이드)

import { Reopt, createReopt } from "@reopt-ai/data-sdk/node";

// 클래스 인스턴스 생성
const reopt = new Reopt({
  clientId: "your-client-id",
  clientSecret: "your-client-secret",
  baseUrl: "https://data.reopt.app",
});

// 또는 팩토리 함수 사용
const reopt = createReopt({ clientId: "...", clientSecret: "..." });

// 이벤트 트래킹
reopt.track("server_event", { action: "api_call", endpoint: "/users" });
await reopt.flush();

// 서버리스/route handler에서는 한 번에 큐잉+전송 보장
const delivery = await reopt.trackAndFlush("checkout_completed", { orderId: "order-456" });
console.log(delivery.queue.eventId, delivery.flush?.status);

// 프로필 ID 설정 (이후 트래킹에 자동 포함)
reopt.setProfileId("user-123");
reopt.track("order_created", { orderId: "order-456" });

// 사용자 식별
reopt.identify("user-123", { name: "John", tier: "enterprise" });

// 프로퍼티 증가/감소
reopt.increment("user-123", "login_count");
reopt.decrement("user-123", "credits", 10);

// 큐에 쌓인 이벤트 즉시 전송
const result = await reopt.flush();
console.log(result.sent, result.pending);

// 정리
await reopt.close();

API Reference

설정 옵션

| 옵션 | 타입 | 필수 | 설명 | | ------------------- | --------- | --------------------- | ----------------------------------------------------------------------------- | | writeKey | string | 브라우저/React에서 ✅ | 브라우저 안전 수집 키 | | clientId | string | 서버에서 ✅ | 프로젝트 서버 클라이언트 ID | | clientSecret | string | 서버에서 ✅ | 프로젝트 서버 시크릿 | | baseUrl | string | ✅ | reopt-data 오리진. SDK가 경로를 붙인다 (apiUrl은 같은 값의 deprecated 표기) | | debug | boolean | ❌ | 디버그 모드 활성화 | | deviceId | string | ❌ | 익명 디바이스 ID 직접 지정 | | autoFlushOnUnload | boolean | ❌ | 브라우저 종료/숨김 시 keepalive flush | | storagePrefix | string | ❌ | 로컬 저장 키 prefix (기본값: reopt_) |

브라우저/React/Next.js 통합에는 writeKey만 사용하고, clientSecret은 서버 환경에서만 사용해야 합니다.

baseUrl은 필수이며 기본값이 없습니다. init()이 즉시 throw합니다.

기본 엔드포인트를 두면 설정을 빠뜨린 통합이 정상 동작처럼 보입니다 — SDK는 성공을 보고하고 이벤트는 아무 데도 가지 않으며, 빈 대시보드를 누군가 알아챌 때까지 아무것도 드러나지 않습니다. 초기화 시점에 실패하는 편이 고치기 가장 쌉니다.

baseUrl@reopt-ai/data-contractcreateDataClient({ baseUrl })과 같은 의미입니다. 끝 슬래시는 무시됩니다.

SDK가 자동으로 붙이는 메타데이터

  • eventId: 클라이언트에서 생성하는 UUID입니다. 서버의 raw event deduplication 키로 사용됩니다.
  • timestamp: 클라이언트 이벤트 생성 시각입니다. 서버는 별도로 수신 시각도 저장합니다.
  • reopt-device-id: 익명 디바이스 ID 헤더입니다. 브라우저에서는 기본적으로 localStorage에 저장됩니다.

track, identify, increment, decrement, pageView, screenView{ eventId, queued, reason?, errors? } 형태의 QueueResult를 반환합니다. flush(){ status, sent, failed, pending } 형태의 FlushResult를 반환합니다.

flush()는 track 응답의 accepted + duplicates + rejected.length를 제출한 배치 크기와 대조합니다. sent는 accepted와 duplicate, failed는 서버가 명시적으로 거부한 행 수입니다. 계약 버전이나 응답 합계가 맞지 않으면 배치를 성공으로 지우지 않고 pending에 보존합니다.

Node.js 서버 SDK는 서버리스 환경을 위해 trackAndFlush, identifyAndFlush, incrementAndFlush, decrementAndFlush를 제공합니다. 이 메서드들은 { queue, flush } 형태의 DeliveryResult를 반환하며, 큐잉이 실패한 경우 flushnull입니다. close()는 pending timer/listener를 정리하고 큐에 남은 이벤트를 전송합니다.

직접 HTTP로 POST /api/track를 호출하는 경우에도 SDK와 같은 @reopt-ai/data-contract(track) 계약을 따라야 합니다. track, identify, increment, decrement 이벤트에는 eventId UUID와 millisecond timestamp가 필수입니다.

프로덕션 통합 패턴

Browser / SPA

  • 앱 shell에서 한 번만 init()합니다.
  • SPA 라우팅에서는 enableAutoPageView() 또는 React Provider의 autoPageView를 사용합니다.
  • 테스트, Storybook, micro frontend teardown처럼 SDK 인스턴스 수명이 짧은 환경에서는 await close()를 호출합니다.
  • init()을 다시 호출하면 이전 singleton은 자동으로 close()되어 listener와 pending flush가 정리됩니다.
  • localStorage가 막힌 브라우저에서도 수집은 시도하지만, device ID와 offline queue 영속성은 보장되지 않습니다.

React / Next.js

  • Client Component에서 ReoptProvider로 앱을 감쌉니다.
  • Provider가 unmount되면 SDK는 남은 큐를 flush하고 page lifecycle listener를 정리합니다.
  • 로그인 직후 useIdentify()profileId를 설정하면 이후 track() 이벤트에 같은 프로필이 붙습니다.
  • 로그아웃 시에는 reset()으로 현재 프로필 ID와 pending queue를 비웁니다.

Node.js / Serverless

  • 서버리스 route handler, webhook, cron job에서는 trackAndFlush 계열을 우선 사용합니다.
  • track()만 호출하고 요청을 종료하면 런타임이 scheduled flush를 끝까지 보장하지 않을 수 있습니다.
  • 긴 수명의 서버나 worker에서는 인스턴스를 재사용하고, 종료 시 await close()로 drain합니다.
  • flush()close()는 큐가 빌 때까지 drain을 시도합니다.
const delivery = await reopt.trackAndFlush("invoice_paid", { invoiceId });

if (!delivery.queue.queued) {
  console.warn("event was not queued", delivery.queue.reason, delivery.queue.errors);
} else if (delivery.flush?.status !== "success") {
  console.warn("event is still pending", delivery.flush?.pending);
}

메서드

track(name, properties?)

커스텀 이벤트를 트래킹합니다.

identify(profileId, properties?)

사용자를 식별하고 프로필 속성을 설정합니다.

pageView(options?)

페이지뷰를 트래킹합니다. 자동으로 path, title, referrer를 캡처합니다.

screenView(screenName, properties?)

모바일/앱 화면 뷰를 트래킹합니다.

setProfileId(profileId)

이후 이벤트에 자동으로 포함될 프로필 ID를 설정합니다.

reset()

프로필 ID와 큐를 초기화합니다 (로그아웃 시 사용).

flush()

큐에 쌓인 이벤트를 즉시 서버로 전송합니다.

close()

큐에 남은 이벤트를 전송하고 SDK 리소스를 정리합니다. Node.js 서버 SDK와 브라우저 singleton API에서 사용할 수 있습니다.

React Hooks

| Hook | 설명 | | ------------------------------------ | ---------------------------------- | | useReopt() | 전체 SDK API 접근 | | useTrack() | track 함수 반환 | | useIdentify() | identify 함수 반환 | | usePageView() | pageView 함수 반환 | | useTrackOnMount(name, properties?) | 컴포넌트 마운트 시 이벤트 트래킹 | | usePageViewOnMount(options?) | 컴포넌트 마운트 시 페이지뷰 트래킹 |

동의(Consent) 관리

이벤트를 카테고리별 동의 상태로 게이팅할 수 있습니다. 카테고리는 analytics, marketing, functional, performance입니다.

init({
  writeKey: "...",
  consent: {
    categories: ["analytics", "marketing"],
    defaultConsent: false, // 동의 전까지 수집하지 않음
  },
});

// 마케팅 동의만 부여
setConsent("marketing", true);

// consentCategory로 이벤트를 분류 (미지정 시 기본값은 "analytics")
track("page_view", { plan: "pro" }); // 기본 analytics → analytics 미동의면 차단
track({ name: "promo_click", consentCategory: "marketing" }); // marketing 동의 → 전송

setAllConsent(false); // 전체 철회
  • 카테고리 검사는 enqueue 시점에 이뤄지며, 카테고리 자체는 서버로 전송되지 않습니다(클라이언트 측 게이트).
  • 이미 큐에 들어간 이벤트는 동의 시점 기준으로 수집된 것이므로, 이후 다른 카테고리를 철회해도 전송됩니다. setAllConsent(false)처럼 모든 카테고리가 거부된 전면 opt-out 상태가 되면 flush가 중단됩니다.
  • consentCategorytrack, identify, increment, decrement, pageView에서 지정할 수 있습니다.

SDK 제공 이벤트 이름

다음 이름은 SDK 메서드가 생성합니다:

  • $pageview - 페이지뷰
  • $screen_view - 화면 뷰

이벤트 배치 처리

SDK는 성능 최적화를 위해 이벤트를 배치로 처리합니다:

  • 이벤트는 큐에 쌓였다가 1초마다 자동 전송됩니다
  • flush()를 호출하면 즉시 전송됩니다
  • 브라우저에서는 페이지 언로드/숨김 시 keepalive로 자동 flush됩니다
  • 일시적 실패(네트워크 오류·5xx·429)는 지수 백오프로 재시도하고, 영구 거부(그 외 4xx)는 해당 배치를 폐기해 후속 이벤트 전송을 막지 않습니다
  • 오프라인 버퍼가 켜져 있으면 큐를 저장소에 보존하며, 페이지 언로드 시점에는 디바운스 없이 즉시 저장합니다

라이선스

MIT