본문으로 바로가기

자바스크립트 클로저 실제로 활용해서 문제 해결하면서 드디어 이해했다

나이
나이
조회수 34

배경 설명

  • ReactQuill 텍스트 에디터에서 이미지 업로드 기능 구현 중.

  • AdminEditor 컴포넌트 하위에 별도의 이미지 업로드 컴포넌트(ImageUploader) 존재.

  • ImageUploader에서 이미지 Input 받아서, Quill 에디터가 있는 부모 컴포넌트(AdminEditor)에서 사용자 입력 중 커서가 있는 위치에 해당 이미지를 삽입해야 한다.

문제

자식 컴포넌트(ImageUploader)가 부모 컴포넌트(AdminEditor)의 매번 바뀌는 ref값(커서가 있는 위치)을 어떻게 알고 그걸 활용하는가?

커서 위치 정보 = quillInstanceRef에 있음.

그러니 반드시 AdminEditor에 있는 정보이고, props로 값을 전달해줄 수도 없음.

커서 옮길 때마다 컴포넌트 리렌더링 할 거야?


해결책

AdminEditor에서 함수를 정의하고 그걸 ImageUploader에 props로 보내면 클로저를 통해서 활용할 수 있다.

// AdminEditor.tsx 

function AdminEditor = () => {
  const quillInstanceRef = useRef(null); // ← 이 변수는 AdminEditor 스코프에 있음

  const insertImage = (imageUrl: string) => {
    // 이 함수는 정의될 때 quillInstanceRef에 대한 참조를 "기억"함
    if (quillInstanceRef.current) { // ← 여전히 AdminEditor의 quillInstanceRef에 접근
      const range = quillInstanceRef.current.getSelection(true);
      // ...
    }
  };

  return (
    <>      
      {/* ... */}
      <ImageUploader
        onImageInsert={insertImage} // ← 함수를 props로 전달
      />
    </>
  );
};
  1. 함수 정의 시점: insertImage 함수가 정의될 때, 이 함수는 자신의 정의된 스코프(AdminEditor)에 있는 모든 변수들의 참조(메모리 주소값)을 기억.

  2. 함수 전달: insertImage 함수가 props로 전달될 때, 함수와 함께 클로저도 전달.

  3. ImageUploader에서 onImageInsert를 호출: AdminEditor에서 정의된 insertImage 함수 실행. 이 함수는 여전히 AdminEditor의 quillInstanceRef에 접근할 수 있다.

quillInstanceRef에 저장된 이 전달되는 것이 아니다!! quillInstanceRef참조(주소값) 이 전달되는 것이다. insertImage 함수가 클로저를 통해 원래 스코프의 변수들을 "기억"하고 있기 때문에, 어디서 호출되든 원래 변수에 접근할 수 있는 것.


참나 변수를 기억한다, 변수를 참조한다는 표현을 내가 이해 못 하고 있던 거였다

주소값 얘기였구나

진작 그렇게 설명해주지