Amelia-Shin 님의 상세페이지[1팀 신희원] Chapter 1-3. React, Beyond the Basics

과제 체크포인트

배포 링크

https://amelia-shin.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 개선

과제 셀프회고

이번 과제에서는 2주차 과제를 진행하면서 이지훈님이 AI를 어떻게 사용하면 좋을지 추천해주신 방법으로 진행해보았다. (지훈님 덕분에 AI를 더 잘 활용할 수 있게 된?거같다. 감사합니다.) 2주차 과제까지 나는 AI에게 ~~짜줘. 형식으로 질문하여 코드를 복붙했었다. 3주차 과제부터는 AI에게 ~~를 진행하려고 하는데, 필요한 개념이 무엇인지 알려줘. 형식으로 질문하여 개념 공부를 진행했다. 물론, e2e과제를 진행할때는 너무 막막해서 어떻게 해야하지??? AI한테 정답을 알려줘. 할뻔했지만~ AI를 사용하지 않고, 지훈님에게 도움을 요청했다. 문제를 해결하기 위해 현재 코드에서 무슨 문제점이 있는지 알려주시고, 수정이 필요한 내용을 말해주셔서 수정해나갔다. 혼자 진행하다가 에러가 나길래...다른 분 PR도 참고해보고 ^^..

아, 그리고 memo , usecallback 개념 알려주신 정유열님 감사합니다. HOC 알려주신 박지수 학메님 감사합니다.

아직 리액트에 대해 개념이 부족한 나는 다른 분들에게 질문하면서 배워나간다. 이번 주차는 AI를 좀 더 잘 활용할 수 있었던 거 같고, 무작정 다른 분의 PR을 보며 베끼지 않고 스스로 해보면서 다른분들은 어떻게 했나 참고용으로 사용할 수 있었던 것 같다. *** 주의 : 과제 통과는 했지만 다시 코드를 보면서 공부 및 이해가 필요한 거 같다. 차근차근 함수 및 훅이 언제/왜 쓰이는지 공부해보자. ***

앞으로 남은 과제를 진행하면서 더 배우면서 나아갈 수 있을 거 같아 자신감이 붙는다!!!! 물론 개념 공부할꺼 짱 많음;;; 블로그도 열심히 쓰면서 개념정리도 해봐야지.

기술적 성장

useSyncExternalStore 학습

useAutoCallback 에서 의존성 없이 최신값을 업데이트를 해줄 때 왜 args(파라미터)를 넣어줄까 생각했습니다. (없어도 기본/심화 통과)

e2e 테스트 코드에서 실패하여 디버깅해서 확인해보니 장바구니를 담을 때 인자들이 들어가지 않았습니다. 그래서 데이터 값들을 넣어주기 위해 args를 사용했구나 하면서 깨달았습니다. useAutoCallback.ts

import type { AnyFunction } from "../types";
import { useCallback } from "./useCallback";
import { useRef } from "./useRef";

export const useAutoCallback = <T extends AnyFunction>(fn: T): T => {
  const ref = useRef<T>(fn);

  // 이후 렌더마다 최신값으로 업데이트
  ref.current = fn; 

  return useCallback(((...args: Parameters<T>): ReturnType<T> => ref.current(...args)) as T, []);
}

학습 효과 분석

React Hook에 대해서 어떻게 동작하는지 deepdive를 할 수 있어 좋았습니다.

과제 피드백

리액트 훅에 대해 구현하기 위해서 과제에 가이드라인이 있어서 좋았습니다.

학습 갈무리

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

렌더링 과정

리액트는 상태(state)나 props가 변경되면 컴포넌트를 리렌더링한다. 내부적으로는 Virtual DOM을 새로 만들고, 이전 Virtual DOM과 비교(diffing)해 변경된 부분만 실제 DOM에 반영한다.

렌더링 최적화 방법

  • React.memo: 상태가 자주 바뀌는 상위 컴포넌트로 인해 자식 컴포넌트가 매번 리렌더링되던 문제를 memo로 막을 수 있다.
  • useCallback: 자식에게 함수를 props로 넘길 때, 매번 새로 생성되어 리렌더링이 발생했던 걸 막기 위해 사용. > 의존성 배열을 제대로 관리하는 게 핵심이었다.
  • useMemo: 무거운 연산을 메모이제이션하거나, props로 객체를 넘기는 경우 참조 값이 계속 바뀌지 않도록 유지할 때 효과적이다.

렌더링 관련 주요 개념

Virtual DOM: 실제 DOM보다 가볍게 구성된 JS 객체. 변경사항을 빠르게 계산 가능. Reconciliation: 변경 전후의 Virtual DOM을 비교하여 최소 DOM 변경만 적용. Batched Updates: 여러 상태 업데이트를 하나로 묶어 렌더링 최적화.

렌더링 관련 라이프사이클

클래스 컴포넌트: shouldComponentUpdate, componentDidUpdate 등으로 렌더링 제어 가능. 함수형 컴포넌트: useEffect는 렌더링 이후 실행되므로, 렌더링 전에 조건 분기 필요.

렌더링에 도움 되는 주요 Hooks

useMemo | 무거운 연산 결과를 캐싱하여 재계산 방지 useCallback | 콜백 함수의 참조 유지 (props 최적화) useRef | 렌더링과 관계없는 값 유지 및 이전값 비교 useSyncExternalStore | 외부 상태 구독 시 렌더링 타이밍 제어

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

메모이제이션의 장점은 값이 바뀌었는지 확인하여 불필요한 렌더링을 줄일 수 있는 거 같습니다. 단점으로는 의존성에 어떤 값이 들어가냐에 따라 성능 최적이 될지 아닐지 갈릴 수 있을거같습니다.

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

아직 컨텍스트 개념을 잘 모르겠습니다... 컨텍스트와 상태관리에 대해 더 알아가봐야할 것 같습니다.

리뷰 받고 싶은 내용

Q1. useCallback , useAutoCallback 은 각각 어떤 때에 쓰는게 좋은가요? (의존성 없이 항상 최신 값을 사용하여 콜백 함수를 반환하는데, 실제 어디서 활용되는지 궁금하기도 합니다.) Q2. 메모이제이션을 성능 이슈를 위해 사용할 때, 적절한 사용 방법같은게 있을까요? 메모이제이션을 정말로 필요할 때만 적절하게 사용해야 할 거같은데, 무조건 사용을 한다면 좋지 않을 것 같아서 질문드립니다.

과제 피드백

안녕하세요 희원!, 수고하셨습니다. 이번 과제는 React의 핵심 훅들과 최적화 기법을 직접 구현해보면서 프레임워크가 어떻게 상태를 관리하고 렌더링을 최적화하는지 내부 원리를 체득하는 것이 목표였습니다. 특히 이론적으로 쓰는 법을 이해하는 공부와 구현을 하기 위해 필요한 것을 공부하는 것의 차이를 경험하는 시간이 되었기를 바래요.

회고에서 AI를 단순 코드 생성이 아닌 개념 학습 도구로 활용하신 접근법의 변화가 정말 인상적입니다. "~~짜줘"에서 "필요한 개념이 무엇인지 알려줘"로 질문 방식을 바꾸는 것이 좋네요. AI를 다앙한 방법을 필요에 맞게 바꿔보는 것도 현대 시대에서 중요한 능력이라 생각해새요. 무엇보다 동료들에게도 도움을 요청하며 협업으로 문제를 해결하려고 한 부분은 너무 너무 칭찬하고 싶네요. 결국 사람이죠!

코드를 살펴보니 useAutoCallback에서 args 파라미터가 필요한 이유를 e2e 테스트를 통해 직접 발견하신 점이 특히 좋았습니다. 장바구니 데이터가 전달되지 않는 문제를 디버깅하며 깨달으신 것처럼, 실제 동작을 확인하며 이해한 지식이 가장 오래 남죠. ToastProvider의 Context 분리도 잘 구현하셨고, 상태와 액션을 분리하여 불필요한 리렌더링을 방지해보는 것도 잘했습니다.

지난 3주간의 과제들을 통해서 "필요가 공부를 만든다"는 것을 느껴보며 어떻게 깊이를 학습해야하는지 이해하는 시간이 되었기를 바랍니다. 수고하셨습니다.


Q1) useCallback vs useAutoCallback 사용 시점 => useCallback은 의존성이 명확하고 변경 시점을 제어해야 할 때 사용합니다. useAutoCallback은 이벤트 핸들러처럼 항상 최신 상태를 참조해야 하지만 함수 참조는 유지해야 할 때 유용합니다.

Q2) 메모이제이션 적절한 사용법 => 원작자는 메모제이션은 대부분의 경우에는 필요가 없으니 필요할때만 하라고 말하고 있죠. 그래서 최적화가 필요하다 느껴지기 전까지는 안하는 게 일반적인 방법입니다. 그리고 마우스 드래그, keydown, timer 등 리렌더링이 빈번하게 발생하는 과정에 느리다는 것이 느껴지는 곳에 선택적으로 memo를 메모제이션을 하죠.

=> 그러나 이렇게 메모제이션을 하라고 하면 판단의 근거가 너무 주관적이게 되므로 컨벤션등은 모든 더 극단적인 형태를 띄게 됩니다. 하나는 그냥 메모제이션이 필요한 곳에 모든 메모를 붙이자는 것입니다.

=> 다른 하나는 컴포넌트를 완전히 격리해서 메모제이션을 최소화 하고 컴포넌트에서의 메모제이션을 하자는 방식이죠. 이 두가지 방식에 대해서는 한번 공부해보시면 좋겠네요.

수고하셨습니다. 깊이를 탐구하는 방법을 터득하신 만큼 앞으로의 클린코드 챕터도 기대됩니다. 화이팅입니다! :)