React Windowing

Yejiยท2023๋…„ 11์›” 8์ผ
0

๐Ÿ”– Before Start

ํ•˜์ดํ‚น๋ค ํ”„๋กœ์ ํŠธ๊ฐ€ ์ •์‹ ์—†์ด ๋งˆ๋ฌด๋ฆฌ๋˜๊ณ  ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…์„ ๊ตฌํ˜„ํ•˜๋ฉฐ ์•„์‰ฌ์šด ์ ์ด ๊ณ„์†ํ•ด์„œ ๋งด๋Œ์•˜๋‹ค. ๋ฉค๋ฒ„ ๋ฐ์ดํ„ฐ๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜์—ˆ์„ ๋•Œ ์ฑ„ํŒ… ๋‚ด์—ญ ์ „์ฒด๋ฅผ ๋ Œ๋”๋ง ํ•ด์•ผํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๋ฏธ ๋ชจ๋“  ์„œ๋ฒ„๊ฐ€ ๋‚ด๋ ค๊ฐ„ ๋งˆ๋‹น์— ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ์ง€ ๋ง‰๋ง‰ํ•œ ๋ถ€๋ถ„๋„ ์žˆ์—ˆ์ง€๋งŒ ํ˜ผ์ž ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด windowing์„ ์ ์šฉํ•ด๋ณด๊ณ  ๋ Œ๋”๋ง ์„ฑ๋Šฅ์„ ๋น„๊ตํ•œ ํ›„, ๊ธฐ์กด ํ•˜์ดํ‚น๋ค ์ฝ”๋“œ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ–ˆ๋‹ค. ๋ฉ”์ธ์— ๋จธ์ง€๋Š” ํ•˜์ง€ ์•Š์•˜๋‹ค. ํ˜น์‹œ ๋ชจ๋ฅด๋‹ˆ...

1. ์œˆ๋„์ž‰ (Windowing)

๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด ์—„์ฒญ๋‚˜๊ฒŒ ๊ธด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐ€์ƒํ™” windowing์„ ๊ถŒ์žฅํ•œ๋‹ค๊ณ  ๋‚˜์™€์žˆ๋‹ค. ๋ฆฌ์ŠคํŠธ ์ „์ฒด๊ฐ€ ์•„๋‹Œ ๋ถ€๋ถ„์„ ๋ Œ๋”๋งํ•ด ์ƒ์„ฑ๋˜๋Š” DOM ์š”์†Œ์˜ ์ˆ˜๋ฅผ ์ค„์ด๊ณ  ์žฌ๋ Œ๋”๋ง ํ•˜๋Š” ์‹œ๊ฐ„์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

react-virtualized VS react-window

๋ฆฌ์•กํŠธ์— ์œˆ๋„์ž‰ ๊ธฐ๋ฒ•์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ‘œ์ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” react-window์™€ react-virtualized๊ฐ€ ์žˆ๋‹ค. ๋‘˜ ๋‹ค ๋˜‘๊ฐ™์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, react-virtualized์— ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ๊ณผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งŽ์•„ ๋” ๋น ๋ฅด๊ณ  ์šฉ๋Ÿ‰์ด ์ž‘์€ react-window๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๋‚˜๋Š” react-window๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. ๊ณต์‹๋ฌธ์„œ๋„ ์ž˜ ๋‚˜์™€์žˆ์–ด ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์šฐ์„  10000๊ฐœ์˜ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ฉค๋ฒ„ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ๋ฅผ ์žฌํ˜„ํ•˜๊ณ ์ž ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์ „๋ถ€ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋กœ ๊ต์ฒด๋˜๊ฒŒ๋” ๋งŒ๋“ค์—ˆ๋‹ค.

๐Ÿ“ ๊ธฐ์กด ์ฝ”๋“œ

{
// ์ƒ๋žต
   return (
    <div>
      <div className="chat-list">
        {chatList.map((chat) => {
          return <ListItem chat={chat} key={chat.key} />
        })}
      </div>
      <button onClick={handleClick}>๋ฉค๋ฒ„ ๋ณ€๊ฒฝ</button>
    </div>
  )
}

๐Ÿ“ windowing ์ ์šฉ

import { FixedSizeList as List } from 'react-window'
// ์ƒ๋žต
  return (
    <>
      <div className="chat-list">
        <List
          height={300}
          itemCount={chatList.length}
          itemSize={20}
          itemData={chatList}
        >
          {Column}
        </List>
      </div>
      <button onClick={handleClick}>๋ฉค๋ฒ„ ๋ณ€๊ฒฝ</button>
    </>
  )
}


 const Column = (props) => {
  return (
    <div className={props.index % 2 ? 'odd' : 'even'} style={props.style}>
      {props.index}
      {props.data[props.index].content}
    </div>
  )
}

export default App

2. Lighthouse

Lighthouse ๊ณต์‹๋ฌธ์„œ์— ๊ฐ ์ง€ํ‘œ๋ณ„ ์„ค๋ช…์ด ์ž์„ธํ•˜๊ฒŒ ๋‚˜์™€์žˆ๋‹ค. Lighthouse 10์„ ๊ธฐ์ค€์œผ๋กœ ์„ฑ๋Šฅ ์ธก์ • ๊ธฐ์ค€์„ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Metric์„ค๋ช…
First Contentful PaintํŽ˜์ด์ง€ ์ฒ˜์Œ ๋กœ๋“œ๋œ ์‹œ์ ๋ถ€ํ„ฐ ํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ ์˜ ์ผ๋ถ€๊ฐ€ ํ™”๋ฉด์— ๋ Œ๋”๋ง๋˜๋Š” ์‹œ์ ๊นŒ์ง€์˜ ์‹œ๊ฐ„
Speed IndexํŽ˜์ด๊ฐ€ ๋กœ๋“œ๋  ๋•Œ ์ฝ˜ํ…์ธ ๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋นจ๋ฆฌ ํ‘œ์‹œ๋˜๋Š”์ง€์˜ ์‹œ๊ฐ„
Largest Contentful PaintํŽ˜์ด์ง€๊ฐ€ ์ฒ˜์Œ ๋กœ๋“œ๋œ ์‹œ์ ์„ ๊ธฐ์ค€์œผ๋กœ ๊ฐ€์žฅ ํฐ ์ด๋ฏธ์ง€ ๋˜๋Š” ํ…์ŠคํŠธ ๋ธ”๋ก์˜ ๋ Œ๋”๋ง ์‹œ๊ฐ„
Total Blocking Time์‚ฌ์šฉ์ž๊ฐ€ ํŽ˜์ด์ง€์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์„ ๋•Œ๊นŒ์ง€ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„
Cumulative Layout Shift์‚ฌ์šฉ์ž๊ฐ€ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ ˆ์ด์•„์›ƒ ๋ณ€๊ฒฝ์„ ๊ฒฝํ—˜ํ•˜๋Š” ๋นˆ๋„
[FCP์™€ Speed Index์˜ ์ฐจ์ด]

FCP
- ์ฒซ ๋ฒˆ์งธ ์ฝ˜ํ…์ธ ๊ฐ€ ๋ธŒ๋ผ์šฐ์ € ํ™”๋ฉด์— ๊ทธ๋ ค์ง€๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ์‹œ๊ฐ„.
- ์‚ฌ์šฉ์ž๋Š” ์›นํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋˜๊ณ  ์žˆ๋Š”์ง€ ์ธ์‹ํ•  ์ˆ˜ ์žˆ๋‹ค.

Speed Index
- ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋˜๊ณ  ํ™”๋ฉด์ด ์–ผ๋งˆ๋‚˜ ๋น ๋ฅด๊ฒŒ ์ฑ„์›Œ์ง€๋Š”์ง€ ์ธก์ •ํ•œ ์‹œ๊ฐ„.
- ์‚ฌ์šฉ์ž๋Š” ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ ์ธ์‹ํ•˜๊ณ  ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Lighthouse ๊ฒฐ๊ณผ

๐Ÿ“ ๊ธฐ์กด ์ฝ”๋“œ

๐Ÿ“ windowing ์ ์šฉ

TBT (Total Blocking Time)

TBT์™€ Speed Index์—์„œ ๊ฐ€์žฅ ํฐ ์ฐจ์ด๊ฐ€ ๋‚ฌ๋‹ค. TBT๋Š” ํ™”๋ฉด์ด ๋กœ๋“œ๋˜๊ณ  ๋‚œ ์ดํ›„์— ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์งˆ์ ์œผ๋กœ ํŽ˜์ด์ง€์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์„ ๋•Œ๊นŒ์ง€์˜ ์‹œ๊ฐ„์„ ์ธก์ •ํ•œ ๊ฒƒ์ด๋‹ค. Lighthouse ์„ฑ๋Šฅ ์ธก์ •์—์„œ ๊ฐ€์žฅ ๋งŽ์€ ์ ์ˆ˜๋ฅผ ์ฐจ์ง€ํ•˜๊ณ  ์žˆ๋‹ค.

TBT๋Š” ๊ฒฐ๊ตญ FCP์™€ TTI์˜ ์‹œ๊ฐ„ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐํ•œ ๊ฒƒ์ด๋‹ค. ์ฒซ ์ฝ˜ํ…์ธ ๊ฐ€ ํ™”๋ฉด์— ๊ทธ๋ ค์ง€๊ณ (FCP) ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ๊ฒƒ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ(TTI) ์•„๋ฌด๋Ÿฐ ๋ฐ˜์‘์ด ์—†๋Š” ์‹œ๊ฐ„์ด ๊ธธ์–ด์งˆ ์ˆ˜๋ก TBT๋Š” ๊ธธ์–ด์ง€๊ณ  ์„ฑ๋Šฅ ์ ์ˆ˜๋Š” ๋‚ฎ์•„์ง„๋‹ค. ๋‚ด ์ฝ”๋“œ์—์„œ๋Š” ๋ Œ๋”๋งํ•˜๋Š” ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋‹ค๋ฅด๋‹ค๋ณด๋‹ˆ TBT ์ ์ˆ˜์—์„œ ์ฐจ์ด๊ฐ€ ๋‚œ๋‹ค๊ณ  ํŒ๋‹จํ–ˆ๋‹ค. ๋ Œ๋”๋ง ํ•ด์•ผํ•˜๋Š” ์š”์†Œ๊ฐ€ ๋งŽ์•„์งˆ ์ˆ˜๋ก ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„์ด ๋Šฆ์ถฐ์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฉค๋ฒ„ ๋ฐ์ดํ„ฐ๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝ๋˜๊ณ , ๋ณ€๊ฒฝ์„ ๋ฐ˜์˜ํ•ด ๋ Œ๋”๋งํ•˜๋Š” ๋™์•ˆ ์‚ฌ์šฉ์ž๊ฐ€ ์ฑ„ํŒ… ์ „์†ก ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ๋‹ค๋ฉด ์•„๋ฌด๋Ÿฐ ๋ฐ˜์‘๋„ ํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค.

[ TTI (Time To Interative) ]

์‚ฌ์šฉ์ž๊ฐ€ ํŽ˜์ด์ง€์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„

TBT ์ ์ˆ˜๋Š” ์–ด๋–ป๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์„๊นŒ? TBT ๊ณต์‹๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด ๋ถˆํ•„์š”ํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฅผ ์ค„์ด๋ผ๊ณ  ๋‚˜์˜จ๋‹ค. ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ๋กœ๋“œํ•˜๋Š” ๊ฒƒ๊ณผ ์ƒ๊ด€ ์—†๋Š” ๋ถˆํ•„์š”ํ•œ ์ž‘์—…์„ ํ•˜๋„๋ก ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋น„ํšจ์œจ์ ์ธ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฅผ ์ค„์—ฌ์•ผํ•œ๋‹ค๊ณ  ๊ถŒ์žฅํ•œ๋‹ค.

3. Profiler

React Profiler๋กœ๋„ ๋ Œ๋”๋ง ์„ฑ๋Šฅ์„ ์ธก์ •ํ•ด๋ดค๋‹ค.

๐Ÿ“ ๊ธฐ์กด ์ฝ”๋“œ

๐Ÿ“ windowing ์ ์šฉ

4. Chrome Performance

์œ ํœด ์ƒํƒœ๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ๋ฅผ ๋งํ•œ๋‹ค. ์œ ํœด ์‹œ๊ฐ„์ด ๊ธธ ์ˆ˜๋ก ์‚ฌ์šฉ์ž ์ž…๋ ฅ์— ๋น ๋ฅด๊ฒŒ ๋ฐ˜์‘ํ•  ์ˆ˜ ์—†์–ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ๋–จ์–ด์ง„๋‹ค. ์•ž์„œ ๋งํ•œ TBT์™€ ๊ฐ™๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

๐Ÿ“ ๊ธฐ์กด ์ฝ”๋“œ

๐Ÿ“ windowing ์ ์šฉ

๋น„ํŒ์€ ํ™˜์˜์ด์ง€๋งŒ ๋น„๋‚œ์€ ๋งˆ์Œ ์•„ํŒŒ์š”.

profile
์ฑ„์›Œ๋‚˜๊ฐ€๋Š” ๊ณผ์ •

0๊ฐœ์˜ ๋Œ“๊ธ€

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด