SSOT를 한글로 해석하면, “단일 진실 공급원”이 된다. 이를 내 나름대로 해석하면 “동일한 데이터를 가지는 상태는 하나” 라고 해석했다.
예를 들어 아래와 같이 Header
와 ProductList
컴포넌트가 있다.
<Header/>
<ProductList/>
// Header 컴포넌트
function Header(){
const [cartItems, setCartItems] = useState<CartItemType[]>([]);
//...
useEffect(() => {
getCartItems().then(setCartItems);
}, []);
//...
}
// ProductList 컴포넌트
function ProductList(){
const [cartItems, setCartItems] = useState<CartItemType[]>([]);
// ...
useEffect(() => {
getCartItems().then(setCartItems);
}, []);
const handleToggleCartItem = async (productId: number) => {
const existingCartItem = cartItems.find(
(item) => item.product.id === productId
);
if (existingCartItem) {
await deleteCartItem(existingCartItem.id);
} else {
await addCartItem(productId);
}
const updatedCartItems = await getCartItems();
setCartItems(updatedCartItems);
};
// ...
}
위 예시 코드를 보면, cartItems
이라는 동일한 데이터를 두 개의 컴포넌트에서 각각 상태로 관리하고 있다. 이렇게 코드를 작성했을 때, 문제점은 Header
와 ProductList
컴포넌트가 동기화가 되지 않는 문제가 발생한다.
예를 들어, 장바구니에 아이템을 추가한 경우 Header
에서도 다시 fetching이 일어나야 하지만, 현재 코드에서는 그렇지 못한다. 즉, 동일한 데이터를 2곳에서 따로 관리하니까 동기화가 되지 않는 문제가 발생한다.
결론적으로, 내가 생각하는 SSOT는 동일한 데이터는 하나의 상태로 관리하여 사용하는 것이라고 생각한다.
SSOT(Single Source of Truth)는, “어떤 특정 데이터나 정보에 대해 그 데이터의 정확하고 신뢰할 수 있는 하나의 출처나 저장 위치가 있어야 한다” 이다. 이 원칙은 중복, 모순 및 데이터 불일치 문제를 방지하는 데 도움을 준다.
- 블로그
모든 데이터 요소를 한 곳에서만 제어 또는 편집하도록 조직하는 관례를 이른다.
- wikipedia (https://ko.wikipedia.org/wiki/단일진실공급원)
위의 말들을 정리해보면, “특정 데이터를 관리하는 곳은 하나”라고 정리할 수 있을 거 같다.
수업중 위와 같은 질문을 받았다. 해당 질문을 받았을 때, 어떤 대답을 해야할 지 막막했다.
막막했던 이유를 찾아보면 SSOT 원칙이 무엇인지 모르고, 방법론이라는 단어의 뜻도 제대로 몰라서 해당 문장 자체가 이해가 되지 않았다. 따라서 이해가 되지 않았던 부분부터 알아보고, 해당 질문에 대한 답을 찾아보고자 한다.
프론트엔드에서 SSOT를 지킨다는 것은
- 어떤 학문이 사용하는 방법들, 법칙들, 가설들의 원리들을 분석
어떤 학문 안에서 사용할 수 있거나 혹은 사용해온 방법들의 체계적 연구
방법들의 연구나 방법들의 서술
-wikipedia(https://ko.wikipedia.org/wiki/방법론)
결국 “SSOT 원칙을 지키는 React 방법론”은 SSOT를 지키기 위해서 리액트에서는 어떤 방법을 사용하는 지를 묻는 질문이다!
1. 상태 끌어올리기 (Lifting State Up)
function App(){
// 기존 Header와 ProductList 컴포넌트 각각에서 관리했던 상태를 공통 조상 컴포넌트인 App으로 끌어 올림
const [cartItems, setCartItems] = useState<CartItemType[]>([]);
return (
<>
<Header cartItems={cartItems}/>
<ProductList cartItems={cartItems} setCartItems={setCartItems}/>
</>
)
}
2. 전역 상태 관리 도구 사용 (Recoil, Zustand, Redux 등)
// store(중앙 저장소) 생성 (프로그램 전체에서 사용할 수 있는 상태 선언)
export const useCartStore = create<CartStore>((set) => ({
cartItems: [], // 장바구니 상태
addItem: (item) =>
set((state) => {
// 장바구니에 추가하는 코드
}),
removeItem: (id) =>
set((state) => ({
// 장바구니에서 제거하는 코드
})),
}));
// 실제 사용
function App(){
return (
<>
<Header />
<ProductList />
</>
)
}
// Header
function Header() {
// 중앙에서 장바구니 데이터 가져오기
const cartItems = useCartStore((state) => state.cartItems);
// ...
}
// ProductList
function ProductList() {
// 중앙에서 장바구니 데이터 가져오기
const {catrItems, addItem, removeItem} = useCartStore();
// ...
}
3. Context API
// 저장소 생성
export const CartItemContext = createContext()
// Context Provider로 값 전달하기
function App(){
const [cartItems, setCartItems] = useState<CartItemType[]>([]);
return (
<>
**<CartItemContext.Provider value={{cartItems, setCartItems}} >**
<Header />
<ProductList />
**</CartItemContext.Provider>**
</>
)
}
// Header
function Header() {
// 중앙에서 장바구니 데이터 가져오기
const {cartItems} = useContext(CartItemContext);
// ...
}
// ProductList
function ProductList() {
// 중앙에서 장바구니 데이터 가져오기
const {cartItems, setCartItems} = useContext(CartItemContext);
// 추가 함수 만들기
// ...
}
위와 같은 방식은 상태 끌어올리기(Lifting State Up)와 유사하다. 즉, Context API
는 상태를 끌어올린 뒤 props drilling 문제를 해결하기 위한 도구라고 생각한다.
따라서 “Context API가 SSOT(Single Source of Truth)를 위한 방법이냐?”고 묻는다면, 나는 그렇지 않다고 대답하고 싶다.
Context
는 단지 상태 공유와 전달을 편리하게 해주는 수단이지, SSOT 자체를 보장하는 구조는 아니라고 생각한다.
항상 그렇지는 않다.
API 서버가 SSOT가 될 수도 있고, 아닐 수도 있다.
대부분의 경우, API 서버는 데이터를 생성·보관·검증하는 주체다.
또한, 아래와 같은 경우엔 API 서버가 SSOT다.
따라서, 데이터는 항상 API 서버를 통해서만 가져오는 경우 API 서버는 진실의 원천이라고 말할 수 있다.
그런데 항상 API 서버가 항상 DB와 연결되어 있는 것은 아니다!
1. API 서버가 다른 시스템의 프록시인 경우
2. 비동기 동기화 상황
3. 분산 시스템
결과적으로, API 서버는 언제나 진실의 원천이 아니고, 상황이나 문맥에 따라 SSOT는 변경된다!
1. React Query(TanStack Query)
2. 전역 상태 관리 라이브러리 사용(Zustand, Recoil, Redux 등..)
3. Context API
https://ko.wikipedia.org/wiki/단일진실공급원
https://velog.io/@chy8165/SSOT-Single-Source-of-Truth (thanks to 호초)
SSOT 알차게 정리한 거 좋은데요?! 👍