바이브코딩 워크플로우

상태(State) 설계 입문: 어디에 저장하고 누가 바꿔야 할까?

바이브빌더 2026. 5. 5. 12:00

상태(State) 설계 입문: 어디에 저장하고 누가 바꿔야 할까?

1. 주제 소개

프론트엔드 개발에서 버그가 반복되는 가장 큰 이유 중 하나는 상태를 어디에 둬야 하는지 초기에 정하지 않았기 때문입니다. 화면이 커질수록 같은 데이터가 여러 컴포넌트에 흩어지고, 누가 값을 바꿨는지 추적하기 어려워집니다. 결국 기능은 돌아가지만 수정할 때마다 예기치 않은 사이드 이펙트가 생깁니다. 그래서 상태 설계의 첫 질문은 단순합니다. 이 값은 어디에 저장해야 하고, 누가 변경 권한을 가져야 하는가?

입문 단계에서 흔히 하는 실수는 “일단 가까운 컴포넌트에 state를 둔다”는 방식입니다. 초기엔 편하지만 기능이 늘어나면 props 전달이 깊어지고, 중간 컴포넌트가 데이터 중계 역할만 하게 됩니다. 이 문제를 줄이려면 상태를 만들기 전에 데이터 성격을 분류하는 습관이 필요합니다. 로컬 UI 상태인지, 여러 화면에서 공유하는 도메인 상태인지, 서버에서 내려오는 원본 데이터인지 먼저 구분하면 구조가 훨씬 깔끔해집니다.

2. 핵심 내용

상태 설계의 핵심 원칙은 세 가지입니다. 첫째, 상태는 가능한 한 가까운 곳에 둡니다. 단, 둘 이상의 컴포넌트가 동일하게 읽고 수정해야 한다면 공통 상위로 올립니다. 둘째, 상태의 단일 출처를 유지합니다. 같은 의미의 값을 두 군데 이상 저장하면 동기화 버그가 생깁니다. 셋째, 변경 책임을 명확히 나눕니다. 읽기 전용 컴포넌트와 변경 가능한 컴포넌트를 구분하면 디버깅이 쉬워집니다.

특히 서버 데이터와 UI 상태를 섞지 않는 것이 중요합니다. 예를 들어 상품 목록 API 응답은 서버 상태이고, 정렬 드롭다운 선택값은 UI 상태입니다. 이 둘을 하나의 객체로 무리하게 합치면 캐시 전략, 재요청 처리, 로딩 상태 관리가 복잡해집니다. 반대로 역할을 분리하면 로딩/에러/성공 흐름도 예측 가능해지고 테스트 범위도 명확해집니다.

3. 적용 방법

실전에선 새 상태를 추가할 때 아래 체크리스트를 먼저 통과시키면 좋습니다. “이 값은 누가 읽는가, 누가 바꾸는가, 새로고침 후 유지가 필요한가”를 빠르게 확인하면 저장 위치를 거의 자동으로 결정할 수 있습니다. 팀 단위 개발에서는 이 기준을 PR 템플릿에 넣어두면 리뷰 품질도 올라갑니다.

상태 유형 권장 저장 위치 변경 주체
입력창 열림/닫힘 해당 컴포넌트 로컬 state 컴포넌트 내부 이벤트 핸들러
페이지 공통 필터값 상위 컨테이너 또는 전역 스토어 필터 패널과 리셋 액션
서버 목록 데이터 서버 상태 관리 레이어(query/cache) API 응답 및 재요청 로직

한 가지 실용적인 팁은 “파생 가능한 값은 저장하지 않는다”는 원칙입니다. 예를 들어 장바구니 총액은 상품 목록과 수량으로 계산 가능하므로 별도 상태로 저장하기보다 필요할 때 계산하는 편이 안전합니다. 저장 상태를 줄일수록 버그 지점도 줄어듭니다. 또한 변경 함수 이름을 명확하게 짓는 것도 중요합니다. `setData` 같은 이름보다 `updateFilter`, `resetPagination`처럼 의도가 드러나는 이름이 유지보수에 훨씬 유리합니다.

4. 정리

상태 설계는 특정 라이브러리를 잘 아는 문제보다 데이터 책임을 어떻게 나누는지의 문제에 가깝습니다. 어디에 저장할지, 누가 바꿀지, 무엇이 원본인지 세 가지만 정리해도 코드 복잡도가 크게 줄어듭니다. 초보 단계에서는 모든 걸 전역으로 올리거나 반대로 전부 로컬에 두는 극단을 피하고, 공유 범위에 맞춰 단계적으로 확장하는 전략이 가장 안정적입니다. 좋은 상태 구조는 기능 추가 속도를 높이고, 버그 수정 시간을 짧게 만들어 결국 팀 전체 생산성을 끌어올립니다.

5. 자주 묻는 질문

Q1. 상태 관리 라이브러리를 바로 도입해야 하나요?

초기에는 로컬 state와 상위 승격만으로 충분한 경우가 많습니다. 컴포넌트 간 공유 범위가 넓어지고 변경 로직이 복잡해질 때 도입해도 늦지 않습니다.

Q2. 전역 상태는 많을수록 편하지 않나요?

단기적으로는 편해 보이지만 장기적으로는 의존성이 커져 디버깅이 어려워집니다. 정말 여러 영역에서 공통으로 쓰는 값만 전역으로 올리고, 나머지는 로컬에 두는 것이 유지보수에 유리합니다.