IT/React & Next.js

[React] 커스텀 훅으로 로직 분리

땅일단 2025. 2. 14. 00:52

나는 왜 그렇게 커스텀 훅이 헷갈렸는지 모르겠는데, 최근 원티드 강의도 듣고 코드리뷰도 하고 챗지피티랑 놀다보니 슬슬 감이 잡히는 것 같다.

 

꼭 재사용되는 로직이 아니라도, 컴포넌트의 UI와 직접적으로 관련 있는 로직이 아닐 경우 뽑아내면 각자의 역할에 충실한 코드가 된다. VAC(View Asset Component) 패턴을 구현하기 위해서는 중요한 부분이다.

 

사실 내가 이걸 왜 쓰는지 감을 못 잡았어서 그렇지 구현은 정말 별것 없다.

아래는 버튼을 누를 때마다 엘리먼트(box)를 1px씩 밑으로 내리는 로직을 useAction으로 뺀 것이다.

export default function useAction(콜백) {
    const box = useRef<HTMLDivElement | null>(null);
    const count = useRef<number>(0);
    
    const onButtonClick = () => {
        box.current!.style.top = `${count.current}px`;
        count.current += 1;
        
        콜백();
    }
    
    return {onButtonClick, box};
}

export default function Board() {
    const {onButtonClick, box} = useAction(log);
    
    // useCallback은 왜 써야 할까?
    // 혹시나 이 함수 안에서 state의 최신값이 필요하다면, 파라미터로 state를 전달한다.
    const log = useCallback(() => {
        console.log("move");
    }, []);
    
    return (
        <div>
            <div ref={box}></div>
            <button onClick={onButtonClick}>버튼</button>
        </div>
    );
}

 

Board에서는 뷰만, 그리고 실질적인 로직은 useAction에서 구현하고 있다.

 

콜백을 전달할 때는 주의할 점이 있다.

컴포넌트가 재렌더링될 때 모든 변수와 함수가 다시 만들어지는데, Board 컴포넌트에 있는 log() 역시 계속해서 만들어진다.

 

따라서 그 콜백에 의존적인 onButtonClick() 또한 다시 만들어진다.

혹시나 onButtonClick이 useEffect의 의존성에 포함된다면?

onButtonClick이 변경되지도 않았는데 Board 컴포넌트에 재렌더링이 일어났다고 useEffect가 실행될 것이다.

 

결론은 log() 함수를 useCallback()으로 감싸줘야 한다.

 

 

 


묵묵히 걸어가는 풀스택 개발자의 길 ...