React 컴포넌트를 정리하는 최적의 구조와 핵심 원칙
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
웹 개발
대상자
React 개발자 및 중급 이상의 프론트엔드 개발자 (난이도: 중급)
핵심 요약
- React Hook의 순서는 예측 가능해야 한다
useState
,useEffect
등 내장 Hook은 컴포넌트 최상단에 배치 (예:const [count, setCount] = useState(0);
)- 커스텀 Hook은 내장 Hook 이후에 배치 (예:
const user = useUser();
) - 조건문은 Hook 아래에 배치하여
React
의 Hook 실행 순서 오류를 방지 (예:if (!isLoggedIn) { return
); } - Effects(
useEffect
)는 조건문 이전에 배치 (예:useEffect(() => { ... }, [count]);
)
섹션별 세부 요약
1. 내장 Hook 우선 배치 (Built-in Hooks)
useState
,useEffect
등 React 제공 Hook은 항상 컴포넌트 최상단에 배치- Hook 실행 순서가 일관되지 않으면
React
가Hook call that is inconsistent with previous renders
오류 발생 - 예시:
const [count, setCount] = useState(0);
2. 커스텀 Hook 다음 배치 (Custom Hooks)
- 커스텀 Hook(
useUser
,useTheme
)은 내장 Hook 이후에 배치 (예:const user = useUser();
) - 내장 Hook이 기반으로 작동하므로 순서가 중요
- Hook의 실행 순서를 통일해
React
의 예측 가능성을 확보
3. 파생 변수 처리 (Derived Variables)
- Props, state에서 파생된 변수는 Hook 이후에 정의 (예:
const isLoggedIn = Boolean(user);
) user?.name?.trim() ?? "Anonymous"
와 같이 옵셔널 체이닝 사용- 항상 최신 state와 props를 기반으로 계산
4. 콜백 및 메모이제이션 (Callbacks & Memoization)
useCallback
은 state/props에 의존하는 경우 Hook 이후에 정의 (예:const handleClick = useCallback(() => { ... }, []);
)- 컴포넌트 외부로 이동 가능하지만, Hook에 의존할 경우 내부에 배치
- 불필요한 re-render 방지와 성능 최적화
5. Effect Hook 배치 (Effects)
useEffect
는 조건문 전에 배치 (예:useEffect(() => { ... }, [count]);
)- 컴포넌트의 "정리 작업" 역할 수행 (ex: DOM 정리, 타이머 해제)
- Effect Hook은 Hook 실행 순서에 따라 실행 순서가 결정됨
6. 조건문 배치 (Conditionals)
- 조건문(
if
)은 Hook 이후에 배치 (예:if (!isLoggedIn) { return
); } - 조건문 위에 Hook 배치하면
React
가 Hook 실행 순서를 예측 불가로 판단 return
문은 조건문 내부에 배치 가능
7. UI 렌더링 (Return Statement)
return
문은 모든 로직 이후에 배치 (예:return (
)...);- 최종 UI 출력은 모든 준비 과정 완료 후 수행
React
의 렌더링 흐름과 일치해 가독성 향상
결론
- Hook 순서를 일관성 있게 유지하고, ESLint + Prettier 등 도구로 자동 검증
useState
→useEffect
→useCustom
→Derived Variables
→useCallback
→useEffect
→Conditionals
→Return
순서를 준수- Hook 실행 순서 오류는
React
의 예측 불가능한 동작으로 이어져 Debugging 시간 증가 - 커스텀 Hook과 파생 변수는 Hook 이후에 배치하여
React
의 예측 가능성을 보장