Skip to content

[8주차/조이] 워크북 제출합니다.#81

Open
aeongiing wants to merge 5 commits into
UMC-Inha:조이/mainfrom
aeongiing:main
Open

[8주차/조이] 워크북 제출합니다.#81
aeongiing wants to merge 5 commits into
UMC-Inha:조이/mainfrom
aeongiing:main

Conversation

@aeongiing
Copy link
Copy Markdown
Member

@aeongiing aeongiing commented May 20, 2026

✅ 워크북 체크리스트

  • 모든 핵심 키워드 정리를 마쳤나요?
  • 핵심 키워드에 대해 완벽히 이해하셨나요?
  • 이론 학습 이후 직접 실습을 해보는 시간을 가졌나요?
  • 미션을 수행하셨나요?
  • 미션을 기록하셨나요?

✅ 컨벤션 체크리스트

  • 디렉토리 구조 컨벤션을 잘 지켰나요?
  • pr 제목을 컨벤션에 맞게 작성하였나요?
  • pr에 해당되는 이슈를 연결하였나요?(중요)
  • 적절한 라벨을 설정하였나요?
  • 파트장에게 code review를 요청하기 위해 reviewer를 등록하였나요?
  • 닉네임/main 브랜치의 최신 상태를 반영하고 있는지 확인했나요?(매우 중요!)

📌 주안점

@aeongiing aeongiing self-assigned this May 20, 2026
@aeongiing aeongiing requested a review from qkrdmsthff as a code owner May 20, 2026 12:43
@aeongiing aeongiing linked an issue May 20, 2026 that may be closed by this pull request
const toggle = () => setIsOpen((prev) => !prev);

// ESC 키로 닫기
useEffect(() => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 구조에서는 사이드바가 화면에 닫혀있는 상태(isOpen === false)일 때도 브라우저 전체(document)가 ESC 키보드 입력을 계속해서 감시하게 되는 구조입니다

나중에 이 useSidebar 훅을 프로젝트 내의 여러 페이지나 다른 모달 컴포넌트에서 재사용하게 되면, 화면에 아무것도 열리지 않았는데도 백그라운드에 ESC 감지용 keydown 리스너가 수십 개씩 중첩 등록되어 메모리 누수(Memory Leak)나 원치 않는 부작용을 유발할 위험이 있다고 합니다.

오직 사이드바가 열렸을 때만 이벤트를 구독하고 닫히면 즉시 리스너가 해제되어 메모리를 안전하게 관리할 수 있도록 수정 해보면 어떨까요?

useEffect(() => {
  if (!isOpen) return;

  const handleKeyDown = (e: KeyboardEvent) => {
    if (e.key === 'Escape') close();
  };

  document.addEventListener('keydown', handleKeyDown);
  return () => document.removeEventListener('keydown', handleKeyDown);
}, [isOpen]);

hasNextPage,
refetch,
} = useInfiniteQuery({
queryKey: ['lps', order, trimmedQuery],
Copy link
Copy Markdown

@kcleverp kcleverp May 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

특정 시간동안의 여러 요청을 한번에 묶어 전달하는 디바운스를 사용해서 검색어 입력 후 로직 요청을 제어하신 점과 빈 공백이나 타이핑 중인 상태를 제어하기 위해 enabled와 isBlocked등의 안전 장치를 구축한 것이 인상적인 이번 주차 학습의 이해도가 보이는 코드 였습니다.

하지만 몇 가지 아쉬운 점이 보이는 것 같습니다

리엑트 쿼리는 querykey가 변해야 호출이 실행되는 구조입니다. 그리고 현재 querykey에는 디바운스 된trimmedQuery라는 값이 들어가 있습니다.
queryKey: ['lps', order, trimmedQuery]

따라서 enabled에 원본 query를 넣어서 타이핑 중 로직을 비 활성화하는 것은 굳이 필요치 않으며 query가 변할 때 마다 False과 True를 전환하며 내부 캐싱 상태가 복잡해질 위험이 있습니다.

또한 만약 사용자가 검색어를 지우다가 실수로 공백을 남겼을 시 query는 " "로, !query는 False가 되고 trimmedQuery는 trim으로 인해 공백이 제거되어 아무 값도 없으니 False 즉 !!trimmedQuery는 False가 됩니다.
그러면 enabled이 False가 되기에 쿼리가 비활성화 됩니다
이때 사용자는 전체 목록이 보이길 원하겠지만 아무것도 보이지 않는 문제가 발생 할 수 있습니다.
아마 이것을 해결하기 위해 isBlocked를 구상하신것 같습니다

제 제안으로는
enabled: !query || !!trimmedQuery,를 과감하게 제거하고
이것과 묶여있던
const isBlocked = query !== '' && trimmedQuery.length === 0; 이 코드도 제거하는 것은 어떨까요?
공백만 입력했을 때 발생하는 문제를 제거하고 쿼리의 기능을 온전히 살리며 직관적인 코드가 될 것 같습니다

return debouncedValue;
}

export default useDebounce;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한 가지 공유해 드리고 싶은 잠재적 버그 케이스가 있습니다. 리액트 useEffect 의존성 배열은 객체를 비교할 때 참조값(얕은 비교)을 기준으로 삼습니다. 따라서 만약 다른 팀원이 이 훅에 객체 리터럴(useDebounce({ search }, 300))을 그대로 넘기게 되면, 리렌더링마다 타이머가 계속 초기화되어 디바운스가 무력화될 위험이 있습니다.
아예 훅 내부에서 JSON.stringify와 useRef를 활용해 실제 내용물이 바뀌었는지 검증하는 방어 코드를 추가해 두면 훨씬 안전한 훅이 될 것 같습니다.

// 1. 훅 내부에 이전 값을 기억할 Ref를 하나 선언합니다.
const prevSerializedRef = useRef<string>("");

// 2. useEffect 최상단에 아래 로직을 추가하여 스킵 조건을 만듭니다.
const currentSerialized = JSON.stringify(value);
if (prevSerializedRef.current === currentSerialized) return; 

prevSerializedRef.current = currentSerialized;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chapter08_Debouncing & Throttling

4 participants