SSOT (Single Source of Truth)

김진서·2025년 5월 16일

우아한테크코스 7기

목록 보기
43/56
post-thumbnail

SSOT (Single Source of Truth) ✨

  • 애플리케이션 내에서 어떤 데이터나 상태가 오직 한 곳에서만 관리되고, 그 한 곳을 통해서만 읽고 쓰기를 하는 설계 원칙

  • 장점
    1. 일관성 유지: 중복된 데이터가 여러 군데에 흩어져 있지 않기 때문에, 값이 변경될 때마다 모든 복제본을 동기화할 필요가 없다.
    2. 버그 감소: 변경 지점을 한 군데로 제한할 수 있으므로, 어디서 데이터가 바뀌는지 추적하기 쉽고 예측 가능성이 높아진다.
    3. 유지보수 편리: 데이터 흐름을 한 눈에 파악할 수 있어 리팩토링이나 기능 추가 시 안정적으로 작업할 수 있다.

EXAMPLE ⚛️

// ❌ 나쁜 예: 부모와 자식이 각각 로컬 state를 갖고 있을 때
function Parent() {
  const [count, setCount] = useState(0);
  return <Child count={count} onChange={setCount} />;
}

function Child({ count, onChange }) {
  const [localCount, setLocalCount] = useState(count);
  // 부모가 바꿔도 자식 로컬 state는 동기화가 안 될 수 있음
}
// ✅ 좋은 예: 단일 state를 부모에서만 관리
function Parent() {
  const [count, setCount] = useState(0);
  return <Child count={count} onChange={setCount} />;
}

function Child({ count, onChange }) {
  // 부모가 관리하는 count만 사용
  return <button onClick={() => onChange(count + 1)}>{count}</button>;
}
  • count를 부모 컴포넌트의 state 한 곳에서만 유지하고, 자식 컴포넌트는 props로 내려받아 사용하는 것이 Single Source of Truth 원칙

주의할 점 ⚠️

  • 너무 많은 데이터를 “한 곳”에 몰아넣으면, 그 소스가 복잡해질 수 있다.
  • 가끔은 퍼포먼스나 아키텍처 상, 적절히 캐시하거나 로컬 상태를 쓰는 편이 나을 때도 있다.

그러나 데이터 일관성이 중요한 대부분의 상황에서는 단일 진실의 원천을 지키는 것이 유지보수성과 신뢰성을 크게 높여 준다.


SSOT 원칙을 지키는 React 방법론 ䷼

  • 프로젝트를 진행할 때, 항상 상위 컴포넌트든, 외부의 어떤 store든 데이터를 저장해두고, 로컬에서만 조작하는 데이터가 아닌 이상 같은 데이터를 분산해서 만들지 않으려고 한다. 이게 깨지면 동기화와 신뢰성, 유지보수성 문제가 생기기 때문이다.

1. 리프팅 State Up (상태 끌어올리기)

  • 이번 상품 목록 미션에서 상품 목록을 ProductCardList에서 products 데이터 목록 상태를 가지는 게 아니라 부모 컴포넌트에서 가지고, props로 내려주었다.
const ProductListPage = () => {
  const { products, productsError, isProductsLoading } = useProductsContext();
  const { shoppingCartError } = useShoppingCartContext();

  return (
    <>
      {productsError.isError && (
        <ErrorToast errorMessage={productsError.errorMessage} />
      )}
      {shoppingCartError.isError && (
         <ErrorToast errorMessage={shoppingCartError.errorMessage} />
      )}
      <ProductListToolBar />
      {isProductsLoading ? (
        <OrbitSpinner />
      ) : (
		<ProductCardList products={products} />
	  )}
    </>
  );
};

2. Context API + Custom Hooks

  • 이번 상품 목록 미션에서 데이터 동기화 문제를 해결하기 위해 ContextAPI와 Custom Hook으로 데이터를 관리했다.
const ShoppingCartProvider: React.FC<PropsWithChildren> = ({ children }) => {
  const { data, error, isLoading } = useGetShoppingCart();
  const [cartItems, setCartItems] = useState<CartItem[]>([]);
  const [shoppingCartError, setShoppingCartError] = useState<Error>(INITIAL_ERROR);
  const [isShoppingLoading, setIsShoppingLoading] = useState<boolean>(false);
  • ContextProvider에서 cartItems 데이터, Error, loading 상태를 가지고 있고, 다른 컴포넌트들에서 이를 구독하고 조작한다.
profile
PAy IT forwaRD를 실천하는 프론트엔드 개발자.

0개의 댓글