선요약
ㄴㄴ
아무 함수나 커스텀 훅이 될 수 있을까?
‘Hook’의 사전적 의미에는 무언가에 건다는 뜻이 들어 있다. 어린 나는 이런 생각을 한다. “그러면 컴포넌트에 ‘거는’건 전부 훅인가?” 단순한 예시를 들어보자.
const useLengthValidator = (string, maxLength) => (string.length <= maxLength);
이런 평범한 함수도 앞에 ‘use’라는 성씨가 붙었다는 이유만으로 위대한 커스텀 훅의 일원이 될 수 있을까?
나는 이 문제를 꽤 고민했었다. 답은 리액트 공식 문서에 이미 있었다.
1. 훅은 ‘컴포넌트’에 걸어서 훅이 아니다.
Hooks are functions that let you “hook into” React state and lifecycle features from function components.
함수형 컴포넌트의 ‘상태와 생명 주기’에 걸어서 훅이다.
2. 커스텀 훅은 stateful logic을 재사용하는 방법이다.
이 두 가지만 봐도 우리의 useLengthValidator는 커스텀 훅이 아니라는 걸 알 수 있다.
하지만 커스텀 훅이 아닌데도 ‘use’를 붙이는 건 괜찮지 않을까?
1. 상관은 없다
리액트 자체적으로 이름을 강제하지는 않는다.
2. 근데 개발자를 위해서는 붙이지 않는 게 낫다.
우리가 어떤 컴포넌트 내부를 처음 봤을 때 ‘use’가 있다면 이 친구는 state, effect같은 리액트 기능을 사용하고 있음을 유추할 수 있다. 반대로 없다면 평범한 함수라고 생각할 수 있을 것이다. 공식 문서에서는 지금 당장은 아니더라도 혹시 추후에 stateful logic을 쓸 거라면 use를 붙일 만하다고도 한다.
이 약속이 얼만큼 중요한가 라고 묻는다면 내가 할 말은 없긴 하다. 하지만 나는 나름 중요한 순간이 있겠다는 생각이 든다. 근거 자료로는 리액트 useState의 특이한 동작 방식을 제출한다.
우리는 useState를 쓸 때 구체적으로 ‘누구의’ 상태인지 알려주지 않는다. 그냥 인자로 초기값이나 초기화 함수를 전달할 뿐이다. 근데 리액트 컴포넌트는 우리가 useState를 여러 번 하더라도 그게 누구의 상태인지 정확히 안다. 이 글에서는 구체적인 구현에 대해서는 다루지 않겠다. 짧게 말하면 리액트는 컴포넌트 함수 호출 시 훅을 부르는 ‘순서’에 따라 일정하게 값을 저장하는 방식으로 누구의 상태인지 기억한다. 이 때문에 우리가 조건문 안에 훅을 넣을 수 없는 것이다.
다시 커스텀 훅 이름 이야기로 돌아와 보자. 위와 같은 이유로 훅은 컴포넌트의 최상단(top-level)에서만 부를 수 있다. 하지만 훅이 아닌 일반 함수에는 그런 제약이 없다. 우리가 일반 함수에 use를 붙여서 커스텀 훅인 것처럼 만든다면 오히려 일반 함수의 자유를 뺏는 셈이다. 개발자 입장에서는 조건문 안으로 옮기면 더 좋을 것 같은데 이름이 훅 같아서 망설이는 경우가 생길 수도 있다. 근데 코드를 열어 보니 stateful logic이 하나도 없다면 어떻게 옮길 지 고민한 시간이 억울하지 않을까?
마치며
느낀 점: 공식 문서를 읽자
읽어볼 만한 글들
https://legacy.reactjs.org/docs/hooks-overview.html#but-what-is-a-hook
https://legacy.reactjs.org/docs/hooks-custom.html#using-a-custom-hook
https://react.dev/learn/state-a-components-memory#how-does-react-know-which-state-to-return
'호기심 천국' 카테고리의 다른 글
React.ReactNode vs JSX.Element (1) | 2024.02.09 |
---|---|
리액트 서버 컴포넌트 vs 서버 사이드 렌더링 (0) | 2024.01.27 |
타입스크립트는 자바스크립트의 상위집합(superset)일까? (4) | 2023.09.30 |
React) useState는 클로저로 동작할까? (4) | 2023.09.11 |
컴파일러는 JSX를 React.createElement() 로 바꿀까? (6) | 2023.05.04 |