๐งฉ ๊ฐ์ ์คํฌ๋กค( Virtualized List ) ํ๊ฒฝ์์ ๊ด๊ณ ๋ฐฐ์น ์ด์ & ํด๊ฒฐ ์ ๋ต ๊ธฐ๋ก
์ฝ์ธ ๋ง์ผ, ๊ฑฐ๋์, ๊ฐ๊ฒฉ ๋ฆฌ์คํธ์ฒ๋ผ ๋๋ ๋ฐ์ดํฐ UI๋ฅผ ๋ค๋ฃจ๋ ์๋น์ค์์๋ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด ๋๋ถ๋ถ ๊ฐ์ ์คํฌ๋กค(virtualized list) ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ค.
ํ์ง๋งโฆ๊ด๊ณ (AdSense ๋ฑ)๋ฅผ ๋ฆฌ์คํธ ๋ด๋ถ ์์๋ก ์ฝ์
ํ๋ ์๊ฐ ๋ฌธ์ ๊ฐ ์์๋๋ค.
๐จ ๋ฌธ์ ์ํฉ
๊ฐ์ ์คํฌ๋กค ๊ตฌ์กฐ์์ ๊ด๊ณ ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ์คํธ ์์ดํ
์ฒ๋ผ ์ทจ๊ธํ๋ฉด ๋ค์ ํ์์ด ๋ฐ์ํ๋ค.
- viewport ๋ฐ ์์ โ unmount
- ๋ค์ ๋ค์ด์ค๋ฉด โ remount
- remount ์ โ ๊ด๊ณ ์ฌ์์ฒญ ๋ฐ์

๐ฅ ์ค์ ๋ก ๋ฐ์ํ๋ ๋ฆฌ์คํฌ
์ด ๊ตฌ์กฐ๊ฐ ๊ด๊ณ ์์คํ
๊ณผ ์ถฉ๋ํ๋ฉด์ ์๊ธฐ๋ ์ํฅ:
- CTR ํ๋ฝ
- RPM ํ๋ฝ
- Google Ads ํ์ง ์ ํธ ์ ํ ๊ฐ๋ฅ์ฑ
- ๋น์ ์ ์์ฒญ ํจํด ๊ฐ์ง ๊ฐ๋ฅ์ฑ
- ์ต์ ์ ๊ฒฝ์ฐ โ ๊ณ์ ๋ฆฌ์คํฌ
๐ง ์ ์ด๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊น?
์ด์ ๋ ๊ฐ์ ์คํฌ๋กค์ ๊ธฐ๋ณธ ๋์ ๋ฐฉ์ ๋๋ฌธ์ด๋ค.

๊ฐ์ ์คํฌ๋กค์ viewport ๋ด ๋ณด์ด๋ ์์๋ค์ ๋ํด์๋ง DOM์ ์ ์งํ๊ณ ๋๋จธ์ง๋ ์ ๊ฑฐํจ์ผ๋ก ์ฑ๋ฅ ์ต์ ํ๋ฅผ ํ๋ค.
๋ฐ๋ฉด ๊ด๊ณ ์ ๊ฒฝ์ฐ ํ ๋ฒ ๊ด๊ณ ๋ฅผ ๋ก๋๊ฐ ๋๋ฉด ์ฌ์์ฒญ ํน์ DOM์ ์ฌ์์ฑํ์ง ์๋ ์ด์ ๊ด๊ณ ๊ฐ ์ ์ง๋๋ค.
์ด๋ ๊ฐ์์คํฌ๋กค์ ๊ธฐ๋ณธ๋์๊ณผ ๊ตฌ์กฐ์ ์ธ ์ถฉ๋์ ๋ฐ์ํ๊ฒ ๋์ด remount ๋ ๋๋ง๊ฐ ๊ด๊ณ ์ฌ์์ฒญํ๋ ์ด์๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค.
๐ฏ ๋ชฉํ ์ ์
๊ถ๊ทน์ ์ผ๋ก ์ํ๋ ์ํ ๋ค์๊ณผ ๊ฐ๋ค:
- ๊ด๊ณ DOM์ ํญ์ ๋ง์ดํธ ์ํ ์ ์ง
- ๊ฐ์ ์คํฌ๋กค ์๋ช ์ฃผ๊ธฐ์ ์ํฅ์ ๋ฐ์ง ์๋๋ก ๋ถ๋ฆฌ
- ๊ด๊ณ ์ฌ์์ฒญ ์์ ์ฐจ๋จ
๐ ์๋ํ๋ ํด๊ฒฐ ๋ฐฉ์
1๏ธโฃ Overscan ํ์ฅ
์์ด๋์ด:
- viewport ๋ฐ ์์ญ๊น์ง DOM ์ ์ง
๊ฒฐ๊ณผ: โ ์คํจ
์ด์ :
- ์ ์ ์คํฌ๋กค ๋ฒ์ ์์ธก ๋ถ๊ฐ
- ๋น ๋ฅธ ์คํฌ๋กค ์ ์ฌ์ ํ unmount ๋ฐ์
- ๊ทผ๋ณธ ํด๊ฒฐ ๋ถ๊ฐ
2๏ธโฃ DOM KeepAlive
์์ด๋์ด:
- ๊ด๊ณ ์ปดํฌ๋ํธ ๊ฐ์ ์ ์ง
๊ฒฐ๊ณผ: โ ์คํจ
๋ฌธ์ ์ :
- ๋ด๋ถ์ ์ผ๋ก ๊ด๊ณ ์ฌ์์ฒญ ๋ฐ์
- React ๋ ๋ฒจ ์ ์ง โ ๊ด๊ณ ์์คํ ์ ์ง
- DOM ์ด๋ / ์ ๊ฑฐ ์์ฒด๊ฐ ๋ฌธ์
โ ์ต์ข ํด๊ฒฐ ์ ๋ต
์ธ๋ถ ๋ ๋๋ง + ์ขํ ๋๊ธฐํ ( Sticky Portal ์ ๋ต )
๊ด๊ณ ๋ฅผ ๊ฐ์์คํฌ๋กค ๋ฆฌ์คํธ ์์ดํ ์ผ๋ก ์ทจ๊ธํ์ง ์๋๋ค.
- Spacer ๋ฐฐ์น (๋ฆฌ์คํธ ๋ด๋ถ)
- ๋ฆฌ์คํธ ๋ด๋ถ ๊ด๊ณ ๊ฐ ๋ฐฐ์น๋์ด์ผ ํ ๊ณต๊ฐ์ ๋์ผ ํฌ๊ธฐ์ ๋น div๋ฅผ ์ฝ์ ํ๋ค
- ์ฝ์ ๋ div๋ ๋ค์ ์ญํ ์ ์ํํ๊ฒ ๋๋ค
- ๋ ์ด์์ ๊ณต๊ฐ ํ๋ณด
- ๊ฐ์ ์คํฌ๋กค ๊ณ์ฐ ์ ์ง
- ๊ด๊ณ DOM๊ณผ ๋ถ๋ฆฌ
- ๊ด๊ณ ๋ ๋ฆฝ ๋ ๋๋ง (๋ฆฌ์คํธ ์ธ๋ถ)
- ๊ด๊ณ ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ์คํธ ์ธ๋ถ์ ๋ฐฐ์นํ๊ณ position ๊ฐ์ผ๋ก
absolute๋ฅผ ์ค์ ํ๋ค.
- ์ธ๋ถ์ ๋ฐฐ์น๊ฐ ๋จ์ผ๋ก ๋ฆฌ์คํธ์ ๋๋๋ง ๋ผ์ดํ์ฌ์ดํด ์ํฅ์ ๋ฐ์ง ์๋ ์ํ๊ฐ ๋๋ฉฐ, ์ด๋ DOM์ด ์ ์ง๋์ด ๊ด๊ณ ์ฌ์์ฒญ ๋ฐ์์ ๋ฐฉ์ง ํ ์ ์๊ฒ ๋๋ค.
- ์ขํ ๊ณ์ฐ & ๋๊ธฐํ
- ์ธ๋ถ์ ๋ฐฐ์นํ ๊ด๊ณ ๋ฅผ ์คํฌ๋กค์ ์์ฐ์ค๋ฝ๊ฒ ์ด๋๋๋๋ก ํ๊ธฐ ์ํ spacer ์์น์ ๋๊ธฐํ ์์ ์ ์งํํ๋ค.
- ๊ฐ์ ์คํฌ๋กค์ ๋ชจ๋ row๊ฐ ๋์ผ ๋์ด(virtualRowHeight)๋ผ๊ณ ๊ฐ์ ํ๊ณ ์ขํ๋ฅผ ๊ณ์ฐํ๋ค:
- ์ด index๋ ์ค์ DOM index๊ฐ ์๋๋ผ, ๊ฐ์ ๋ฆฌ์คํธ ๊ธฐ์ค ๋ ผ๋ฆฌ์ ์์(positionIndex) ์ด๋ค.
- ๋ช ๋ฒ์งธ ์์น์ ๊ด๊ณ spacer๊ฐ ์กด์ฌํ๋๊ฐ? ๋ฆฌ์คํธ๋ด ์ด๋ค ์์์ ์ฝ์ ๋๋๊ฐ? ๋ฅผ ์๋ฏธํ๋ค.
- ๋์ด ์ฐจ์ด๋ก ์ธํด ๋ฐ์ํ๋ ๋์ ๋ณด์ ๊ฐ
- ๊ธฐ๋ณธ์ ๊ฐ row ์์๋ค์ ์์น๋
positionIndex * virtualRowHeight๋ก ๊ณ์ฐํ๋ฉด ์ถฉ๋ถํ๋ค. - ํ์ง๋ง ๊ด๊ณ ๊ฐ์ ์ธ๋ถ ์ฝ์ ์์๋ ์ผ๋ฐ row์ ๋ฌ๋ฆฌ ๋์ด๊ฐ ๋ ํด ์ ์๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ ๋ณด์ ์ด ํ์ํ๋ค.
- ์ผ๋ฐ row ๋์ด = 72px (virtualRowHeight),
- ๊ด๊ณ ๋์ด = 250px,
- ๋ฆฌ์คํธ ๋ด๋ถ spacer(๊ด๊ณ ์๋ฆฌ) = 250px
- ๊ฐ์ ์คํฌ๋กค์ row๋ฅผ 72px๋ก ๊ณ์ฐํ๋ฉฐ ์์ ์ฌ๋ฆฌ๋๋ฐ, ์ค์ ๋ ์ด์์์ ๊ด๊ณ ๊ฐ ๋ค์ด๊ฐ ์ง์ ๋ถํฐ ์ถ๊ฐ ๋์ด(250-72) ๋งํผ ๋ ๋ฐ๋ฆฌ๊ฒ ๋๋ค.
positionIndex * virtualRowHeight:
์์ดํ ์์น = index * rowHeight
heightCorrection:
์๋ฅผ ๋ค์ด:
๊ด๊ณ spacer๊ฐ ์ค์ ๋์ด๋ฅผ ์ ํํ ์ฐจ์งํ๊ณ ์์์๋ ๋ถ๊ตฌํ๊ณ , react-window์ ์์น ๊ณ์ฐ ๋ชจ๋ธ์์๋ ์ฌ์ ํ virtualRowHeight ๊ธฐ์ค์ผ๋ก๋ง offset์ด ๊ณ์ฐ๋๋ค
๊ทธ ๊ฒฐ๊ณผ ๊ด๊ณ ๊ฐ ์ฝ์
๋ ์ดํ๋ถํฐ ๊ฐ์ ๊ณ์ฐ ์์น์ ์ค์ ๋ ์ด์์ ์ฌ์ด์ (adHeight - virtualRowHeight)
์ด ์ค์ฐจ๋ฅผ ๋ณด์ ํ๊ธฐ ์ํ ๊ฐ์ด ๋ฐ๋ก heightCorrection ๋ค.
โ ์ต์ข ๊ฒฐ๊ณผ
- ๊ด๊ณ unmount ๋ฐ์ ์์
- ๊ด๊ณ ์ฌ์์ฒญ ์ ๊ฑฐ
- ์ต์ด ๋ก๋ ๊ด๊ณ ์ ์ง
- CTR, RPM ์ํฅ ์์
.gif?table=block&id=3048cb44-979a-80f4-9ef3-cdb7c046a5cd&cache=v2)
ย