Next.js
React 컴포넌트가 너무 커졌을 때 나누기
컴포넌트를 나눌 때는 상태와 렌더링을 먼저 분리하고, 실제 재사용성을 고려해야 한다.
React에서 한 파일에 모든 로직을 때려박으면, 코드가 복잡해지고 수정할 때마다 예상 밖의 버그가 생긴다. 특히 상태 관리와 렌더링이 뒤섞여 있으면 문제를 찾기 힘들다.
핵심은 컴포넌트를 작게 나누는 것 자체가 아니라, 무엇을 기준으로 나눌지 생각하는 것이다.
먼저 현재 상태 파악
컴포넌트의 state가 몇 개인지, 각 state가 어디에서 쓰이는지 정리한다. 로그를 찍거나 React DevTools로 확인하면 된다.
// 컴포넌트 내부 state 확인
const [formData, setFormData] = useState({})
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)
const [data, setData] = useState([])
렌더링과 상태 관리 분리
컴포넌트를 둘로 나눈다. 상태만 관리하는 Custom Hook과, 상태를 받아서 UI만 그리는 프레젠테이션 컴포넌트로 나눈다.
// useFormLogic.ts - 상태 관리만
const useFormLogic = () => {
const [formData, setFormData] = useState({})
const [loading, setLoading] = useState(false)
return { formData, setFormData, loading, setLoading }
}
// FormUI.tsx - UI만
const FormUI = ({ formData, loading }) => (
<div>...</div>
)
같은 책임끼리 묶기
컴포넌트의 부분별로 역할을 보고, 같은 책임을 가진 부분끼리 새로운 컴포넌트로 분리한다. 예를 들어 폼 입력 부분, 결과 표시 부분, 에러 처리 부분을 따로 컴포넌트로 뺀다.
// 각각 독립적인 역할
<FormInputs />
<ResultDisplay />
<ErrorMessage />
Props drilling 피하기
Props를 너무 깊게 파고 내려가면 컴포넌트 간 결합도가 높아진다. Context나 상태 관리 라이브러리 사용을 고려한다.
모바일과 데스크톱 뷰 분리
데스크톱과 모바일 레이아웃이 크게 다르다면, 조건부 렌더링보다는 별도의 컴포넌트로 나누는 게 낫다.
// 화면 크기에 따라 다른 컴포넌트
const isMobile = useMediaQuery('(max-width: 768px)')
return isMobile ? <MobileForm /> : <DesktopForm />
실제 재사용 여부 확인
나눈 컴포넌트가 정말 재사용될지 확인한다. 한 곳에서만 쓰이는 컴포넌트로 나누면 오히려 코드가 복잡해질 수 있다.
개발 환경에서 상태 변화 추적
React DevTools로 각 컴포넌트의 props와 state 변화를 실시간으로 추적하면서 나눠진 컴포넌트들이 제대로 동작하는지 본다.
- 컴포넌트의 state와 렌더링 로직을 먼저 분석한다.
- 상태 관리를 Custom Hook으로 빼낸다.
- 남은 렌더링 로직을 더 작은 프레젠테이션 컴포넌트로 나눈다.
- Props drilling이 없는지 확인한다.
마지막 확인
컴포넌트를 나눈 후에는 각 컴포넌트가 독립적으로 작동하는지 테스트해야 한다. 로컬에서 완전히 재현 가능한 상태로 만들어두면 다음에 같은 컴포넌트를 수정할 때도 빨리 찾을 수 있다.