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 🙏

© 2025 – Pkg Stats / Ryan Hefner

hsc-store

v1.0.0

Published

hsc-store

Downloads

124

Readme

HSC-Store

간결하고 직관적인 전역 상태 관리 라이브러리입니다.

✨ 주요 특징

  • TypeScript 지원: 타입 안전성 제공
  • React 통합: React 컴포넌트에서 쉽게 사용 가능
  • 선택적 구독: 필요한 부분만 선택하여 구독 가능
  • 영구 저장: localStorage/sessionStorage를 통한 상태 유지 기능
  • 타임트래블 디버깅: 상태 변화 이력을 추적하고 이전/이후 상태로 이동 가능
  • 파생 상태: 기존 상태에서 자동으로 계산되는 상태 관리

📦 설치

npm install hsc-store
# 또는
yarn add hsc-store
# 또는
pnpm add hsc-store

🚀 기본 사용법

스토어 생성하기

import { createStore } from "hsc-store";

// 카운터 스토어 생성
const useCounterStore = createStore((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}));

React 컴포넌트에서 사용하기

import React from "react";
import { useCounterStore } from "./stores/counter";

function Counter() {
  // 훅으로 사용 - 자동으로 리렌더링됨
  const { count, increment, decrement, reset } = useCounterStore();

  return (
    <div>
      <h1>카운터: {count}</h1>
      <button onClick={increment}>증가</button>
      <button onClick={decrement}>감소</button>
      <button onClick={reset}>초기화</button>
    </div>
  );
}

컴포넌트 외부에서 사용하기

// 상태 직접 접근
const count = useCounterStore.getState().count;
console.log("현재 카운트:", count);

// 상태 변경하기
useCounterStore.getState().increment();
// 또는
useCounterStore.setState({ count: 10 });

// 변경 구독하기
const unsubscribe = useCounterStore.subscribe((state) =>
  console.log("상태가 변경되었습니다:", state.count)
);

// 구독 해지하기
unsubscribe();

🔄 비동기 액션 처리

const useUserStore = createStore((set) => ({
  user: null,
  loading: false,
  error: null,

  // 비동기 액션
  fetchUser: async (id) => {
    set({ loading: true, error: null });

    try {
      const response = await fetch(`/api/users/${id}`);
      const userData = await response.json();
      set({ user: userData, loading: false });
    } catch (err) {
      set({ error: err.message, loading: false });
    }
  },

  logout: () => set({ user: null }),
}));

💾 영구 저장 (Persistence)

새로고침 후에도 상태를 유지하기 위해 persist 기능을 사용할 수 있습니다:

import { createStore, persist } from "hsc-store";

// 기본 스토어 생성
const useSettingsStore = createStore((set) => ({
  theme: "light",
  fontSize: 16,
  setTheme: (theme) => set({ theme }),
  setFontSize: (fontSize) => set({ fontSize }),
}));

// 영구 저장 추가
const usePersistedSettingsStore = persist(useSettingsStore, {
  name: "settings-storage", // 로컬 스토리지 키 이름
  // 선택적 옵션
  storage: localStorage, // 기본값: localStorage
  partialize: (state) => ({ theme: state.theme }), // 일부 필드만 저장
  version: 1, // 버전 관리
  migrate: (persistedState, version) => {
    // 이전 버전 데이터 마이그레이션
    if (version === 0) {
      return { ...persistedState, fontSize: 16 };
    }
    return persistedState;
  },
  onRehydrateStorage: (state) => {
    console.log("상태가 복원되었습니다:", state);
  },
  skipHydration: true, // 하이드레이션 문제 방지
});

한번에 생성하기

import { createPersistStore } from "hsc-store";

// 한번에 스토어 생성 및 영구 저장 설정
const useSettingsStore = createPersistStore(
  (set) => ({
    theme: "light",
    fontSize: 16,
    setTheme: (theme) => set({ theme }),
    setFontSize: (fontSize) => set({ fontSize }),
  }),
  {
    name: "settings-storage",
    // 다른 선택적 옵션들...
  }
);

// 사용법은 동일
function ThemeSwitcher() {
  const { theme, setTheme } = useSettingsStore();

  return (
    <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
      테마 변경 (현재: {theme})
    </button>
  );
}

영구 저장 API

persist(store, options)

스토어에 영구 저장 기능을 추가합니다.

createPersistStore(creator, options)

스토어 생성과 영구 저장 기능을 한번에 적용합니다.

영구 저장 옵션

  • name: 스토리지 키 이름 (필수)
  • storage: 사용할 스토리지 (기본값: localStorage)
  • partialize: 저장할 상태 일부 선택 함수
  • version: 상태 버전 (마이그레이션에 사용)
  • migrate: 버전 간 상태 마이그레이션 함수
  • onRehydrateStorage: 상태 복원 후 콜백
  • skipHydration: 하이드레이션 문제 방지 옵션

영구 저장 메서드

  • persist.getOptions(): 현재 persist 옵션 가져오기
  • persist.rehydrate(): 수동으로 상태 복원 실행
  • persist.hasHydrated(): 하이드레이션 완료 여부 확인
  • persist.onHydrate: 하이드레이션 완료 콜백
  • persist.clearStorage(): 저장된 상태 제거

🕰️ 타임트래블 디버깅

상태 변화 이력을 추적하고 이전/이후 상태로 이동할 수 있는 기능을 제공합니다:

import { createStore, timeTravelMiddleware } from "hsc-store";

// 타임트래블 미들웨어 적용
const useCounterStore = createStore(
  timeTravelMiddleware({
    maxHistory: 50, // 최대 히스토리 수 (기본값: 100)
    enabled: true, // 활성화 여부 (기본값: true)
  })((set) => ({
    count: 0,
    increment: () => set((state) => ({ count: state.count + 1 })),
    decrement: () => set((state) => ({ count: state.count - 1 })),
  }))
);

// 타임트래블 기능 사용하기
function CounterWithTimeTravel() {
  const { count, increment, decrement } = useCounterStore();

  // 타임트래블 API 접근
  const timeTravel = useCounterStore.getState()._timeTravel;
  const history = timeTravel.getHistory();
  const currentIndex = timeTravel.getCurrentIndex();

  return (
    <div>
      <h1>카운터: {count}</h1>
      <div>
        <button onClick={increment}>증가</button>
        <button onClick={decrement}>감소</button>
      </div>

      <div>
        <h3>타임머신</h3>
        <button
          onClick={() => timeTravel.goBack()}
          disabled={currentIndex <= 0}
        >
          이전 상태
        </button>
        <button
          onClick={() => timeTravel.goForward()}
          disabled={currentIndex >= history.length - 1}
        >
          다음 상태
        </button>
      </div>

      <div>
        <h3>히스토리</h3>
        {history.map((item, index) => (
          <div
            key={index}
            style={{
              cursor: "pointer",
              fontWeight: index === currentIndex ? "bold" : "normal",
            }}
            onClick={() => timeTravel.jumpToState(index)}
          >
            {index}: {JSON.stringify(item.state)}
          </div>
        ))}
      </div>
    </div>
  );
}

🧮 파생 상태 (Computed State)

다른 상태 값에서 자동으로 계산되는 파생 상태를 정의할 수 있습니다:

import { createStore, computedMiddleware } from "hsc-store";

// 파생 상태 미들웨어 적용
const useCartStore = createStore(
  computedMiddleware({
    computed: {
      // 총 금액 계산
      totalPrice: (state) =>
        state.items.reduce((sum, item) => sum + item.price * item.quantity, 0),

      // 총 아이템 개수
      totalItems: (state) =>
        state.items.reduce((sum, item) => sum + item.quantity, 0),

      // 할인된 금액
      discountedPrice: (state) =>
        state.items.reduce((sum, item) => sum + item.price * item.quantity, 0) *
        0.9,
    },
  })((set) => ({
    items: [],
    addItem: (item) =>
      set((state) => ({
        items: [...state.items, item],
      })),
    updateQuantity: (id, quantity) =>
      set((state) => ({
        items: state.items.map((item) =>
          item.id === id ? { ...item, quantity } : item
        ),
      })),
    removeItem: (id) =>
      set((state) => ({
        items: state.items.filter((item) => item.id !== id),
      })),
  }))
);

// 컴포넌트에서 사용하기
function Cart() {
  // 기본 상태와 계산된 상태 모두 접근 가능
  const {
    items,
    addItem,
    removeItem,
    totalPrice,
    totalItems,
    discountedPrice,
  } = useCartStore();

  return (
    <div>
      <h2>장바구니 ({totalItems}개 상품)</h2>
      <div>
        {items.map((item) => (
          <div key={item.id}>
            {item.name} - {item.price}원 x {item.quantity}개
            <button onClick={() => removeItem(item.id)}>삭제</button>
          </div>
        ))}
      </div>
      <div>
        <p>총 금액: {totalPrice}원</p>
        <p>할인 금액: {totalPrice - discountedPrice}원</p>
        <p>최종 금액: {discountedPrice}원</p>
      </div>
    </div>
  );
}

📝 API 문서

코어 API

createStore(creator)

스토어를 생성합니다. creator 함수는 set 함수를 파라미터로 받아 초기 상태와 액션을 반환합니다.

스토어 메서드

  • useStore(): React 훅으로 전체 상태를 반환
  • useStore(selector): 특정 부분만 선택하여 반환
  • getState(): 현재 상태 가져오기
  • setState(partial): 상태 업데이트
  • subscribe(listener): 변경 구독 (구독 해지 함수 반환)

영구 저장 API

persist(store, options)

스토어에 영구 저장 기능을 추가합니다.

createPersistStore(creator, options)

스토어 생성과 영구 저장 기능을 한번에 적용합니다.

영구 저장 옵션

  • name: 스토리지 키 이름 (필수)
  • storage: 사용할 스토리지 (기본값: localStorage)
  • partialize: 저장할 상태 일부 선택 함수
  • version: 상태 버전 (마이그레이션에 사용)
  • migrate: 버전 간 상태 마이그레이션 함수
  • onRehydrateStorage: 상태 복원 후 콜백
  • skipHydration: 하이드레이션 문제 방지 옵션

영구 저장 메서드

  • persist.getOptions(): 현재 persist 옵션 가져오기
  • persist.rehydrate(): 수동으로 상태 복원 실행
  • persist.hasHydrated(): 하이드레이션 완료 여부 확인
  • persist.onHydrate: 하이드레이션 완료 콜백
  • persist.clearStorage(): 저장된 상태 제거

타임트래블 API

timeTravelMiddleware(options)

상태 변화 이력을 추적하고 이전/이후 상태로 이동할 수 있는 기능을 추가합니다.

타임트래블 옵션

  • maxHistory: 최대 히스토리 저장 개수 (기본값: 100)
  • enabled: 타임트래블 활성화 여부 (기본값: true)

타임트래블 메서드

  • _timeTravel.goBack(): 이전 상태로 이동
  • _timeTravel.goForward(): 다음 상태로 이동
  • _timeTravel.jumpToState(index): 특정 인덱스의 상태로 이동
  • _timeTravel.getHistory(): 전체 히스토리 데이터 가져오기
  • _timeTravel.getCurrentIndex(): 현재 상태 인덱스 가져오기
  • _timeTravel.clearHistory(): 히스토리 초기화

파생 상태 API

computedMiddleware(options)

다른 상태에서 자동으로 계산되는 파생 상태 기능을 추가합니다.

파생 상태 옵션

  • computed: 계산된 속성 정의
  • dependsOn: 각 계산 속성이 의존하는 기본 상태 필드 정의 (선택 사항)

파생 상태 메서드

  • _computed.recompute(key): 특정 계산 속성 재계산
  • _computed.recomputeAll(): 모든 계산 속성 재계산
  • _computed.getStateWithComputed(): 기본 상태와 계산된 상태를 모두 포함한 결과 가져오기
  • getStateWithComputed(): 기본 및 계산된 상태에 접근 가능한 프록시 반환

📄 라이선스

MIT ©