๊ฐ๋ฐ์๋ฅผ ์ํ ํ๋ก ํธ์๋ Device Memory API ์ข ํฉ ๊ฐ์ด๋. ์น ์ฑ๋ฅ ์ต์ ํ, ์ ์ฌ์ ๊ธฐ๊ธฐ ์ฌ์ฉ์ ๊ฒฝํ ๊ฐ์ , ์ง์ ํ ์ ์ํ ์ ํ๋ฆฌ์ผ์ด์ ๊ตฌ์ถ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์.
ํ๋ก ํธ์๋ Device Memory API: ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ธ์ํ๋ ์น ๊ฒฝํ ๋ง๋ค๊ธฐ
์น ๊ฐ๋ฐ ์ธ๊ณ์์ ์ฐ๋ฆฌ๋ ์ข ์ข ๋น ๋ฅด๊ณ ์์ ์ ์ธ ๋คํธ์ํฌ์ ์ฐ๊ฒฐ๋ ๊ณ ์ฑ๋ฅ ๊ธฐ๊ธฐ์์ ์๋น์ค๋ฅผ ๊ตฌ์ถํ๊ณ ํ ์คํธํฉ๋๋ค. ํ์ง๋ง ์ฌ์ฉ์๋ค์ ์์ฒญ๋๊ฒ ๋ค์ํ ๊ธฐ๊ธฐ์ ํ๊ฒฝ์์ ์ฐ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฌผ์ ์ ์ํฉ๋๋ค. ๊ฐ๋ฐ์์ ๋ ธํธ๋ถ์์๋ ์๋ฒฝํ๊ฒ ์คํ๋๋ ์ธ๋ จ๋๊ณ ๊ธฐ๋ฅ์ด ํ๋ถํ ์ ํ๋ฆฌ์ผ์ด์ ์ด, ์ฐ๊ฒฐ์ด ์ ํ๋ ์ง์ญ์ ์ ๊ฐ ์ค๋งํธํฐ์์๋ ๋ต๋ตํ๊ณ ๋๋ฆฐ ๊ฒฝํ์ ์ค ์ ์์ต๋๋ค. ๊ฐ๋ฐ ํ๊ฒฝ๊ณผ ์ค์ ์ฌ์ฉ ํ๊ฒฝ ๊ฐ์ ์ด๋ฌํ ๊ฒฉ์ฐจ๋ ์ง์ ์ผ๋ก ๊ธ๋ก๋ฒํ๊ณ ํฌ์ฉ์ ์ธ ์น ๊ฒฝํ์ ๋ง๋๋ ๋ฐ ์์ด ๊ฐ์ฅ ํฐ ๊ณผ์ ์ค ํ๋์ ๋๋ค.
์ด ๊ฒฉ์ฐจ๋ฅผ ์ด๋ป๊ฒ ํด์ํ ์ ์์๊น์? ๊ณ ์ฌ์ ๊ธฐ๊ธฐ๋ฅผ ๊ฐ์ง ์ฌ์ฉ์์๊ฒ๋ ํ๋ถํ ๊ฒฝํ์ ์ ๊ณตํ๋ฉด์, ์ฑ๋ฅ์ด ๋ฎ์ ํ๋์จ์ด๋ฅผ ๊ฐ์ง ์ฌ์ฉ์์๊ฒ๋ ๋น ๋ฅด๊ณ ๊ธฐ๋ฅ์ ์ด๋ฉฐ ์์ ์ ์ธ ๊ฒฝํ์ ๋ณด์ฅํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ํด๋ต์ ์ ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐ ์์ต๋๋ค. 'ํ๋์ ํฌ๊ธฐ๊ฐ ๋ชจ๋ ๊ฒ์ ๋ง๋๋ค'๋ ์์ ์ ๊ทผ ๋ฐฉ์ ๋์ , ์ฌ์ฉ์์ ๊ธฐ๊ธฐ ์ฑ๋ฅ์ ๋ง์ถฐ ์ฌ์ฉ์ ๊ฒฝํ์ ์กฐ์ ํด์ผ ํฉ๋๋ค. ๊ฐ์ฅ ์ค์ํ๋ฉด์๋ ์ข ์ข ๊ฐ๊ณผ๋๋ ๊ธฐ๊ธฐ ์ ์ฝ ์กฐ๊ฑด ์ค ํ๋๋ ๋ฉ๋ชจ๋ฆฌ(RAM)์ ๋๋ค. ๋ฐ๋ก ์ด ์ง์ ์์ Device Memory API๊ฐ ๋ฑ์ฅํ์ฌ, ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๊ฐ ์์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฉ๋ชจ๋ฆฌ ์ธ์(memory-aware) ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๊ฐ๋จํ๋ฉด์๋ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค.
Device Memory API๋ ์ ํํ ๋ฌด์์ธ๊ฐ?
Device Memory API๋ ์ฌ์ฉ์ ๊ธฐ๊ธฐ์์ ์ฌ์ฉ ๊ฐ๋ฅํ RAM์ ์์ ๋ํ ํํธ(hint)๋ฅผ ์ ๊ณตํ๋ ์น ํ์ค์ ๋๋ค. ์ด๋ `navigator` ๊ฐ์ฒด์ ๋จ์ผ ์ฝ๊ธฐ ์ ์ฉ ์์ฑ์ ํตํด ๋ ธ์ถ๋๋ ๋งค์ฐ ๊ฐ๋จํ API์ ๋๋ค.
`navigator.deviceMemory`
์ด ์์ฑ์ ์ ๊ทผํ๋ฉด ๊ธฐ๊ธฐ์ RAM ์ฉ๋์ ๊ธฐ๊ฐ๋ฐ์ดํธ ๋จ์์ ๊ทผ์ฌ์น๋ก ๋ฐํํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ธ๋ผ์ฐ์ ์ฝ์์์ ๊ฐ๋จํ๊ฒ ํ์ธํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ์ ์์ต๋๋ค.
`console.log(navigator.deviceMemory);` // ์์ ์ถ๋ ฅ๊ฐ: 8
๋ฐํ๊ฐ๊ณผ ๊ฐ์ธ์ ๋ณด ๋ณดํธ ์ดํดํ๊ธฐ
API๊ฐ 7.89GB์ ๊ฐ์ ์ ํํ ์ซ์๋ฅผ ๋ฐํํ์ง ์๋๋ค๋ ๊ฒ์ ๋์น์ฑ์ จ์ ๊ฒ๋๋ค. ๋์ , 2์ ๊ฑฐ๋ญ์ ๊ณฑ์ผ๋ก ๋ฐ์ฌ๋ฆผ๋ ๊ฐ์ ๋ฐํํฉ๋๋ค. ์ฌ์์์๋ 0.25, 0.5, 1, 2, 4, 8 ๋ฑ๊ณผ ๊ฐ์ ๊ฐ์ ์ ์ํฉ๋๋ค. ์ด๋ ๊ฐ์ธ์ ๋ณด ๋ณดํธ๋ฅผ ์ํ ์๋์ ์ธ ์ค๊ณ์ ๋๋ค.
๋ง์ฝ API๊ฐ ์ ํํ RAM ์ฉ๋์ ์ ๊ณตํ๋ค๋ฉด, ์ด๋ ๋ธ๋ผ์ฐ์ "ํ๊ฑฐํ๋ฆฐํ (fingerprinting)"์ ์ํ ๋ ๋ค๋ฅธ ๋ฐ์ดํฐ ํฌ์ธํธ๊ฐ ๋ ์ ์์ต๋๋ค. ํ๊ฑฐํ๋ฆฐํ ์ ์ฌ๋ฌ ์์ ์ ๋ณด ์กฐ๊ฐ์ ๊ฒฐํฉํ์ฌ ์ฌ์ฉ์์ ๊ณ ์ ์๋ณ์๋ฅผ ๋ง๋ค์ด ์ถ์ ์ ์ฌ์ฉํ ์ ์๋ ๊ธฐ์ ์ ๋๋ค. ๊ฐ์ ๊ตฌ๊ฐํ(bucketing)ํจ์ผ๋ก์จ, API๋ ์ฌ์ฉ์ ๊ฐ์ธ์ ๋ณด ๋ณดํธ์ ๋ํ ์ํ์ ํฌ๊ฒ ์ฆ๊ฐ์ํค์ง ์์ผ๋ฉด์๋ ์ฑ๋ฅ ์ต์ ํ์ ์ ์ฉํ ์ถฉ๋ถํ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ ์ง๋์น๊ฒ ๊ตฌ์ฒด์ ์ธ ํ๋์จ์ด ์ธ๋ถ ์ ๋ณด๋ฅผ ๋ ธ์ถํ์ง ์์ผ๋ฉด์ ์ ์ฉํ ํํธ๋ฅผ ์ ๊ณตํ๋ ์ ํ์ ์ธ ํธ๋ ์ด๋์คํ์ ๋๋ค.
๋ธ๋ผ์ฐ์ ์ง์
์ด ๊ธ์ ์ฐ๋ ์์ ์์ Device Memory API๋ Google Chrome, Microsoft Edge, Opera๋ฅผ ํฌํจํ Chromium ๊ธฐ๋ฐ ๋ธ๋ผ์ฐ์ ์์ ์ง์๋ฉ๋๋ค. ์ด๋ ์ ์ธ๊ณ ์น ์ฌ์ฉ์์ ์๋น ๋ถ๋ถ์ ๋๋ฌํ ์ ์๋ ๊ท์คํ ๋๊ตฌ์ ๋๋ค. ์ต์ ์ง์ ์ ๋ณด๋ "Can I Use"์ ๊ฐ์ ๋ฆฌ์์ค๋ฅผ ํญ์ ํ์ธํ๊ณ , API์ ์กด์ฌ๋ฅผ ์ ์ง์ ํฅ์(progressive enhancement)์ผ๋ก ๋ค๋ฃจ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ๋ง์ฝ `navigator.deviceMemory`๊ฐ ์ ์๋์ง ์์(undefined) ๊ฒฝ์ฐ, ๊ธฐ๋ณธ ํ๊ฒฝ์ผ๋ก ์ฐ์ํ๊ฒ ๋์ฒด(gracefully fall back)ํด์ผ ํฉ๋๋ค.
์ Device Memory๊ฐ ํ๋ก ํธ์๋ ์ฑ๋ฅ์ ๊ฒ์ ์ฒด์ธ์ ์ธ๊ฐ
์์ญ ๋ ๋์ ํ๋ก ํธ์๋ ์ฑ๋ฅ ๋ ผ์๋ ๋คํธ์ํฌ ์๋์ CPU ์ฒ๋ฆฌ์ ์ง์ค๋์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์์ฐ์ ์์ถํ๊ณ , ์ฝ๋๋ฅผ ์ต์ํํ๋ฉฐ, ๋ ๋๋ง ๊ฒฝ๋ก๋ฅผ ์ต์ ํํฉ๋๋ค. ์ด ๋ชจ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํ์ง๋ง, ํนํ ์ ์ธ๊ณ ์น ํธ๋ํฝ์ ์ง๋ฐฐํ๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์์ ๋ฉ๋ชจ๋ฆฌ๋ ์กฐ์ฉํ ๋ณ๋ชฉ ํ์์ผ๋ก ๋ ์ฌ๋์ต๋๋ค.
์ต์ ์น์ฌ์ดํธ์ ๋ฉ๋ชจ๋ฆฌ ๋ณ๋ชฉ ํ์
์ต์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์ฌ์ฉํฉ๋๋ค. ์ฌ๊ธฐ์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค.
- ๋์ฉ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค: ํ๋ ์์ํฌ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ ํ์ฑ๋๊ณ , ์ปดํ์ผ๋์ด ๋ฉ๋ชจ๋ฆฌ์ ์ ์ง๋์ด์ผ ํฉ๋๋ค.
- ๊ณ ํด์๋ ์ด๋ฏธ์ง ๋ฐ ๋น๋์ค: ์ด๋ฌํ ์์ฐ์ ํนํ ๋์ฝ๋ฉ๋๊ณ ๋ ๋๋ง๋ ๋ ์๋นํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋นํฉ๋๋ค.
- ๋ณต์กํ DOM ๊ตฌ์กฐ: ๋จ์ผ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ (SPA)์ ์์ฒ ๊ฐ์ DOM ๋ ธ๋๋ ํฐ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฐจ์งํฉ๋๋ค.
- CSS ์ ๋๋ฉ์ด์ ๋ฐ WebGL: ํ๋ถํ ์๊ฐ ํจ๊ณผ๋ GPU์ ์์คํ RAM ๋ชจ๋์ ์๋นํ ๋ถ๋ด์ ์ค ์ ์์ต๋๋ค.
8GB ๋๋ 16GB RAM์ ๊ฐ์ง ๊ธฐ๊ธฐ์์๋ ์ด๊ฒ์ด ๊ฑฐ์ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. ํ์ง๋ง ์ธ๊ณ ์ฌ๋ฌ ์ง์ญ์์ ํํ ๋ณผ ์ ์๋ 1GB ๋๋ 2GB RAM๋ง ๊ฐ์ง ์ ์ฌ์ ์ค๋งํธํฐ์์๋ ์ฌ๊ฐํ ์ฑ๋ฅ ์ ํ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ๋ ๋ชจ๋ ๊ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์งํ๊ธฐ ์ํด ์ ์ฐ๊ฒ ๋๊ณ , ์ด๋ ๋ฒ๋ฒ ๊ฑฐ๋ฆฌ๋ ์ ๋๋ฉ์ด์ , ๋๋ฆฐ ๋ฐ์ ์๊ฐ, ์ฌ์ง์ด ํญ ์ถฉ๋๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ์ด๋ ๋ฉ์ธ ์ค๋ ๋๊ฐ ์ฌ์ฉ์ ์ ๋ ฅ์ ์๋ตํ๊ธฐ์ ๋๋ฌด ๋ฐ์๊ธฐ ๋๋ฌธ์ ์ฝ์ด ์น ๋ฐ์ดํ(Core Web Vitals), ํนํ ๋ค์ ํ์ธํธ์ ๋ํ ์ํธ์์ฉ(INP, Interaction to Next Paint)๊ณผ ๊ฐ์ ํต์ฌ ์ฑ๋ฅ ์งํ์ ์ง์ ์ ์ธ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
๊ธ๋ก๋ฒ ๋์งํธ ๊ฒฉ์ฐจ ํด์ํ๊ธฐ
๊ธฐ๊ธฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ ๊ธ๋ก๋ฒ ์ฌ์ฉ์ ๊ธฐ๋ฐ์ ๋ํ ๊ณต๊ฐ์ ํํ์ ๋๋ค. ์๋ฐฑ๋ง ๋ช ์ ์ฌ์ฉ์์๊ฒ ์ ๊ฐํ ์๋๋ก์ด๋ ๊ธฐ๊ธฐ๋ ์ธํฐ๋ท์ผ๋ก ํตํ๋ ์ฃผ์ํ, ์ด์ฉ๋ฉด ์ ์ผํ ๊ด๋ฌธ์ ๋๋ค. ๋ง์ฝ ๋น์ ์ ์ฌ์ดํธ๊ฐ ๊ทธ๋ค์ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ค์ด์ํจ๋ค๋ฉด, ๋น์ ์ ๋จ์ง ์ธ์ ์ ์์ ๊ฒ์ด ์๋๋ผ ์์ํ ์ฌ์ฉ์๋ฅผ ์์ ์๋ ์์ต๋๋ค. ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ธ์ํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํจ์ผ๋ก์จ, ๋น์ ์ ๊ณ ์ฌ์ ํ๋์จ์ด๋ฅผ ๊ฐ์ง ์ฌ๋๋ค๋ฟ๋ง ์๋๋ผ ๋ชจ๋ ์ฌ๋์ด ๋น์ ์ ์๋น์ค์ ์ ๊ทผํ๊ณ ์ฌ์ฉํ ์ ์๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค. ์ด๊ฒ์ ๋จ์ง ์ข์ ์ค๋ฆฌ์ผ ๋ฟ๋ง ์๋๋ผ, ๋ ๋์ ์ ์ฌ ์์ฅ์ ๋น์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด์ด์ฃผ๋ ์ข์ ๋น์ฆ๋์ค์ ๋๋ค.
์ค์ฉ์ ์ธ ์ฌ์ฉ ์ฌ๋ก ๋ฐ ๊ตฌํ ์ ๋ต
๊ธฐ๊ธฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋ ๊ฒ๊ณผ ๊ทธ์ ๋ฐ๋ผ ์กฐ์นํ๋ ๊ฒ์ ๋ณ๊ฐ์ ๋ฌธ์ ์ ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฉ๋ชจ๋ฆฌ ์ธ์ ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๋ช ๊ฐ์ง ์ค์ฉ์ ์ธ ์ ๋ต์ด ์์ต๋๋ค. ๊ฐ ์์ ์์๋ ๋ค์๊ณผ ๊ฐ์ ๊ฐ๋จํ ๋ถ๋ฅ๋ฅผ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
`const memory = navigator.deviceMemory;`
`const isLowMemory = memory && memory < 2;` // ์ด ์์ ์์๋ "์ ๋ฉ๋ชจ๋ฆฌ"๋ฅผ 2GB ๋ฏธ๋ง์ผ๋ก ์ ์ํ๊ฒ ์ต๋๋ค.
1. ์ ์ํ ์ด๋ฏธ์ง ๋ก๋ฉ
๋ฌธ์ ์ : ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ๊ฑฐ๋ํ ๊ณ ํด์๋ ํ์ด๋ก ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ๋์ญํญ์ ๋ญ๋นํ๊ณ , ์ ์ฒด ํ์ง๋ก ํ์ํ ์๋ ์๋ ๊ธฐ๊ธฐ์์ ๋ง๋ํ ์์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋นํฉ๋๋ค.
ํด๊ฒฐ์ฑ
: Device Memory API๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ ํ ํฌ๊ธฐ์ ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํฉ๋๋ค. `
๊ตฌํ:
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ์์ค๋ฅผ ๋์ ์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค. ํ์ด๋ก ์ด๋ฏธ์ง ์ปดํฌ๋ํธ๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค.
function getHeroImageUrl() {
const base_path = '/images/hero';
const isLowMemory = navigator.deviceMemory && navigator.deviceMemory < 2;
if (isLowMemory) {
return `${base_path}-low-res.jpg`; // ๋ ์๊ณ ์์ถ๋ฅ ์ด ๋์ JPEG
} else {
return `${base_path}-high-res.webp`; // ๋ ํฌ๊ณ ํ์ง์ด ์ข์ WebP
}
}
document.getElementById('hero-image').src = getHeroImageUrl();
์ด ๊ฐ๋จํ ํ์ธ์ ํตํด ์ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๊ธฐ ์ฌ์ฉ์๋ ๋น ๋ฅด๊ฒ ๋ก๋๋๊ณ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ค์ด์ํค์ง ์๋ ์๊ฐ์ ์ผ๋ก ์์ฉ ๊ฐ๋ฅํ ์ด๋ฏธ์ง๋ฅผ ์ป๊ณ , ๊ณ ์ฑ๋ฅ ๊ธฐ๊ธฐ ์ฌ์ฉ์๋ ์ต๊ณ ํ์ง์ ๊ฒฝํ์ ์ป์ ์ ์์ต๋๋ค.
2. ๋ฌด๊ฑฐ์ด ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์กฐ๊ฑด๋ถ ๋ก๋ฉ
๋ฌธ์ ์ : ์ ํ๋ฆฌ์ผ์ด์ ์ ํ๋ คํ๊ณ ์ํธ์์ฉ์ ์ธ 3D ์ ํ ๋ทฐ์ด๋ ๋ณต์กํ ๋ฐ์ดํฐ ์๊ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํฌํจ๋์ด ์์ต๋๋ค. ์ด๊ฒ๋ค์ ํ๋ฅญํ ๊ธฐ๋ฅ์ด์ง๋ง, ํ์์ ์ด์ง ์์ผ๋ฉฐ ์๋ฐฑ ํฌ๋ก๋ฐ์ดํธ(๋๋ ๋ฉ๊ฐ๋ฐ์ดํธ)์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋นํฉ๋๋ค.
ํด๊ฒฐ์ฑ : ๊ธฐ๊ธฐ๊ฐ ํธ์ํ๊ฒ ์ฒ๋ฆฌํ ์ ์์ ๋งํผ ์ถฉ๋ถํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ์ง ๊ฒฝ์ฐ์๋ง ์ด๋ฌํ ๋ฌด๊ฒ๊ณ ๋นํต์ฌ์ ์ธ ๋ชจ๋์ ๋ก๋ํฉ๋๋ค.
๋์ `import()`๋ฅผ ์ฌ์ฉํ ๊ตฌํ:
async function initializeProductViewer() {
const viewerElement = document.getElementById('product-viewer');
if (!viewerElement) return;
const hasEnoughMemory = navigator.deviceMemory && navigator.deviceMemory >= 4;
if (hasEnoughMemory) {
try {
const { ProductViewer } = await import('./libs/heavy-3d-viewer.js');
const viewer = new ProductViewer(viewerElement);
viewer.render();
} catch (error) {
console.error('3D ๋ทฐ์ด ๋ก๋ ์คํจ:', error);
// ๋์ฒด ์ ์ ์ด๋ฏธ์ง ํ์
viewerElement.innerHTML = '<img src="/images/product-fallback.jpg" alt="์ ํ ์ด๋ฏธ์ง">';
}
} else {
// ์ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๊ธฐ์์๋ ์ฒ์๋ถํฐ ์ ์ ์ด๋ฏธ์ง๋ง ํ์ํฉ๋๋ค.
console.log('์ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ง. 3D ๋ทฐ์ด๋ฅผ ๊ฑด๋๋๋๋ค.');
viewerElement.innerHTML = '<img src="/images/product-fallback.jpg" alt="์ ํ ์ด๋ฏธ์ง">';
}
}
initializeProductViewer();
์ด๋ฌํ ์ ์ง์ ํฅ์ ํจํด์ ์์(win-win)์ ๋๋ค. ๊ณ ์ฌ์ ์ฌ์ฉ์๋ ํ๋ถํ ๊ธฐ๋ฅ์ ์ป๊ณ , ์ ์ฌ์ ์ฌ์ฉ์๋ ๋ฌด๊ฑฐ์ด ๋ค์ด๋ก๋์ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋ ์์ด ๋น ๋ฅด๊ณ ๊ธฐ๋ฅ์ ์ธ ํ์ด์ง๋ฅผ ์ป์ต๋๋ค.
3. ์ ๋๋ฉ์ด์ ๋ฐ ํจ๊ณผ ๋ณต์ก๋ ์กฐ์
๋ฌธ์ ์ : ๋ณต์กํ CSS ์ ๋๋ฉ์ด์ , ํํฐํด ํจ๊ณผ, ํฌ๋ช ๋ ์ด์ด๋ ๋ฉ์ ธ ๋ณด์ผ ์ ์์ง๋ง, ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ง์ ์ปดํฌ์งํฐ ๋ ์ด์ด๋ฅผ ์์ฑํด์ผ ํ๋ฏ๋ก ๋ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋นํฉ๋๋ค. ์ ์ฌ์ ๊ธฐ๊ธฐ์์๋ ์ด๋ก ์ธํด ๋ฒ๋ฒ ๊ฑฐ๋ฆผ(stuttering)๊ณผ ์ํฌ(jank)๊ฐ ๋ฐ์ํฉ๋๋ค.
ํด๊ฒฐ์ฑ : Device Memory API๋ฅผ ์ฌ์ฉํ์ฌ ๋นํ์์ ์ธ ์ ๋๋ฉ์ด์ ์ ์ถ์ํ๊ฑฐ๋ ๋นํ์ฑํํฉ๋๋ค.
CSS ํด๋์ค๋ฅผ ์ฌ์ฉํ ๊ตฌํ:
๋จผ์ , ๋ฉ๋ชจ๋ฆฌ ํ์ธ์ ๊ธฐ๋ฐ์ผ๋ก `
` ๋๋ `` ์์์ ํด๋์ค๋ฅผ ์ถ๊ฐํฉ๋๋ค.
// ์ด ์คํฌ๋ฆฝํธ๋ฅผ ํ์ด์ง ๋ก๋ ์ด๊ธฐ์ ์คํํ์ธ์
if (navigator.deviceMemory && navigator.deviceMemory < 1) {
document.documentElement.classList.add('low-memory');
}
์ด์ ์ด ํด๋์ค๋ฅผ CSS์์ ์ฌ์ฉํ์ฌ ์ ๋๋ฉ์ด์ ์ ์ ํ์ ์ผ๋ก ๋นํ์ฑํํ๊ฑฐ๋ ๋จ์ํํ ์ ์์ต๋๋ค.
/* ๊ธฐ๋ณธ, ์๋ฆ๋ค์ด ์ ๋๋ฉ์ด์
*/
.animated-card {
transition: transform 0.5s ease-in-out, box-shadow 0.5s ease;
}
.animated-card:hover {
transform: translateY(-10px) scale(1.05);
box-shadow: 0 10px 20px rgba(0,0,0,0.2);
}
/* ์ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๊ธฐ๋ฅผ ์ํ ๋ ๊ฐ๋จํ ๋ฒ์ */
.low-memory .animated-card:hover {
transform: translateY(-2px); /* ํจ์ฌ ๊ฐ๋จํ ๋ณํ */
box-shadow: none; /* ๋น์ฉ์ด ๋ง์ด ๋๋ box-shadow ๋นํ์ฑํ */
}
/* ๋๋ ๋ค๋ฅธ ๋ฌด๊ฑฐ์ด ํจ๊ณผ๋ฅผ ์์ ํ ๋นํ์ฑํ */
.low-memory .particle-background {
display: none;
}
4. ์ ํ๋ฆฌ์ผ์ด์ ์ "๋ผ์ดํธ(Lite)" ๋ฒ์ ์ ๊ณต
๋ฌธ์ ์ : ์ผ๋ถ ๋ณต์กํ ๋จ์ผ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ, ์ฌ์ํ ์กฐ์ ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค. ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ ์ ์ฅ์, ๊ฐ์ DOM, ๊ด๋ฒ์ํ ์ปดํฌ๋ํธ ํธ๋ฆฌ๋ฅผ ๊ฐ์ถ ํต์ฌ ์ํคํ ์ฒ ์์ฒด๊ฐ ์ ์ฌ์ ๊ธฐ๊ธฐ์๋ ๋๋ฌด ๋ฌด๊ฒ์ต๋๋ค.
ํด๊ฒฐ์ฑ : ์ฑ์ "๋ผ์ดํธ(Lite)" ๋ฒ์ ์ ์ ๊ณตํ๋ ํ์ด์ค๋ถ์ด๋ ๊ตฌ๊ธ ๊ฐ์ ํ์ฌ์์ ์๊ฐ์ ์ป์ผ์ธ์. Device Memory API๋ฅผ ์ ํธ๋ก ์ฌ์ฉํ์ฌ ๊ทผ๋ณธ์ ์ผ๋ก ๋ ๊ฐ๋จํ ๋ฒ์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
๊ตฌํ:
์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ถํธ์คํธ๋ฉ ํ๋ก์ธ์ค ๋งจ ์ฒ์์ ์ํํ๋ ํ์ธ ์์ ์ด ๋ ์ ์์ต๋๋ค. ์ด๋ ์ฑ์ ๋ ๊ฐ์ง ๋ณ๋ ๋น๋๋ฅผ ํ์๋ก ํ๋ ๊ณ ๊ธ ๊ธฐ์ ์ ๋๋ค.
const MEMORY_THRESHOLD_FOR_LITE_APP = 1; // 1 GB
function bootstrapApp() {
const isLowMemory = navigator.deviceMemory && navigator.deviceMemory < MEMORY_THRESHOLD_FOR_LITE_APP;
if (isLowMemory && window.location.pathname !== '/lite/') {
// ๋ผ์ดํธ ๋ฒ์ ์ผ๋ก ๋ฆฌ๋๋ ์
window.location.href = '/lite/';
} else {
// ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์
๋ก๋
import('./main-app.js');
}
}
bootstrapApp();
"๋ผ์ดํธ" ๋ฒ์ ์ ์ต์ํ์ ํด๋ผ์ด์ธํธ ์ธก ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ ์๋ฒ ๋ ๋๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก, ํต์ฌ ๊ธฐ๋ฅ์๋ง ์์ํ๊ฒ ์ด์ ์ ๋ง์ถ ์ ์์ต๋๋ค.
`if` ๋ฌธ์ ๋์ด์: ํตํฉ ์ฑ๋ฅ ํ๋กํ ๋ง๋ค๊ธฐ
๋จ์ผ ์ ํธ์ ์์กดํ๋ ๊ฒ์ ์ํํฉ๋๋ค. ๊ธฐ๊ธฐ์ RAM์ ๋ง์ง๋ง ๋คํธ์ํฌ๊ฐ ๋งค์ฐ ๋๋ฆด ์ ์์ต๋๋ค. ๋ ๊ฐ๋ ฅํ ์ ๊ทผ ๋ฐฉ์์ Device Memory API๋ฅผ Network Information API (`navigator.connection`) ๋ฐ CPU ์ฝ์ด ์ (`navigator.hardwareConcurrency`)์ ๊ฐ์ ๋ค๋ฅธ ์ ์ํ ์ ํธ์ ๊ฒฐํฉํ๋ ๊ฒ์ ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ๊ฑธ์ณ ์์ฌ ๊ฒฐ์ ์ ์๋ดํ๋ ํตํฉ ๊ตฌ์ฑ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
function getPerformanceProfile() {
const profile = {
memory: 'high',
network: 'fast',
cpu: 'multi-core',
saveData: false,
};
// ๋ฉ๋ชจ๋ฆฌ ํ์ธ
if (navigator.deviceMemory) {
if (navigator.deviceMemory < 2) profile.memory = 'low';
else if (navigator.deviceMemory < 4) profile.memory = 'medium';
}
// ๋คํธ์ํฌ ํ์ธ
if (navigator.connection) {
profile.saveData = navigator.connection.saveData;
switch (navigator.connection.effectiveType) {
case 'slow-2g':
case '2g':
profile.network = 'slow';
break;
case '3g':
profile.network = 'medium';
break;
}
}
// CPU ํ์ธ
if (navigator.hardwareConcurrency && navigator.hardwareConcurrency < 4) {
profile.cpu = 'single-core';
}
return profile;
}
const performanceProfile = getPerformanceProfile();
// ์ด์ ๋ ๋ฏธ๋ฌํ ๊ฒฐ์ ์ ๋ด๋ฆด ์ ์์ต๋๋ค
if (performanceProfile.memory === 'low' || performanceProfile.network === 'slow') {
// ์ ํ์ง ์ด๋ฏธ์ง ๋ก๋
}
if (performanceProfile.cpu === 'single-core' && performanceProfile.memory === 'low') {
// ๋ชจ๋ ๋นํ์ ์ ๋๋ฉ์ด์
๋ฐ JS ๋นํ์ฑํ
}
ํ๊ณ, ๋ชจ๋ฒ ์ฌ๋ก ๋ฐ ์๋ฒ ์ธก ํตํฉ
Device Memory API๋ ๊ฐ๋ ฅํ์ง๋ง ์ ์คํ๊ฒ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
1. ๋ณด์ฅ์ด ์๋ ํํธ์ ๋๋ค
์ด ๊ฐ์ ํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅํ ์ฌ์ RAM์ด ์๋๋ผ ์ ์ฒด ์์คํ RAM์ ๊ทผ์ฌ์น์ ๋๋ค. ๊ณ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๊ธฐ๋ผ๋ ๋ค๋ฅธ ๋ง์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ๊ณ ์์ด ์น ํ์ด์ง๋ฅผ ์ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ฑฐ์ ๋จ์์์ง ์์ ์ ์์ต๋๋ค. ํญ์ ์ ์ง์ ํฅ์์ด๋ ์ฐ์ํ ์ ํ๋ฅผ ์ํด API๋ฅผ ์ฌ์ฉํ๊ณ , ํน์ ์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋น์ด ์๋ค๊ณ ๊ฐ์ ํ๋ ์ค์ํ ๋ก์ง์๋ ์ฌ์ฉํ์ง ๋ง์ธ์.
2. ์๋ฒ ์ธก ํด๋ผ์ด์ธํธ ํํธ์ ํ
ํด๋ผ์ด์ธํธ ์ธก์์ ์ด๋ฌํ ๊ฒฐ์ ์ ๋ด๋ฆฌ๋ ๊ฒ๋ ์ข์ง๋ง, ์ด๋ ์ฌ์ฉ์๊ฐ ์ ์ํ๊ธฐ ์ ์ ์ด๋ฏธ ์ด๊ธฐ HTML, CSS, JS๋ฅผ ๋ค์ด๋ก๋ํ๋ค๋ ์๋ฏธ์ ๋๋ค. ์ง์ ์ผ๋ก ์ต์ ํ๋ ์ฒซ ๋ก๋๋ฅผ ์ํด์๋ ํด๋ผ์ด์ธํธ ํํธ(Client Hints)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ธ๋ผ์ฐ์ ๋ ์ฒซ HTTP ์์ฒญ๊ณผ ํจ๊ป ๊ธฐ๊ธฐ ์ฑ๋ฅ ์ ๋ณด๋ฅผ ์๋ฒ๋ก ๋ณด๋ผ ์ ์์ต๋๋ค.
์๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์๋ฒ๊ฐ ์๋ต์ `Accept-CH` ํค๋๋ฅผ ๋ณด๋ด `Device-Memory` ํํธ์ ๊ด์ฌ์ด ์์์ ๋ธ๋ผ์ฐ์ ์ ์๋ฆฝ๋๋ค.
- ํค๋ ์์: `Accept-CH: Device-Memory, Viewport-Width, DPR`
- ์ดํ ํด๋น ๋ธ๋ผ์ฐ์ ์์ ๋น์ ์ ์ค๋ฆฌ์ง์ผ๋ก ๋ณด๋ด๋ ์์ฒญ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ด ํฌํจ๋ `Device-Memory` ํค๋๊ฐ ํฌํจ๋ฉ๋๋ค.
- ์์ฒญ ํค๋ ์์: `Device-Memory: 8`
์๋ฒ์์ ์ด ์ ๋ณด๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ต ๋ณธ๋ฌธ์ ๋จ์ผ ๋ฐ์ดํธ๋ฅผ ๋ณด๋ด๊ธฐ ์ ์ ๊ฒฐ์ ์ ๋ด๋ฆด ์ ์์ต๋๋ค. ๋ ๊ฐ๋จํ HTML ๋ฌธ์๋ฅผ ๋ ๋๋งํ๊ฑฐ๋, ๋ ์์ CSS/JS ๋ฒ๋ค์ ์ฐ๊ฒฐํ๊ฑฐ๋, ์ ํด์๋ ์ด๋ฏธ์ง URL์ HTML์ ์ง์ ํฌํจํ ์ ์์ต๋๋ค. ์ด๊ฒ์ด ์ ์ฌ์ ๊ธฐ๊ธฐ์ ์ด๊ธฐ ํ์ด์ง ๋ก๋๋ฅผ ์ต์ ํํ๋ ๊ฐ์ฅ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค.
3. ๊ตฌํ ํ ์คํธ ๋ฐฉ๋ฒ
๋ฉ๋ชจ๋ฆฌ ์ธ์ ๊ธฐ๋ฅ์ ํ ์คํธํ๊ธฐ ์ํด ๋ค์ํ ๋ฌผ๋ฆฌ์ ๊ธฐ๊ธฐ๋ฅผ ์์งํ ํ์๋ ์์ต๋๋ค. Chrome DevTools๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ๊ฐ์ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
- DevTools๋ฅผ ์ฝ๋๋ค (F12 ๋๋ Ctrl+Shift+I).
- ๋ช ๋ น ๋ฉ๋ด๋ฅผ ์ฝ๋๋ค (Ctrl+Shift+P).
- "Show Sensors"๋ฅผ ์ ๋ ฅํ๊ณ Enter ํค๋ฅผ ๋๋ฆ ๋๋ค.
- ์ผ์(Sensors) ํญ์์ ๋ค์ํ ํด๋ผ์ด์ธํธ ํํธ๋ฅผ ์๋ฎฌ๋ ์ดํธํ๋ ์น์ ์ ์ฐพ์ ์ ์์ต๋๋ค. ํ์ง๋ง Device Memory API ์์ฒด๋ ์ง์ ํ ์คํธํ๊ฑฐ๋ ํด๋ผ์ด์ธํธ ํํธ ํค๋๋ฅผ ๊ธฐ๋กํ๋ ์๋ฒ๋ฅผ ํตํด ํ ์คํธํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ์ง์ ์ ์ธ ํด๋ผ์ด์ธํธ ์ธก ํ ์คํธ๋ฅผ ์ํด์๋ ์์ ํ ์ ์ด๋ฅผ ์ํด ๋ธ๋ผ์ฐ์ ์์ ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์ ์ฒด์ ์ธ ํ ์คํธ๋ฅผ ์ํด ๊ธฐ๊ธฐ ์๋ฎฌ๋ ์ด์ ์ ์์กดํด์ผ ํ ์๋ ์์ต๋๋ค. ๋ง์ ์ฌ๋์๊ฒ ๋ ์ฌ์ด ๋ฐฉ๋ฒ์ ๋ก์ปฌ์์ ๊ฐ๋ฐํ ๋ ์๋ฒ๊ฐ ๋ฐ์ `Device-Memory` ํค๋ ๊ฐ์ ํ์ธํ๋ ๊ฒ์ ๋๋ค.
๊ฒฐ๋ก : ๊ณต๊ฐ์ผ๋ก ๊ตฌ์ถํ๊ธฐ
ํ๋ก ํธ์๋ Device Memory API๋ ๋จ์ํ ๊ธฐ์ ์ ๋๊ตฌ ๊ทธ ์ด์์ ๋๋ค. ๋ ๊ณต๊ฐ์ ์ด๊ณ ํฌ์ฉ์ ์ด๋ฉฐ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํ ์๋จ์ ๋๋ค. ์ ์ธ๊ณ ์ฌ์ฉ์์ ํ๋์จ์ด ํ๊ณ๋ฅผ ์ธ์ ํ๊ณ ์กด์คํจ์ผ๋ก์จ, ์ฐ๋ฆฌ๋ 'ํ๋์ ํฌ๊ธฐ๊ฐ ๋ชจ๋ ๊ฒ์ ๋ง๋๋ค'๋ ์ฌ๊ณ ๋ฐฉ์์์ ๋ฒ์ด๋ ์ ์์ต๋๋ค. ์ต๊ณ ๊ธ ์ปดํจํฐ์์ ์ ์ํ๋ ๋ณด๊ธํ ์ค๋งํธํฐ์์ ์ ์ํ๋ ๊ด๊ณ์์ด, ๊ธฐ๋ฅ์ ์ผ ๋ฟ๋ง ์๋๋ผ ์ฆ๊ฑฐ์ด ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
์๊ฒ ์์ํ์ธ์. ์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ฐ์ฅ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ ๋ถ๋ถ(ํฐ ์ด๋ฏธ์ง, ๋ฌด๊ฑฐ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ๋ณต์กํ ์ ๋๋ฉ์ด์ ๋ฑ)์ ์๋ณํ์ธ์. `navigator.deviceMemory`๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ํ์ธ ๋ก์ง์ ๊ตฌํํ์ธ์. ๊ทธ ์ํฅ์ ์ธก์ ํ์ธ์. ์ด๋ฌํ ์ ์ง์ ์ธ ๋จ๊ณ๋ฅผ ํตํด ๋ชจ๋ ์ฌ๋์ ์ํ ๋ ๋น ๋ฅด๊ณ , ๋ ํ๋ ฅ์ ์ด๋ฉฐ, ๋ ํ์๋ฐ๋ ์น์ ๋ง๋ค ์ ์์ต๋๋ค.