Legitgoons 님의 상세페이지[1팀 이의찬] Chapter 1-3. React, Beyond the Basics

과제 체크포인트

배포 링크

https://legitgoons.github.io/front_6th_chapter1-3

기본과제

equalities

  • shallowEquals 구현 완료
  • deepEquals 구현 완료

hooks

  • useRef 구현 완료
  • useMemo 구현 완료
  • useCallback 구현 완료
  • useDeepMemo 구현 완료
  • useShallowState 구현 완료
  • useAutoCallback 구현 완료

High Order Components

  • memo 구현 완료
  • deepMemo 구현 완료

심화 과제

hooks

  • createObserver를 useSyncExternalStore에 사용하기 적합한 코드로 개선
  • useShallowSelector 구현
  • useStore 구현
  • useRouter 구현
  • useStorage 구현

context

  • ToastContext, ModalContext 개선

과제 셀프회고

  • 지난 과제들에서는 ai 사용을 지양하고, 가능한 직접 코드를 작성하려고 해왔습니다
    • 하지만 잘 되진 않았고 막판에 그냥 막 쓰긴 했습니다.
  • 그래서 이번에는 ai를 처음부터 적극적으로 사용해서 구현해보았습니다.
    • 당연히 구현 속도가 매우 빨랐지만 스스로 코드를 제대로 이해한지는 확신하기 어려웠고, 지금도 코드를 복기하면서 학습중입니다.
    • 그래도 전반적으로는 코드 전체를 훑어보면서 학습할 수 있다는 부분에서 지난 과제들보다는 스스로 만족도가 높았습니다.
    • 산들님이 ~~~를 구현해보려고 하는데 가이드를 해줘. 처음부터 정답을 알려주지 말고 내가 충분히 학습하면서 정답에 가까워질 수 있도록 질문을 하면서 정답까지 이끌어줘.라는 방식의 프롬프트를 사용해보라고 조언해주셔서 다음 과제부터는 이렇게 해보려고 합니다.

기술적 성장

  • 리액트가 얕은 비교를 주로 사용하는 이유
  • 실제 Hook의 구현 원리들

자랑하고 싶은 코드

커밋 링크

feat: 타입 가드를 사용해 isObject 구현 refactor: equals/util에 helper함수 compareObject 구현

  • equals를 구현하면서 하나의 함수에 많은 로직들이 얽혀있다는 것을 느꼈고, 헬퍼함수들을 사용해서 선언적으로 구현해보았습니다.
  • 주요 고민 : return keysA.every((key) => compareFn(a[key], b[key])); 부분에서 로직이 달라 어떻게 해야할지 고민했습니다.
  1. compareObjectDeep / compareObjectShallow를 분리하는 것
  2. 비교함수를 매개변수로 추가하는 것
  3. 비교 수행 로직을 compareObject에 넣어두고, deepEquals / shallowEquals 를 매개변수로 받아서 이에 따라 적용
  • 위 세 가지 방안을 생각해보았는데, 우선 3번의 경우에는 순환 의존성 문제가 있어서 배제하였고, 1번의 경우에는 명시적으로 분리해주는 것은 좋지만 중복되는 코드량이 많아 2번을 선택하였습니다.
export function isObject(value?: unknown): value is Record<string, unknown> {
  return value !== null && typeof value === "object";
}

export function compareObject(
  a: Record<string, unknown>,
  b: Record<string, unknown>,
  compareFn: (a: unknown, b: unknown) => boolean = (a, b) => a === b,
): boolean {
  // 객체의 키 개수가 다른 경우 처리
  const keysA = Object.keys(a);
  const keysB = Object.keys(b);
  if (keysA.length !== keysB.length) return false;

  // 모든 키에 대해 비교 수행
  return keysA.every((key) => compareFn(a[key], b[key]));
}

개선이 필요하다고 생각하는 코드

  • 메모이제이션에 대해서 충분히 학습하지 못하고 넘어가서 아쉽습니다.
  • Toast Provider 부분도 깊게 고민하지 못하고, 우선 동작하는대로 ai에게 맡기고 넘겼는데 이 부분도 추가적으로 학습하고 싶습니다.
    • 위 두 부분을 학습해서 기술적 성장으로 옮기고 싶습니다...!!

학습 효과 분석

과제 피드백

학습 갈무리

리액트의 렌더링이 어떻게 이루어지는지 정리해주세요.

  • React의 랜더링 과정 KakaoTalk_Photo_2025-07-16-16-03-34
  • 이미지 출처 : 7팀의 병준님

메모이제이션에 대한 나의 생각을 적어주세요.

  • 아직 학습이 모자란 부분이라, 추후 정리해서 작성하겠습니다

컨텍스트와 상태관리에 대한 나의 생각을 적어주세요.

  • 컨텍스트와 상태관리를 사용했을 때의 장점과 단점은 무엇일까?
    • 장점
      • 깊은 컴포넌트 구조에서 상태 공유가 용이해진다.
      • 선언적으로 컴포넌트를 명시함으로써 가독성을 높일 수 있음
    • 단점
      • Context 값이 변경되면 해당 Context를 구독하는 모든 컴포넌트가 리렌더링
      • Context가 많아지게 된다면 Provider hell에 빠지게 됨

리뷰 받고 싶은 내용

과제 피드백

안녕하세요 의찬, 수고하셨습니다! 이번 과제는 React의 내장 훅들을 직접 구현해보며 프레임워크가 어떻게 상태를 관리하고 최적화하는지 내부 원리를 깊이 이해하는 것이 목표였습니다. React가 제공하는 편리한 API들이 내부적으로 어떤 문제를 해결하고 있는지 체험하셨기를 바랍니다.

AI 활용에 대한 성찰적인 접근이 인상적이네요. 쓰면 안된다 써야 된다 이분법 적인 부분도 아니고 적게 써야 내것이 된다도 아니고 직접 다양하게 체험하면서 나에게 맞는 사용법을 익혀가는 것이 중요한 방식이죠. 적절한 나만의 노하우들을 많이 만들고 또 많이 공유해보면 좋겠습니다.

메모이제이션과 ToastProvider에 대해 추가 학습하고 싶다고 하셨는데, 이는 실무에서도 매우 중요한 개념들입니다. 메모이제이션은 "만능이 아니다"라는 점을 인지하는 것이 중요하고, Context 분리를 통한 렌더링 최적화는 실제 프로젝트에서 자주 마주치는 과제입니다!

수고하셨습니다. 이번 Deep Dive 경험이 앞으로의 개발 여정에 든든한 기초가 되었기를 바랍니다. 클린코드 챕터도 잘 부탁드려요! 화이팅입니다 :)