상품 목록 미션을 하면서 서버의 장바구니 목록과 로컬에서의 내 장바구니 목록이 일치하지 않은 문제가 있었다.
로컬에서 내가 콜라를 장바구니에 담았다면 서버에도 콜라가 담긴다.
그러나 로컬에서 재실행 될 때 서버에서의 장바구니 현황을 내 로컬 장바구니 현황에 동기화시키지 않아서 다음과 같은 문제가 발생했었다. 서버에는 콜라가 있어서 장바구니에서 뺄 수 있는데 로컬에는 콜라가 없어서 장바구니에서 뺄 수 없었다.
이런 문제를 겪지 않기 위해서는 SSOT라는 개념이 중요하다.
SSOT는 말 그대로 '하나의 진실된 출처'라는 뜻이다. 애플리케이션에서 특정 데이터나 정보의 정확하고 신뢰할 수 있는 유일한 출처가 존재해야 한다는 원칙을 의미한다. 프로그래밍에서는 모든 데이터가 한 곳에서만 제어되거나 편집되고, 다른 곳에서는 이 주된 출처를 단순히 참조만 하는 것을 말한다. 즉, '진실된' 상태나 데이터는 단 한 곳에서만 관리되어야 한다는 생각이다.
예를 들어 React의 경우, 단방향 데이터 흐름에서 부모 컴포넌트의 상태가 자식 컴포넌트에게 props로 전달될 때 그 부모 컴포넌트의 상태가 해당 데이터의 SSOT로 간주될 수 있다.
SSOT 원칙을 지키는 것은 안정적이고 예측 가능한 애플리케이션을 만드는 데 필수적이다.
데이터의 일관성 보장: 데이터가 여러 곳에 중복되어 저장될 때 발생할 수 있는 불일치 문제를 근본적으로 방지한다.
항상 최신 상태 유지: 모든 데이터가 한 곳에서만 관리되므로, 언제나 최신 정보를 참조할 수 있다.
유지 관리와 디버깅 용이: 데이터의 흐름이 명확해지면서 어디서 상태가 변경되었는지 추적하기 쉽다. 이는 코드의 유지 보수와 버그를 찾는 디버깅 시간을 크게 줄여준다.
예측 가능성: 데이터 흐름이 단방향으로 통제되므로 애플리케이션의 동작을 예측하기 쉬워진다.
오류 및 버그 발생 가능성 감소: 복잡한 애플리케이션에서 데이터 불일치로 인한 오류나 버그 발생 가능성을 현저히 줄여준다.
찰리 멍거의 '반대로 생각하기' 원칙은 복잡한 문제를 해결할 때 "무엇을 하지 말아야 할까?"를 먼저 생각함으로써 문제의 본질에 더 쉽게 접근할 수 있도록 돕는다. React에서 SSOT 원칙을 지키는 방법을 이해하기 위해, 이 원칙을 어기는 나쁜 관행들과 그로 인해 발생하는 문제 상황에 집중해서 설명해 보려고 한다.
다음은 React에서 SSOT 원칙을 어기는 대표적인 나쁜 관행들이다.
자세한 상황과 실행 예제 코드는 리액트 공식문서에서 확인할 수 있다.
상황: firstName과 lastName 상태가 있는데, 이 둘을 합쳐서 fullName이라는 별도의 상태로 또 저장하는 경우다.
자세한 코드와 실행할 수 있는 예제는 리액트 공식문서에서 더 살펴볼 수 있다.
상황: 여러 항목(items)의 목록 상태(items)를 가지고 있으면서, 동시에 선택된 항목 객체 전체를 selectedItem이라는 별도의 상태로 저장하는 경우다.
자세한 코드와 실행할 수 있는 예제는 리액트 공식문서에서 더 살펴볼 수 있다.
상황: 서로 배타적인 상태를 나타내는 여러 개의 boolean 상태 변수를 사용하는 경우다. 예: isSending과 isSent 상태 변수를 동시에 사용하는 경우.
자세한 코드와 실행할 수 있는 예제는 리액트 공식문서에서 더 살펴볼 수 있다.
상황: 데이터 구조가 행성 > 대륙 > 국가와 같이 깊게 중첩된 객체나 배열 형태로 상태를 관리하는 경우다.
자세한 코드와 실행할 수 있는 예제는 리액트 공식문서에서 더 살펴볼 수 있다.
상황: 두 개 이상의 컴포넌트가 동기화되어야 하는 동일한 상태를 각자 로컬 상태로 가지고 있는 경우다.
상태 끌어올리기는 props 전달을 늘릴 수 있지만, 데이터의 흐름을 명확히 하고 SSOT를 지키는 데 필수적인 패턴이다. Context API나 children prop을 활용하면 props drilling을 완화하면서도 SSOT를 유지할 수 있다.
자세한 코드와 실행할 수 있는 예제는 리액트 공식문서에서 더 살펴볼 수 있다.
API 서버는 맥락과 상황에 따라 진실의 원천이 될 수도 있고, 아닐 수도 있다.
클라이언트(프론트엔드 애플리케이션)의 관점에서 볼 때, API 서버는 보통 가장 직접적인 SSOT로 인식된다. 클라이언트는 API 서버가 제공하는 데이터가 가장 정확하고 최신이라고 가정하고 이를 기반으로 UI를 렌더링하고 비즈니스 로직을 수행한다.
하지만 API 서버의 내부 구조나 더 큰 시스템 아키텍처를 고려하면, API 서버 역시 다른 시스템으로부터 데이터를 가져오는 '중간 다리' 역할을 하는 경우가 많다. 이런 경우 API 서버는 진실의 원천이 아니라고 생각한다.
서버에서 가져온 데이터를 이들 라이브러리가 제공하는 전역 스토어에 저장한다. 여러 컴포넌트가 동일한 데이터를 필요로 할 때, 직접 API 호출을 하는 대신 스토어에서 데이터를 구독하여 사용한다. 데이터가 업데이트되면 스토어만 변경되고, 스토어를 구독하는 모든 컴포넌트가 자동으로 재렌더링되어 일관된 UI를 유지한다.
이 라이브러리들은 비동기 서버 상태 관리에 특화되어 있으며, 클라이언트 측에서 서버 데이터의 SSOT를 유지하는 데 매우 효과적이다.
항상 실시간으로 최신일 필요는 없다.
데이터의 변화 빈도가 낮은 경우:
예시: 제품 카테고리 목록, 국가 목록, 사용자 프로필 정보(자주 변경되지 않는 부분), 웹사이트 설정 등.
데이터의 즉각적인 최신성보다 사용자 경험이 중요한 경우 :
예시: 블로그 게시물 목록, 뉴스 피드, 댓글 목록 등.
성능 최적화를 위해 의도적으로 지연시키는 경우:
예시: 대규모 데이터 리스트의 페이지네이션, 필터링 결과, 검색 결과 등.
집계/보고서성 데이터:
예시: 어제의 매출 보고서, 주간 사용자 통계 등.
클라이언트 사이드 캐싱 (with TTL/Stale-While-Revalidate):
클라이언트 사이드 지속성 (Persistent State):
낙관적 UI 업데이트 (Optimistic UI Updates):
동기화라는 개념이 정말 중요한것 같아요!
잘 보고갑니다 ㅎㅎ