refactor: Detail 렌더링 최적화#930
Conversation
nxnaxx
left a comment
There was a problem hiding this comment.
LGTM!! 첨부해 주신 사진이랑 동영상 덕분에 이해하기 편했습니다👍🏻
기존 toggle button 대신에 indicator로 바꾸니 추가 커밋들이 잘려 보이지 않아서 훨씬 좋네요. 고생하셨습니다!
chae-dahee
left a comment
There was a problem hiding this comment.
가상화와 UIUX 등 기능적으로 많은 고민이 담기신 PR 같습니다 👍 고생하셨습니다!
테스트 측정 환경, 지표 좋은 것 같습니다! 유의미한 결과가 나오면 너무 좋겠네요ㅎㅎ
| export type VirtualizedItem = | ||
| | { | ||
| type: "summary"; | ||
| data: ClusterNode["commitNodeList"]; | ||
| } | ||
| | { | ||
| type: "commit"; | ||
| data: Commit; | ||
| }; |
There was a problem hiding this comment.
타입을 따로 추출하신 이유가 궁금합니다! 다른 Detail 파일들에서도 사용이 될 예정인가요?
지금은 hook 파일에서만 사용되는 것 같아, 내부에 정의하는건 어떠신지 여쭤봅니다~
There was a problem hiding this comment.
다른 파일에서는 우선 사용 계획이 없습니다! 말씀해주신 것처럼 hook에서만 사용되고 있어서, hook 내부에 함께 두는 것이 자연스러운 것 같아요👍
There was a problem hiding this comment.
원활한 작업을 위해 현재 PR은 우선 머지하고 리팩토링 이슈를 따로 등록해서 진행하겠습니다!
| () => | ||
| new CellMeasurerCache({ | ||
| fixedWidth: true, | ||
| defaultHeight: 120, |
There was a problem hiding this comment.
상수화 작업 필요할 것 같습니다. 다음 이슈에서 적용하겠습니다!
| } | ||
|
|
||
| export type VirtualizedItem = | ||
| | { |
There was a problem hiding this comment.
There was a problem hiding this comment.
Discriminated union 방식으로 타입을 정의했고, 이를 기반으로 Type Guard 함수를 사용해서 렌더링하고 있습니다.👍
| const { cache, virtualizedItems, showScrollIndicator, handleRowsRendered } = | ||
| useVirtualizedList(commitNodeListInCluster); | ||
|
|
||
| const renderCommitItem = useCallback( |
| export type VirtualizedItem = | ||
| | { | ||
| type: "summary"; | ||
| data: ClusterNode["commitNodeList"]; |
There was a problem hiding this comment.
어차피 type에 따라 다른 구조를 가질 꺼라면
data라는 변수명 말고, 그냥 바로 clusterNode, commit 이렇게 써도 되지 않을까요? ㅎㅎ
There was a problem hiding this comment.
제가 고려했던 부분은 두 가지였습니다.
- 앞으로 더 많은 타입이 추가될 수 있는지 여부
- 일관된 패턴 적용
타입 확장을 염두에 두었고, 그럴 경우 공통된 필드명을 가져가는 것이 더 좋겠다고 생각했어요.
하지만 Detail 컴포넌트가 더 이상 확장될 계획이 없다면 개별 필드명을 사용해도 괜찮을 것 같습니다! 😊
이 부분에 대해서 어떻게 생각하시는지 궁금합니다
There was a problem hiding this comment.
제가 고려했던 부분은 두 가지였습니다.
- 앞으로 더 많은 타입이 추가될 수 있는지 여부
- 일관된 패턴 적용
타입 확장을 염두에 두었고, 그럴 경우 공통된 필드명을 가져가는 것이 더 좋겠다고 생각했어요. 하지만 Detail 컴포넌트가 더 이상 확장될 계획이 없다면 개별 필드명을 사용해도 괜찮을 것 같습니다! 😊
이 부분에 대해서 어떻게 생각하시는지 궁금합니다
@chysis
아 저도 좀 아리까리한 것 같긴한데, 더 많은 타입이 추가 확장 되더라도,
- 어차피 typeGuard를 하셨기도 하고,
- data의 type이 달라서 분기문으로 구분해서 해야 하므로,
변수명이 모호한data라는 이름 보다는 차라리 type이라도 유추할 수 있는 이름이 좋지 않을까 생각했습니다.
그런데 virtualItem 이긴 하니까, 음 item이라고 단순하게 이름짓는 것도 괜찮을 것 같기도 하구요
지금 생각해보니 data로는 어떤 의미인지 유추하기가 힘든 점이 젤 큰 (?) 이슈였던 것 같네요 😺😺😺
| [virtualizedItems] | ||
| ); | ||
|
|
||
| const rowRenderer = useCallback( |
There was a problem hiding this comment.
(사소) Detail component 가 많이 커지는 것 같은데,
VirtualList를 쓰는 경우가 아니라면, 별도의 component로 분리했어도 좋을 부분들이니
이 함수들도 detail component 바깥으로 분리해도 괜찮지 않을까용?
There was a problem hiding this comment.
해당 부분 고려해서 다음 작업에서 다뤄보겠습니다 :)
…-render-performance
adf56db
성능 측정 관련 변경 사항기존 성능 측정 지표 중 자동 스크롤 스크립트를 작성해서 스크롤 중 FPS와 frame drop rate를 측정해보았으나, 거의 차이가 없었습니다. 따라서 가상화를 통해 직접적으로 개선한 부분으로 성능 측정 지표를 수정했습니다.
성능 측정 환경은 다음과 같습니다.
성능 측정 결과결과 바로가기 에서 확인하실 수 있습니다. |




Related issue
Closes #861
Result
Before
▲ 기존 Detail 컴포넌트 구조
After
DetailSummary와commitNodeList를 react-virtualized의List로 묶어서 가상화를 적용했습니다.다음은 구현한 모습입니다.
_2025_10_06_02_55_21_522.mp4
Work list
CellMeasurer를 사용하여 각 commit item의 height를 자동 계산List컴포넌트의 onRowsRendered prop을 통해 마지막 행이 렌더링 되면 indicator를 끄도록 하여 오차 없이 구현했습니다.Discussion