taeyeong0814 님의 상세페이지[6팀 이태영] Chapter 4-2 코드 관점의 성능 최적화

과제 체크포인트

배포링크

https://taeyeong0814.github.io/front_6th_chapter4-2/

과제 요구사항

  • 배포 후 url 제출

  • API 호출 최적화(Promise.all 이해)

  • SearchDialog 불필요한 연산 최적화

  • SearchDialog 불필요한 리렌더링 최적화

  • 시간표 블록 드래그시 렌더링 최적화

  • 시간표 블록 드롭시 렌더링 최적화

과제 셀프회고

기술적 성장

이번 과제를 통해 React 성능 최적화에 대해 많이 배웠습니다. 처음에는 React.memo, useMemo, useCallback이 그냥 "성능을 좋게 해주는 것들" 정도로만 알고 있었는데 실제로 적용해보니 각각의 역할과 사용 시점이 명확해졌습니다.

특히 드래그 앤 드롭 기능을 구현하면서 Dnd-kit 라이브러리를 처음 써봤는데 개별 DndContext를 분리하는 것이 신기했습니다. 하나의 큰 Context 대신 각 테이블마다 독립적인 Context를 만들어서 불필요한 리렌더링을 방지할 수 있다는 걸 알게 되었습니다.

그리고 useIndividualScheduleTable 같은 커스텀 훅을 만들어보면서, 로직을 재사용 가능한 단위로 분리하는 것의 중요성을 깨달았습니다. 처음에는 모든 로직을 컴포넌트 안에 때려박았는데, 훅으로 분리하니 훨씬 깔끔해지더라고요...ㅎ

무한 스크롤도 IntersectionObserver를 활용해서 구현했는데, 이전에는 스크롤 이벤트로 처리했던 것보다 훨씬 효율적이라는 걸 느꼈습니다.

코드 품질

코드를 작성하면서 가장 고민이 많았던 부분은 "어디까지 최적화해야 할까?"였습니다. 처음에는 모든 함수에 useCallback을 붙이고, 모든 계산에 useMemo를 적용했는데 나중에 보니 오히려 코드가 복잡해지고 가독성이 떨어졌습니다. 그리고 동작에도 문제가 많았습니다.

그래서 실제로 성능에 영향을 주는 부분만 선별적으로 (선별은 AI가) 최적화하기로 했습니다. React DevTools Profiler로 측정해보니 정말 필요한 부분과 그렇지 않은 부분을 구분할 수 있었습니다.

각 기능별로 컴포넌트와 훅을 분리하면서 모듈화의 장점을 체감했습니다. 나중에 기능을 수정하거나 추가할 때 훨씬 편했습니다.

학습 효과 분석

가장 인상 깊었던 건 복제된 시간표의 상태 관리 문제를 해결했을 때였습니다. 처음에는 전역 Context로 모든 걸 관리하려고 했는데 복제된 테이블에서 강의 추가/삭제가 제대로 안 되는 문제가 생겼었습니다.

"아, 이건 각 테이블마다 독립적인 상태가 필요하구나!"라는 깨달음이 있었습니다. 전역 상태와 로컬 상태를 적절히 분리하는 것의 중요성을 알게 되었습니다.

그리고 useRef를 활용해서 각 테이블의 addSchedule 함수를 등록하는 방식으로 해결했을 때, "이렇게도 할 수 있구나!"라는 신기함을 느꼈습니다.

React DevTools Profiler를 처음(?) 써봤는데, 실제로 어떤 컴포넌트가 언제 리렌더링되는지 시각적으로 볼 수 있어서 정말 유용했습니다. 이론으로만 알고 있던 최적화 기법들이 실제로 어떤 효과를 내는지 직접 확인할 수 있었습니다.

과제 피드백

아쉬웠던 점은 초기 설계 단계에서 이번에도 어떻게 해야 할 지, 그리고 성능을 충분히 고려하지 못했다는 것입니다. 나중에 최적화를 하면서 구조를 바꾸는 일이 많았습니다. 심지어 다시 시작했지요.. 다음에는 처음부터 성능을 고려한 설계를 해보고 싶습니다.

하지만 이번 과제를 통해 실제 성능 문제를 해결하는 과정에서 React 최적화 기법을 체계적으로 학습할 수 있어서 정말 좋았습니다. 특히 복제된 시간표의 상태 관리와 개별 테이블 최적화의 균형점을 찾는 과정에서 많은 것을 배웠습니다.

리뷰 받고 싶은 내용

1. 성능 최적화가 과도하지 않을까요?

제가 구현한 React 성능 최적화 전략이 적절한지 궁금합니다. 특히 useMemouseCallback을 많이 사용했는데, 혹시 과도하게 사용한 부분은 없을까요?

2. 상태 관리 구조는 어떤가요?

전역 Context와 개별 테이블 상태를 분리한 현재 구조가 괜찮은지 의견을 듣고 싶습니다.

3. 컴포넌트 설계는 적절한가요?

ScheduleTableWrapperuseIndividualScheduleTable 훅의 설계가 괜찮은지 검토해주세요. 컴포넌트의 책임 분리와 재사용성 측면에서 개선할 수 있는 부분이 있다면 구체적인 개선 방안을 제안해주시면 감사하겠습니다.

과제 피드백

수고했어요 태영!! 이번 과제는 React 애플리케이션에서 실제 성능 병목 지점을 찾고 최적화하는 것이 목표였습니다.

React.memo, useMemo, useCallback이 처음에는 단순히 "성능을 좋게 해주는 것들" 정도로 알고 있었다가 실제 적용하면서 각각의 역할과 사용 시점이 명확해졌다고 하셨는데, 이런 경험이야말로 진짜 학습이죠! 지난 시간들에 배웠던 것들이 이렇게 연결이 되었다니 좋네요.

특히 "어디까지 최적화해야 할까?"라는 고민을 하면서 처음에는 모든 함수에 useCallback을 붙이고 모든 계산에 useMemo를 적용했다가, React DevTools Profiler로 측정해보니 실제 필요한 부분만 선별적으로 최적화하게 되었다는 과정이 정말 인상적이에요. 이게 바로 성능 최적화의 핵심입니다!

복제된 시간표의 상태 관리 문제를 해결하면서 "각 테이블마다 독립적인 상태가 필요하구나!"라고 깨달은 부분도 좋았습니다. 성능최적화의 핵심이 책임의 분리에 있는 것이기에 의존하지 않는 상태와 렌더링을 잘 격리시켜서 해결해주었습니다.

Q) 성능 최적화가 과도하지 않을까요?

=> 그건 이제 태영이가 스스로 판단해야 하는 영역이겠죠. 성능 최적화가 어려운 이유는 방법이라기 보다는 "이게 맞다" 라고 하는 판단에 있으니까요. 메모이제이션이 과도한지 판단하는 방법은 React DevTools Profiler로 실제 렌더링 횟수와 시간을 측정해보는 것이에요. 의존성 배열이 자주 변경되거나 간단한 계산이라면 메모이제이션 비용이 더 클 수 있습니다. 자주 하다보면 직관적으로 판단이 될거에요!

Q) 상태 관리 구조는 어떤가요?

=> 전역 Context와 개별 테이블 상태를 분리하는 방식이 맞아요. 각 테이블이 독립적으로 동작하면서도 필요한 부분만 전역으로 관리하는 방식으로 잘 만들었네요. 현업에서는 Context의 리렌더링 범위가 너무 크기에 Zustand나 Jotai 같은 라이브러리들의 selector를 통해 리렌더링 범위를 조정하는 방식을 사용하곤 합니다.

Q) 컴포넌트 설계는 적절한가요?

=> 이건 클린코드 과제를 돌이켜보면서 한번 스스로 판단해보기 바래요. 이번 과제는 성능최적화하는 관점에서 진행을 했는데 우리가 학습해봤던 클린코드 관점으로도 이제 볼 수 있잖아요? 물론 이번 커리큘럼에서 배운 것들에 너무 매몰되어 다른 시야를 놓쳐셔도 안될것이고 복합적으로 볼 수 있어야 겠죠.

=> 적절한 컴포넌트 설계는 이제 실무에서 찾아가보길 바래요. 이렇게 설계하고 정리하는 길이 있구나 이렇게 성능을 올리고 하는 방법들이 있구나 하는 것들을 배웠으니 실무와 협업을 통해서 잘 짜맞춰 가보길 바래요

지난 10주간 너무 너무 수고 많았어요! 이번 경험들이 앞으로 개발하는 데 있어서 나 스스로 충분히 잘하려고 노력할 수 있구나, 해냈구나 하는 마음으로 새로운 것에 도전하고 성장하는 데 있어 더 쉽게 도전할 수 있게 되는 계기가 되기를 바랍니다. 화이팅입니다!