[2팀 양진성] Chapter 4-2. 코드 관점의 성능 최적화 #17
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
과제 체크포인트
배포 링크
https://jinseoit.github.io/front_7th_chapter4-2/
과제 요구사항
배포 후 url 제출
API 호출 최적화(
Promise.all이해)SearchDialog 불필요한 연산 최적화
SearchDialog 불필요한 리렌더링 최적화
시간표 블록 드래그시 렌더링 최적화
시간표 블록 드롭시 렌더링 최적화
과제 셀프회고
기술적 성장
새로 학습한 개념
구현 과정에서의 기술적 도전과 해결
1. DND 최적화: 전역 Context의 함정
문제 상황
처음에는 하나의
DndProvider로 모든 시간표를 감싸고 있었습니다. 이로 인해 한 테이블에서 드래그를 시작하면 모든 테이블이 리렌더링되는 심각한 성능 문제가 발생했습니다.시도한 해결 방법들
첫 번째 시도: Context 분리
@dnd-kit의DndContext내부 상태 변경이 모든 하위 컴포넌트에 영향두 번째 시도: React.memo 추가
ScheduleTableCard를React.memo로 감쌌지만 여전히 리렌더링 발생세 번째 시도: useCallback으로 콜백 안정화
useCallback으로 메모이제이션했지만 문제 지속최종 해결책: DndProvider 격리 + 커스텀 비교 함수
각 테이블마다 독립적인
DndProvider를 제공하고, 철저한 메모이제이션 전략을 적용했습니다.그리고
ScheduleTableCard에 커스텀 비교 함수를 추가했습니다:핵심 인사이트
schedules === nextProps.schedules참조 비교가 핵심입니다setSchedulesMap내부에서 변경되지 않은 테이블은 원본 참조를 유지하도록 구현했습니다2. 무한 스크롤 타이밍 이슈: 체계적 디버깅의 중요성
문제 상황
SearchDialog를 처음 열었을 때 무한 스크롤이 동작하지 않았습니다. 하지만 필터를 한 번이라도 변경하면 정상 작동했습니다. 이는 초기 렌더링에만 발생하는 타이밍 문제였습니다.
증상 분석
filteredLectures.length > PAGE_SIZE(충분한 데이터 존재)첫 번째 시도: 의존성 배열 수정
이론:
lectures가 로드되면 observer를 재설정하면 동작할 것이라고 예상했지만, 여전히 동작하지 않았습니다.두 번째 시도: 수동 체크 로직 추가
너무 복잡하고 여전히 타이밍 문제 해결 못함.
세 번째 시도: useEffect 분리
로직이 복잡해지고 여전히 문제 지속.
네 번째 시도: 조건부 렌더링
savage 폴더의 참고 코드를 보고 조건부 렌더링 시도:
문제: 매번 컴포넌트가 마운트/언마운트되면서 API를 다시 호출하여 느려짐.
체계적 디버깅: Step-by-step 로깅
문제의 근본 원인을 찾기 위해 각 단계별로 console.log를 추가했습니다:
결과 분석
원인 발견: ref가
null이었습니다! Chakra UI Modal의 애니메이션으로 인해 DOM 렌더링이 지연되어, useEffect가 실행될 시점에 아직 ref가 설정되지 않았던 것입니다.최종 해결책: timeout 내부에서 ref 체크
핵심 인사이트
filteredLectures.length의존성: 필터 변경 시 observer를 재설정하여 새 데이터셋에 대응코드 품질
특히 만족스러운 구현
ScheduleDndProvider를 갖도록 설계하여 격리된 상태 관리를 구현한 점이 만족스럽습니다. 이를 통해 드래그 시 다른 테이블은 전혀 영향받지 않습니다.ScheduleTableCard에서 참조 비교 기반의 커스텀 비교 함수를 사용하여, 실제 데이터가 변경될 때만 리렌더링되도록 최적화했습니다.코드 설계 관련 고민과 결정
isOpenprop 방식으로 되돌렸습니다. 성능과 사용자 경험 사이의 트레이드오프를 고려한 결정이었습니다.학습 효과 분석
가장 큰 배움이 있었던 부분
실무 적용 가능성
과제 피드백
좋았던 부분
어려웠던 부분
리뷰 받고 싶은 내용
메모이제이션 적용 기준과 판단
무분별한 메모이제이션은 오히려 성능을 악화시킬 수 있다는 것을 알고 있습니다. 메모리 오버헤드와 비교 연산 비용이 추가되기 때문입니다. 하지만 이번 DND 최적화 케이스에서는 메모이제이션 없이는 문제를 해결할 수 없었습니다.
질문: