packageshackle

@teamsparta/hackle

Hackle 기능들을 Suspense와 함께 사용할 수 있도록 선언적인 훅과 컴포넌트를 제공하는 라이브러리입니다. 또한 타입 안정성을 개선했습니다.


설치

# pnpm
pnpm install @teamsparta/hackle
 
# yarn
yarn add @teamsparta/hackle
 
# npm
npm install @teamsparta/hackle

원격 구성

기존의 @hackler/react-sdk에서는 useLoadableRemoteConfig 훅을 사용하여 원격 구성을 가져왔었습니다.

import { Suspense } from 'react';
import { useLoadableRemoteConfig } from '@hackler/react-sdk';
 
function App() {
  const { isLoading, remoteConfig } = useLoadableRemoteConfig('parameter-key');
  const parameterValue = remoteConfig.get('parameter-key', 'default-value');
 
  if (isLoading) return <Skeleton />;
 
  return <div>{parameterValue}</div>;
}

위와 같이 useLoadableRemoteConfig 훅을 이용하면 다음과 같은 불편함이 생깁니다.

  • 로딩 화면을 보여주기 위해서는 isLoading 값을 확인해야 하며, 코드가 명령적으로 작성됩니다.
  • remoteConfig의 타입은 any로 추론됩니다.

@teamsparta/hackle에서는

isLoading이 true일 때 Promise를 반환합니다. 이를 통해 Suspense와 같이 결합하여 isLoading이 true일 때는 fallback을 보여줄 수 있습니다. 또한 제네릭을 사용하여 타입을 지정할 수 있습니다.

import { Suspense } from 'react';
import { useSuspenseRemoteConfig } from '@teamsparta/hackle';
 
function App() {
  return (
    <Suspense fallback={<Skeleton />}>
      <Child />
    </Suspense>
  );
}
 
function Child() {
  const {
    data: { title, description },
  } = useSuspenseRemoteConfig<{ title: string; description: string }>(
    'remote-config-key',
  );
 
  return (
    <div>
      <h1>{title}</h1>
      <p>{description}</p>
    </div>
  );
}

SuspenseRemoteConfig 컴포넌트를 사용하여 원격 구성 데이터를 자식 컴포넌트에게 넘겨줄 수도 있습니다. 이렇게 되면 자식 컴포넌트는 Presentational 컴포넌트로 작성할 수 있으며 훅의 제약으로부터 벗어날 수 있습니다.

function App() {
  return (
    <Suspense fallback={<Skeleton />}>
      <SuspenseRemoteConfig<{
        title: string;
        description: string;
      }> remoteConfigKey="remote-config-key">
        {({ data }) => <Child {...data} />}
      </SuspenseRemoteConfig>
    </Suspense>
  );
}
 
function Child({ title, description }: { title: string; description: string }) {
  return (
    <div>
      <h1>{title}</h1>
      <p>{description}</p>
    </div>
  );
}

A/B 테스트

기존의 @hackler/react-sdk에서는 HackleExperiment, HackleVariation 컴포넌트나 useLoadableVariationDetail 훅을 사용하여 테스트 그룹을 분배했었습니다.

  • HackleExperiment, HackleVariation 컴포넌트를 사용했을 때
import {
  HackleExperiment,
  HackleVariation,
  useLoadableVariationDetail,
} from '@hackler/react-sdk';
import { SwitchCase } from '@teamsparta/react';
 
function App() {
  return (
    <HackleExperiment experimentKey={42}>
      <HackleVariation variation="A">
        <A />
      </HackleVariation>
      <HackleVariation variation="B">
        <B />
      </HackleVariation>
      <HackleVariation variation="C">
        <B />
      </HackleVariation>
    </HackleExperiment>
  );
}

  • useLoadableVariationDetail 훅을 사용했을 때
import { useLoadableVariationDetail } from '@hackler/react-sdk';
import { SwitchCase } from '@teamsparta/react';
 
function App() {
  const {
    isLoading,
    decision: { variation }, // variation의 타입은 string
  } = useLoadableVariationDetail(42);
 
  if (isLoading) return <Skeleton />;
 
  return (
    <SwitchCase value={variation} cases={{ A: <A />, B: <B />, C: <C /> }} />
  );
}

위와 같이 코드를 작성하면 다음과 같은 불편함이 생깁니다.

  • HackleExperiment, HackleVariation 컴포넌트를 사용하면 isLoading이 true일 때 fallback을 보여줄 수 없습니다.
  • useLoadableVariationDetail 훅을 사용하면 로딩 화면을 보여주기 위해서는 isLoading 값을 확인해야 하며, 코드가 명령적으로 작성됩니다.
  • 그리고 두 방법 공통적으로 variation의 타입이 ‘A’, ‘B’, ‘C’와 같은 문자열 리터럴이 아니라 string으로 추론됩니다.

@teamsparta/hackle에서는

isLoading이 true일 때 Promise를 반환합니다. 이를 통해 Suspense와 같이 결합하여 isLoading이 true일 때는 fallback을 보여줄 수 있습니다.

또한 hackle에서 테스트 그룹은 총 10개로 A부터 J까지 가능합니다. @teamsparta/hackle의 SuspenseVariation 컴포넌트와 useSuspenseVariation 훅의 variation은 string이 아니라 A부터 J까지의 문자열 리터럴로 추론됩니다.

  • SuspenseVariation 컴포넌트를 사용했을 때
import { Suspense } from 'react';
import { useSuspenseVariation } from '@teamsparta/hackle';
import { SwitchCase } from '@teamsparta/react';
 
function App() {
  return (
    <Suspense fallback={<Skeleton />}>
      <Child />
    </Suspense>
  );
}
 
function Child() {
  const { variation } = useSuspenseVariation(42); // variation의 타입은 'A' ~ 'J'
 
  return (
    <SwitchCase value={variation} cases={{ A: <A />, B: <B />, C: <C /> }} />
  );
}

  • SuspenseVariation 컴포넌트를 사용했을 때
import { Suspense } from 'react';
import { useSuspenseVariation } from '@teamsparta/hackle';
import { SwitchCase } from '@teamsparta/react';
 
function App() {
  return (
    <SuspenseVariation experimentKey={42}>
      {({ variation }) => (
        <SwitchCase
          value={variation}
          cases={{ A: <A />, B: <B />, C: <C /> }}
        />
      )}
    </SuspenseVariation>
  );
}