본문 바로가기
공부기록

React 잡다한 것 (useCallback, Arrow function, Dependency array)

by RiverWon 2026. 2. 22.

세상이 참 좋아졌다. cursor로 바이브코딩이라는 걸 하고 있다. 문법을 하나도 몰라도 된다. 그래도 난 전공자니껜.. 이것저것 물어보면서 새로운 걸 배우면 잡다한 것으로 업로드할 예정이다.

const showLogs = useCallback(
  (logs) => {
    if (!logs) return;
    logs.forEach((l) => addToast(l));
  },
  [addToast]
);

LLM의 동작 과정을 로그에 기록했다가 사용자 화면에 toast해주는 핵심함수이다.

`useCallback`이 뭔지, `=>` 얘가 뭔지, `[addToast]`가 뭔지 몰라서 찾아봤다.

역시 AI에게 물어봤다. 볼 때는 끄덕이지만, 다시 보면 모르기에 글로라도 남겨둔다.

 

useCallback

showLogs라는 함수를 메모리 어딘가에 박아둔다. 

JS의 일반 함수는 컴포넌트가 다시 그려질(리렌더링)될 때마다 새로 만들어진다.

그런데 useCallback을 사용하면 메모리에 함수를 저장해 두고 재사용 가능하게 해 준다.

 

=> (Arrow function)

코드를 보면, (logs) => {...}형식의 구조로 되어 있다.

여기서 logs는 매개변수, =>은 매개변수로 실행할 내용이다.

def showlogs(logs):
	...
    #do something
    ...
    return something

파이썬은 이런 식으로 함수의 정의부터 동작까지 캐주얼룩을 입고 있는 듯한 느낌으로 구획되어있는데,

리액트나 js는 좀 유연한 느낌이다.

(매개변수는 얘니까) => {그걸로 여기 있는 것들 실행해} 형식이다.

 

[addToast]: 의존성 배열(dependency Array)

리액트에게 이 값이 바뀔 때만 함수를 새로 만들고, 아니면 이전 것을 그대로 쓰라고 명령하는 업데이트 배열 느낌이다.

이걸 안 해주면, 위 코드에서 logs의 하나하나(l)마다 반복하며 `addToast(l)`을 실행해야 하는데, addToast의 기능이 변경되어도 이전의 내용을 기반으로 함수가 실행되기 때문이다. 그래서 항상 감시(?)를 해주어야 한다

요약하면, `useCallback(실행할 함수, 감시할 함수)`의 구조이다.

케이스별로 살펴보자.

 

1. 의존성 배열이 비어있는 경우 [ ]

처음 상태 그대로를 박제

addToast함수 내용이 바뀌어도 처음에 저장된 그 addToast함수가 실행된다. (알림이 낡은 방식으로 뜬다던지 등)

-> Stale Closure라고도 한다 (오래된 클로져)

 

2. 의존성 배열 자체를 생략하는 경우

useCallback배열의 두 번째 인자를 아예 생략하는 것이다.

const function = useCallback(var1, var2)

이 구조인데, var2인 [addToast]가 없는 경우이다. 감시할 대상이 없으니, 리액트는 그냥 함수를 매번 새로 만든다. 

 

3. [addToast]가 다른 함수로 바뀌는 겨우

useCallback은 매번 리액트가 다시 그려질 때마다 이렇게 비교한다.

지난번에 내가 봤던 `addToast`가 들어있던 메모리 주소가 `0x123`이었는데, 지금은 `0x456`이네?
아, 함수 내용이 바뀌었구나!

함수 이름이 같아도 메모리 주소(Reference)가 달라지면 리액트는 바뀌었다고 판단 -> function (위에서는 showlogs)새로만듦.

 

 

js나 리액트 법칙처럼 통용되는게 있다고 한다.

함수 안에서 쓰는 외부 변수나 함수가 있다면, 고민하지 말고 의존성 배열에 다 집어넣어라