
PIVOT LABSํ
ํฌ
Core Web Vitals ์ค์ ๊ฐ์ด๋ โ LCPยทINPยทCLS๋ฅผ ๋ฐ์ดํฐ๋ก ๋ค๋ฃจ๋ ๋ฒ
๋ฐ์นญ ์ ๋ฐ๋์ ํ์ธํด์ผ ํ ์นยท๋ชจ๋ฐ์ผ ์ฑ๋ฅ ๋ฐ์ดํ(Core Web Vitals) ๊ธฐ์ค๊ณผ, ์ธก์ โ ์์ธ ๊ท์ โ ์ต์ ํ โ ์ฌ์ธก์ ์ผ๋ก ์ด์ด์ง๋ ์ค์ ๊ธฐ์ ๊ฐ์ด๋. LCPยทINPยทCLS ์ ๋ฐ ํด๋ถ + Lab/RUM ์ธก์ ๋ฐฉ๋ฒ๋ก + ๊ธฐ๋ณธ ์ต์ ํ ๊ธฐ๋ฒ.
์์ฝ
- ์ฑ๋ฅ์ ์ฃผ๊ด์ ๋๋์ด ์๋๋ผ ์ธก์ ๊ฐ๋ฅํ ์งํ๋ก ๊ด๋ฆฌํ๋ค. ์ฌ์ฉ์ ์ฒด๊ฐ์ ํต์ฌ์ Core Web Vitals(CWV) ์ธ ๊ฐ์ง โ LCP(๋ก๋ฉ), INP(๋ฐ์์ฑ), CLS(์๊ฐ์ ์์ ์ฑ).
- ํ์ ๊ธฐ์ค(Google ๊ณต์ Core Web Vitals): LCP โค 2.5s, INP โค 200ms, CLS โค 0.1 ์ด๋ฉด "์ข์". ํ์ฅ ๋ฐ์ดํฐ๋ P75(์์ 75ํผ์ผํ์ผ) ๋ก ๋ณธ๋ค.
- ์ธก์ ์ ๋ ์ถ์ด๋ค. Lab(ํฉ์ฑ) ์ ์ฌํ ๊ฐ๋ฅยท๋ฐฐํฌ ์ ์ง๋จ์ฉ, RUM(์ค์ฌ์ฉ์) ์ ์ง์ง ์ฒด๊ฐยทํ๋ ๋ํ์ฑ์ฉ. INP ์ค์ธก์ RUM์์๋ง ๋์ค๊ณ , Lab์์๋ TBT๋ฅผ ํ๋ก์๋ก ์ด๋ค.
- ์ต์ ํ๋ ์ผํ์ฑ์ด ์๋๋ผ ์ธก์ โ ์์ธ ๊ท์(attribution) โ ๊ฐ์ โ ์ฌ์ธก์ ์ ์ง์ ์ฌ์ดํด์ด๋ค.
- ์๋ ๋ณธ๋ฌธ์ ๊ฐ ๊ธฐ๋ฒ์ โ ๋ฌธ์ โ โก ์๋ฆฌ โ โข ์ ์ฉ โ โฃ ์ฝ๋ โ โค ๊ฒ์ฆ ํ๋ก ์ ๋ฆฌํ๋ค.
1. ์๋ก โ ์ฑ๋ฅ์ ์ UX์ด์ ๋น์ฆ๋์ค ๋ฌธ์ ์ธ๊ฐ
1.1 ๋ชจ๋ฐ์ผ์ด๋ผ๋ ์ ์ฝ์ด ํฐ ์คํ ํ๊ฒฝ
๋ฐ์คํฌํฑ ๊ฐ๋ฐ ํ๊ฒฝ์์ "๋น ๋ฅด๋ค"๊ณ ๋๋ ํ์ด์ง๊ฐ ์ค์ ์ฌ์ฉ์์ ๋ชจ๋ฐ์ผ์์ ๋๋ฆฐ ์ด์ ๋, ๋ ํ๊ฒฝ์ ๋ฌผ๋ฆฌ์ ์กฐ๊ฑด์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค.
- CPU: ์ค์ ๊ฐ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์ ๋จ์ผ ์ฝ์ด ์ฑ๋ฅ์ ๊ฐ๋ฐ์ฉ ๋ฐ์คํฌํฑ ๋๋น ํฌ๊ฒ ๋ฎ๋ค. JavaScript ํ์ฑยท์คํยท๋ ์ด์์ ๊ณ์ฐ์ด ๋ชจ๋ ๋ฉ์ธ ์ค๋ ๋์์ ์ผ์ด๋๋ฏ๋ก, CPU๊ฐ ๋๋ฆฌ๋ฉด ๊ฐ์ ์ฝ๋๋ผ๋ ๋ช ๋ฐฐ ๋๋ฆฌ๊ฒ ์คํ๋๋ค.
- ๋คํธ์ํฌ: ์ ๋ฃฐ๋ฌ ํ๊ฒฝ์ ๋์ญํญ๋ฟ ์๋๋ผ ์ง์ฐ(latency)๊ณผ ๋ณ๋์ฑ์ด ํฌ๋ค. TTFB์ ๋ฆฌ์์ค ๋ก๋๊ฐ ๋ค์ญ๋ ์ญํด์ง๋ค.
- ๋จ๋ง ํธ์ฐจ: ์ต์ ํ๋๊ทธ์ญ๋ถํฐ ์๋ ์ ๋ณด๊ธํ๊น์ง ์คํ ๋ถํฌ๊ฐ ๋๋ค. "๋ด ํฐ์์ ๋น ๋ฅธ๋ฐ"๊ฐ ํตํ์ง ์๋๋ค.
๋น์ : ์ฑ๋ฅ ์ต์ ํ๋ ๊ฐ์ฅ ์ข์ ํ์ ์ ์ต์ ํฐ์ด ์๋๋ผ ๋ถ๋น๋ ์งํ์ฒ ์์ 3๋ ๋ ๋ณด๊ธํฐ์ ์ฐ๋ ์ฌ์ฉ์๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๊ณํ๋ ์ผ์ด๋ค.
1.2 ์ฑ๋ฅ์ด ์งํ์ ๋ฏธ์น๋ ์ํฅ(์ผ๋ฐ๋ก )
์ผ๋ฐ์ ์ผ๋ก ๋ก๋ฉ์ด ๋๋ฆฌ๊ณ ๋ฐ์์ด ๊ตผ๋ฌ ํ์ด์ง๋ ์ดํ๋ฅ ์ด ์ค๋ฅด๊ณ ์ ํยท์ฌ๋ฐฉ๋ฌธ์ ๋ถ์ ์ ์ํฅ์ ์ค๋ค๋ ๊ฒ์ด ์ ๊ณ์ ๊ณตํต๋ ๊ด์ฐฐ์ด๋ค. ๊ตฌ์ฒด์ ์์น๋ ์๋น์คยท์ ์ข ยทํธ๋ํฝ ํน์ฑ์ ๋ฐ๋ผ ํฌ๊ฒ ๋ค๋ฅด๋ฏ๋ก ์์ฌ ๋ฐ์ดํฐ๋ก ํ์ธํด์ผ ํ๋ฉฐ, ์ฌ๊ธฐ์๋ "์ฑ๋ฅ ๊ฐ์ ์ด UXยท๋น์ฆ๋์ค ์งํ์ ์๊ด๊ด๊ณ๊ฐ ์๋ค"๋ ์์น๋ง ์ ์ ํ๋ค.
ํต์ฌ ์์ฝ: ๋ชจ๋ฐ์ผ์ ๋๋ฆฐ CPUยท๋ถ์์ ๋คํธ์ํฌยท๋์ ๋จ๋ง ํธ์ฐจ๊ฐ ์ฒด๊ฐ ์ฑ๋ฅ์ ์ข์ฐํ๋ค. ์ฑ๋ฅ์ ์ธก์ ํด ๊ด๋ฆฌํด์ผ ํ UXยท๋น์ฆ๋์ค ์งํ๋ค.
2. Core Web Vitals ์ ๋ฐ ํด๋ถ
Core Web Vitals(CWV)๋ Google์ด ์ ์ํ ์ฌ์ฉ์ ๊ฒฝํ ์งํ๋ก, ๊ฒฝํ์ ์ธ ์ถ โ ๋ก๋ฉ(LCP) ยท ๋ฐ์์ฑ(INP) ยท ์๊ฐ์ ์์ ์ฑ(CLS) โ ์ผ๋ก ๊ณ๋ํ๋ค. ์๋ ํ์ ์๊ณ๊ฐ์ Google์ด ๊ณต์ ๋ฌธ์์์ ๊ณต๊ฐํ Core Web Vitals ๊ธฐ์ค์ ๊ทธ๋๋ก ๋ฐ๋ฅธ๋ค(web.dev = Google์ด ์ด์ํ๋ ์น ๊ฐ๋ฐ ๊ณต์ ๋ฌธ์ ์ฌ์ดํธ, ๋ฐ Chrome ๊ฐ๋ฐ์ ๋ฌธ์. ์๋ฌธ ๋งํฌ๋ ๋ฌธ์ ๋ง๋ฏธ ใ์ฐธ๊ณ ์๋ฃใ ์ฐธ์กฐ).
2.1 ์งํ ๊ธฐ์คํ (Google ๊ณต์ Core Web Vitals ๊ธฐ์ค)
| ์งํ | ์ธก์ ๋์ | ์ข์(Good) | ๊ฐ์ ํ์ | ๋์จ(Poor) |
|---|---|---|---|---|
| LCP | ์ต๋ ์ฝํ ์ธ ๋ ๋ ์์ (๋ก๋ฉ) | โค 2.5s | 2.5s ~ 4.0s | > 4.0s |
| INP | ์ธํฐ๋์ ๋ฐ์์ฑ | โค 200ms | 200ms ~ 500ms | > 500ms |
| CLS | ๋์ ๋ ์ด์์ ์ด๋(์์ ์ฑ) | โค 0.1 | 0.1 ~ 0.25 | > 0.25 |
ํ๋(ํ์ฅ) ๋ฐ์ดํฐ๋ ๋ฐฉ๋ฌธ์ ๋ถํฌ์ P75(์์ 75ํผ์ผํ์ผ) ๊ฐ์ผ๋ก ํ์ ํ๋ค. "๋๋ถ๋ถ์ ์ฌ์ฉ์๊ฐ ๊ฒช๋ ์ต์ ์ ๊ฐ๊น์ด ๊ฒฝํ"์ ๊ธฐ์ค์ ์ผ๋ก ์ผ๊ธฐ ์ํจ์ด๋ค.
2.2 LCP (Largest Contentful Paint)
์ ์. ๋ทฐํฌํธ์ ๋ณด์ด๋ ์์ ์ค ๊ฐ์ฅ ํฐ ์ฝํ ์ธ ์์๊ฐ ๋ ๋๋ง๋ ์์ . ๋ณดํต ํ์ด๋ก ์ด๋ฏธ์ง, ํฐ ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง, ํฐ ํ ์คํธ ๋ธ๋ก(H1ยท๋ฌธ๋จ)์ด LCP ์์๊ฐ ๋๋ค.
๋ฌด์์ด LCP ์์์ธ๊ฐ. <img>, <image>(SVG ๋ด), background-image๊ฐ ์๋ ๋ธ๋ก, <video>์ ํฌ์คํฐ, ํฐ ํ
์คํธ ๋
ธ๋ ๋ฑ. ๋ ๋ ๊ณผ์ ์์ ๋ ํฐ ์์๊ฐ ๋ํ๋๋ฉด LCP ํ๋ณด๊ฐ ๊ฐฑ์ ๋๋ค.
ํํ ์ง์ฐ ์์ธ(4๋ ๊ตฌ๊ฐ).
- ๋๋ฆฐ ์๋ฒ ์๋ต(TTFB) โ ๋ฌธ์ ์์ฒด๊ฐ ๋ฆ๊ฒ ๋์ฐฉ.
- ๋ ๋ ์ฐจ๋จ ๋ฆฌ์์ค โ <head>์ ๋๊ธฐ CSS/JS๊ฐ ๋ ๋๋ฅผ ๋ง์.
- ๋ฆฌ์์ค ๋ก๋ ์ง์ฐ โ LCP ์ด๋ฏธ์ง๊ฐ ๋ฆ๊ฒ ๋ฐ๊ฒฌ๋๊ฑฐ๋ ์ฐ์ ์์๊ฐ ๋ฎ์.
- ํด๋ผ์ด์ธํธ ๋ ๋๋ง(CSR) โ ๋น HTML์ ๋ฐ์ ๋ค JS๋ก ๊ทธ๋ฆฌ๋ฉด, JS ์คํ์ด ๋๋์ผ LCP๊ฐ ์ฐํ.
์ง๋จ ํฌ์ธํธ. LCP๋ฅผ ์ ๋ค ๊ตฌ๊ฐ(TTFB โ ๋ฆฌ์์ค ๋ก๋ ์ง์ฐ โ ๋ก๋ ์๊ฐ โ ๋ ๋ ์ง์ฐ)์ผ๋ก ์ชผ๊ฐ์ด ์ด๋ ๊ตฌ๊ฐ์ด ํฐ์ง ๋ณธ๋ค. CSR ๊ธฐ๋ฐ ํ์ด์ง๋ LCP๊ฐ ๊ตฌ์กฐ์ ์ผ๋ก ๋ถ๋ฆฌํ๋ค.
2.3 INP (Interaction to Next Paint)
์ ์. ์ฌ์ฉ์์ ์ธํฐ๋์ (ํด๋ฆญยทํญยทํค ์ ๋ ฅ)์ ๋ํด ๋ค์ ํ๋ ์์ด ๊ทธ๋ ค์ง๊ธฐ๊น์ง์ ์ง์ฐ. ํ์ด์ง ์๋ช ๋์ ๋ฐ์ํ ์ธํฐ๋์ ๋ค ์ค ๋ํ๊ฐ(๋์ฒด๋ก ์ต์ ์ ๊ฐ๊น์ด ๊ฐ)์ ๋ณด๊ณ ํ๋ค. INP๋ ๋ค์ ์ธ ๊ตฌ๊ฐ์ ํฉ์ผ๋ก ๊ตฌ์ฑ๋๋ค.
- ์ ๋ ฅ ์ง์ฐ(Input delay) โ ์ด๋ฒคํธ๊ฐ ์ฒ๋ฆฌ๋๊ธฐ ์ , ๋ฉ์ธ ์ค๋ ๋๊ฐ ๋ค๋ฅธ ์์ ์ ์ ์ ๋ ์๊ฐ.
- ์ฒ๋ฆฌ ์๊ฐ(Processing time) โ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ค์ ๋ก ์คํ๋๋ ์๊ฐ.
- ํ๋ ์ ํ ์ด์ ์ง์ฐ(Presentation delay) โ ํธ๋ค๋ฌ ํ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ค์ ํ๋ ์์ ๊ทธ๋ฆฌ๊ธฐ๊น์ง์ ์๊ฐ.
์ FID๋ฅผ ๋์ฒดํ๋. ๊ณผ๊ฑฐ ์งํ FID(First Input Delay)๋ ์ฒซ ์ ๋ ฅ์ ์ง์ฐ๋ง ์ธก์ ํด "์ ๋ ฅ ์ง์ฐ" ํ ์กฐ๊ฐ๋ง ๋ดค๋ค. INP๋ ๋ชจ๋ ์ธํฐ๋์ ์ ์ ์ฒด ์ง์ฐ(์ฒ๋ฆฌ+ํ๋ ์ ํ ์ด์ ํฌํจ) ์ ๋ณด๋ฏ๋ก ์ค์ ๋ฐ์์ฑ์ ํจ์ฌ ์ ํํ ๋ฐ์ํ๋ค. INP๋ 2024๋ 3์ CWV์ ๋ฐ์์ฑ ์งํ๋ก ์ ์ ์ฑํ๋์ด FID๋ฅผ ๋์ฒดํ๋ค.
์ ํ ์์ธ. ๊ธด ์์ (Long Task)์ผ๋ก ๋ฉ์ธ ์ค๋ ๋๊ฐ ์ ์ ๋จ, ๊ณผ๋ํ๊ฑฐ๋ ๋ฌด๊ฑฐ์ด ์ด๋ฒคํธ ํธ๋ค๋ฌ, ํฐ DOM ๊ฐฑ์ , ์๋ํํฐ ์คํฌ๋ฆฝํธ์ ๋ฉ์ธ ์ค๋ ๋ ๊ฒฝ์.
2.4 CLS (Cumulative Layout Shift)
์ ์. ๋ก๋ฉยท์ธํฐ๋์ ์ค ์๊ธฐ์น ์๊ฒ ์์๊ฐ ๋ฐ๋ฆฌ๋ ์์ ๋์ ์น(์ด๋ ์ํฅ ร ์ด๋ ๊ฑฐ๋ฆฌ). ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ๋๋ฅด๋ ค๋ ์๊ฐ ๋ ์ด์์์ด ๋ฐ๋ ค ์คํฐ์น๊ฐ ๋๋ ๊ฒฝํ์ด CLS๋ก ๊ณ๋๋๋ค.
ํํ ์์ธ.
- ํฌ๊ธฐ ๋ฏธ์ง์ ์ด๋ฏธ์ง/๋ฏธ๋์ด โ ๋ก๋ ์ ๊ณต๊ฐ์ด ์์ฝ๋์ง ์์ ๋ก๋ ์ ๋ฐ๋ฆผ.
- ๋์ ์ฝ์ ์ฝํ ์ธ โ ๋ฐฐ๋ยท์๋ฆผยท๊ด๊ณ ๊ฐ ๊ธฐ์กด ์ฝํ ์ธ ์์ ๋ผ์ด๋ฆ.
- ์นํฐํธ FOIT/FOUT โ ํฐํธ ๊ต์ฒด ์ ๊ธ์ ํฌ๊ธฐยท์๊ฐ์ด ๋ฐ๋๋ฉฐ ์ฌ๋ฐฐ์น.
- ๊ด๊ณ ยท์๋ฒ ๋ โ ํฌ๊ธฐ๊ฐ ๊ฐ๋ณ์ ์ธ ์๋ํํฐ ์ฝ์ ๋ฌผ.
2.5 ๋ณด์กฐ ์งํ โ FCPยทTTFBยทTBTยทSpeed Index
| ์งํ | ์๋ฏธ | CWV์์ ๊ด๊ณ |
|---|---|---|
| TTFB (Time To First Byte) | ์ฒซ ๋ฐ์ดํธ ๋์ฐฉ๊น์ง | LCP์ ํ์ ๊ตฌ๊ฐ. ์๋ฒยท๋คํธ์ํฌ ๋ณ๋ชฉ ์ง๋จ |
| FCP (First Contentful Paint) | ์ฒซ ์ฝํ ์ธ ๋ ๋ | LCP์ ์ ํ ์งํ. ๋ ๋ ์ฐจ๋จ ์ง๋จ |
| TBT (Total Blocking Time) | ๋ก๋ ์ค ๋ฉ์ธ ์ค๋ ๋๊ฐ ๋งํ ์ด ์๊ฐ | Lab์์ INP/๋ฐ์์ฑ์ ํ๋ก์ |
| Speed Index | ํ๋ฉด์ด ์๊ฐ์ ์ผ๋ก ์ฑ์์ง๋ ์๋ | ๋ก๋ฉ ์ฒด๊ฐ ๋ณด์กฐ ์งํ |
ํต์ฌ ์์ฝ: CWV๋ ๋ก๋ฉ(LCP)ยท๋ฐ์์ฑ(INP)ยท์์ ์ฑ(CLS) ์ธ ์ถ์ด๋ฉฐ ๊ธฐ์ค์ 2.5s / 200ms / 0.1. ๋ณด์กฐ ์งํ(TTFBยทFCPยทTBTยทSI)๋ ๊ฐ CWV์ ์์ธ ๊ตฌ๊ฐ์ ํ๊ณ ๋ค ๋ ์ด๋ค.
3. Lab(ํฉ์ฑ) vs RUM(์ค์ฌ์ฉ์) โ ์ธก์ ์ ๋ ์ถ
์ฑ๋ฅ ๋ฐ์ดํฐ์๋ ์ฑ๊ฒฉ์ด ๋ค๋ฅธ ๋ ์ข ๋ฅ๊ฐ ์๊ณ , ๋ ์ค ํ๋๋ง ๋ณด๋ฉด ๋ฐ๋์ ์คํํ๋ค.
3.1 Lab(ํฉ์ฑ, Synthetic)
ํต์ ๋ ํ๊ฒฝ์์ ์๋ํ ๋๊ตฌ๊ฐ ํ์ด์ง๋ฅผ ๋ก๋ํด ์ธก์ ํ๋ค.
- ์ฅ์ : ์ฌํ์ฑ(๊ฐ์ ์กฐ๊ฑด ๋ฐ๋ณต), ๋ฐฐํฌ ์ ์ธก์ ๊ฐ๋ฅ, ์์ธํ ์์ธ ๋ถ์(ํธ๋ ์ด์ค) ๊ฐ๋ฅ.
- ํ๊ณ: ์ค์ ์ฌ์ฉ์์ ๋ค์ํ ๊ธฐ๊ธฐยท๋คํธ์ํฌยท์ธํฐ๋์ ์ ๋ด์ง ๋ชปํ๋ค. ํนํ ์ค์ ์ธํฐ๋์ ์ด ์์ผ๋ฏ๋ก INP๋ฅผ ์ธก์ ํ ์ ์๋ค.
3.2 RUM(์ค์ฌ์ฉ์, Real User Monitoring)
์ค์ ๋ฐฉ๋ฌธ์์ ๋ธ๋ผ์ฐ์ ์์ ์ฑ๋ฅ ๋ฐ์ดํฐ๋ฅผ ์์งํ๋ค.
- ์ฅ์ : ์ง์ง ์ฒด๊ฐ ์ฑ๋ฅ, ํ๋ ๋ํ์ฑ(์ค์ ๊ธฐ๊ธฐยทํ์ ๋ถํฌ).
- ํ๊ณ: ๋ฐฐํฌ ํ์๋ง ๋ฐ์ดํฐ๊ฐ ์์ด๊ณ , ํ๊ฒฝ ํธ์ฐจ๊ฐ ์ปค ๊ฐ๋ณ ์์ธ ๊ท๋ช ์ด ์ด๋ ต๋ค.
3.3 ํต์ฌ ์๋ฆฌ โ INP๋ ์ Lab์์ ์ ๋์ค๋
INP๋ ์ค์ ์ธํฐ๋์ ์ด ์์ด์ผ ์ธก์ ๋๋ค. Lab์ ์๋ ๋ก๋๋ง ํ๊ณ ์ฌ๋์ ํด๋ฆญยท์ ๋ ฅ์ด ์์ผ๋ฏ๋ก INP๋ฅผ ์ง์ ์ธก์ ํ์ง ๋ชปํ๋ค. ๊ทธ๋์:
- Lab์์๋ TBT(Total Blocking Time) ๋ฅผ ๋ฐ์์ฑ์ ํ๋ก์๋ก ์ฌ์ฉํ๋ค. TBT๊ฐ ํฌ๋ฉด ์ธํฐ๋์ ๋ ๋๋ฆด ๊ฐ๋ฅ์ฑ์ด ๋๋ค.
- ์ค์ธก INP๋ RUM/ํ๋ ๋ฐ์ดํฐ์์๋ง ์ป๋๋ค.
3.4 75๋ฒ์งธ ๋ฐฑ๋ถ์์(P75) โ ๊ณต์ ํ๊ฐ ๋ฐฉ๋ฒ
Google์ Core Web Vitals๋ฅผ ํ์ด์ง ๋ฐฉ๋ฌธ ๋ถํฌ์ 75๋ฒ์งธ ๋ฐฑ๋ถ์์(75th percentile, ํต์นญ P75) ๊ฐ์์ ํ๊ฐํ๋ค. ์ด๋ web.devยทChrome ๊ฐ๋ฐ์ ๋ฌธ์์ ๋ช ์๋ ๊ณต์ ํ๊ฐ ๋ฐฉ๋ฒ์ด๋ฉฐ, "ํฉ๊ฒฉ/๋ถํฉ๊ฒฉ" ํ์ ๋ ์ด P75 ๊ฐ ๊ธฐ์ค์ด๋ค. ํ๊ท ์ ์์์ ๋น ๋ฅธ ์ธ์ ์ ๊ฐ๋ ค ๋ฌธ์ ๋ฅผ ๊ฐ์ถ์ง๋ง, 75๋ฒ์งธ ๋ฐฑ๋ถ์์๋ "๋ฐฉ๋ฌธ์ ์ฝ 3/4๊ฐ ์ด ๊ฐ๋ณด๋ค ์ข๊ฒ ๊ฒฝํํ๋ค"๋ ๋ณด์์ ๊ธฐ์ค์ ์ ์ ๊ณตํ๋ค.
ํต์ฌ ์์ฝ: Lab์ ๋ฐฐํฌ ์ ์ฌํยท์์ธ๋ถ์, RUM์ ๋ฐฐํฌ ํ ์ค์ฒด๊ฐ. INP ์ค์ธก์ RUM์์๋ง ๋์ค๊ณ Lab์ TBT๋ก ๋์ ๋ณธ๋ค. ํ๋๋ P75๋ก ํ์ ํ๋ค.
4. ์ธก์ ๋ฐฉ๋ฒ๋ก โ ์ ๋ขฐํ ์ ์๋ ์์น๋ฅผ ์ป๋ ๋ฒ
์์น๋ ์ด๋ป๊ฒ ์ธก์ ํ๋๋์ ๋ฐ๋ผ ํฌ๊ฒ ๋ฌ๋ผ์ง๋ค. ๋ฐฉ๋ฒ๋ก ์ด ํ๋ค๋ฆฌ๋ฉด ๊ฐ์ ์ฌ๋ถ๋ฅผ ํ๋จํ ์ ์๋ค.
4.1 ์ค๋กํ๋ง โ ์กฐ๊ฑด์ ์ฌ์ฉ์์๊ฒ ๋ง์ถ๋ค
- CPU ์ฌ๋ก์ฐ๋ค์ด: ๊ฐ๋ฐ ๊ธฐ๊ธฐ์ CPU๋ฅผ ์ธ์์ ์ผ๋ก ๋๋ฆฌ๊ฒ(์: 4ร/6ร ์ฌ๋ก์ฐ๋ค์ด) ์ค์ ํด ๋ณด๊ธํ ๋ชจ๋ฐ์ผ์ ๊ทผ์ ์ํจ๋ค.
- ๋คํธ์ํฌ ์กฐ๊ฑด: ๋์ญํญยท์ง์ฐ์ ์ ํ(์: ๋๋ฆฐ 4G ํ๋กํ์ผ)ํด ์ค์ ํ์ ์ ๊ทผ์ ์ํจ๋ค.
- ์ฃผ์: ์ค๋กํ๋ง ์ค์ ๊ณผ ์คํ ๊ธฐ๊ธฐ์ ๋ฐ๋ผ Lab ๊ฐ์ ํฌ๊ฒ ๋ฌ๋ผ์ง๋ค. ๋ฐ๋ผ์ Lab ์์น๋ "์ ๋๊ฐ"์ด ์๋๋ผ ๋์ผ ์กฐ๊ฑด์์์ ์๋ ๋น๊ต(๊ฐ์ ์ /ํ) ๋ก ํด์ํด์ผ ํ๋ค.
4.2 First View vs Repeat View, ๊ทธ๋ฆฌ๊ณ ์ค์๊ฐ
- First View(์ฒซ ๋ฐฉ๋ฌธ) ์ Repeat View(์ฌ๋ฐฉ๋ฌธ) ๋ ์บ์ ์ํฅ์ผ๋ก ๊ฐ์ด ๋ค๋ฅด๋ค. ๋ชฉ์ ์ ๋ง๋ ๊ฒ์ ๋ณธ๋ค(์ ๊ท ์ ์ ์ต์ ํ๋ฉด First View).
- ๋จ์ผ ์ธก์ ์ ๋ ธ์ด์ฆ๊ฐ ํฌ๋ค. ์ฌ๋ฌ ํ ์ธก์ ํ ์ค์๊ฐ(median) ์ ์ฌ์ฉํ๋ค. ํ ๋ฒ์ ์ข์/๋์ ๊ฐ์ ์์ง ์๊ธฐ ์ํจ์ด๋ค.
4.3 ์์ธ ๊ท์(attribution) โ DevTools Performance
๋ณ๋ชฉ์ "๋๋"์ผ๋ก ์ฐพ์ง ๋ง๊ณ ํธ๋ ์ด์ค๋ก ๊ท์ํ๋ค. Chrome DevTools์ Performance ํจ๋์ด ํ์ค ๋๊ตฌ๋ค.
- Bottom-Up vs Call Tree
- Bottom-Up(self time): ๊ฐ ํจ์๊ฐ ์๊ธฐ ์์ ์์ ์ค์ ๋ก ์๋นํ CPU ์๊ฐ. "์ค์ ๋ก ๋ฌด๊ฑฐ์ด ํจ์"๋ฅผ ์ฐพ๋๋ค.
- Call Tree(total time): ์์ ํธ์ถ์ ํฌํจํ ์ด ์๊ฐ. "์ด๋ ํธ์ถ ๊ฒฝ๋ก๊ฐ ๋ฌด๊ฑฐ์ด๊ฐ"๋ฅผ ๋ณธ๋ค.
- ์ค๋ฌด ์์: Bottom-Up์ผ๋ก self time์ด ํฐ ํญ๋ชฉ์ ์ฐพ๊ณ โ Call Tree๋ก ํธ์ถ ๋งฅ๋ฝ์ ํ์ธํ๋ค.
- Group by ๋ก ๋ณ๋ชฉ ์ฃผ์ฒด ์ขํ๊ธฐ: URL / ์๋ํํฐ ์ฃผ์ฒด / ์์ ์ข ๋ฅ(์คํฌ๋ฆฝํ ยท๋ ๋ยทํ์ธํธ) / ์นดํ ๊ณ ๋ฆฌ ๋ก ๋ฌถ์ด, "์ด๋ ๋๋ฉ์ธยท์ด๋ ์คํฌ๋ฆฝํธยท์ด๋ค ์ข ๋ฅ์ ์์ "์ด ์๊ฐ์ ๋จน๋์ง ๋จ๊ณ์ ์ผ๋ก ์ขํ๋ค.
- ์ต์ ์ดํธ๋ฆฌ๋ทฐ์ ๊ธฐ๋ฒ: Long Animation Frames API(LoAF) ์ web-vitals ๋ผ์ด๋ธ๋ฌ๋ฆฌ(v4๋)์ INP ์ดํธ๋ฆฌ๋ทฐ์ ์ ์ฐ๋ฉด "์ด๋ค ์คํฌ๋ฆฝํธ/์ด๋ค ์ธํฐ๋์ ์ด ๋๋ฆฐ ํ๋ ์์ ์ ๋ฐํ๋๊ฐ"๋ฅผ ์๋ณํ ์ ์๋ค. ๋จ, ๋ธ๋ผ์ฐ์ ยทAPI ์ง์ ๋ฒ์์ ์ฌ์ฉ๋ฒ์ ์์ ์ ๋ฐ๋ผ ๋ฐ๋๋ฏ๋ก ์ต์ ๊ณต์ ๋ฌธ์ ํ์ธ์ ๊ถ์ฅํ๋ค.
ํต์ฌ ์์ฝ: ์ค๋กํ๋งยทFirst/Repeatยท์ค์๊ฐ์ผ๋ก ์กฐ๊ฑด์ ํต์ ํ๊ณ , DevTools์ Bottom-Up/Call Tree + Group by๋ก ๋ณ๋ชฉ์ ๊ท์ํ๋ค. INP ์์ธ์ LoAFยทweb-vitals ์ดํธ๋ฆฌ๋ทฐ์ ์ผ๋ก ์ขํ๋ค(์ง์ ๋ฒ์๋ ๊ณต์ ๋ฌธ์ ํ์ธ).
5. ๊ธฐ๋ณธ ์ต์ ํ ๊ธฐ๋ฒ
๊ฐ ๊ธฐ๋ฒ์ โ ๋ฌธ์ โ โก ์๋ฆฌ โ โข ์ ์ฉ โ โฃ ์ฝ๋(์ํฐํจํดโ๊ฐ์ ) โ โค ๊ฒ์ฆ ํ๋ก ์ ๋ฆฌํ๋ค.
5.1 ๋ ๋๋ง ์ง์ฐ โ content-visibility
โ ๋ฌธ์ . ๊ธด ํ์ด์ง์์ ํ๋ฉด ๋ฐ(์คํฌ๋กคํด์ผ ๋ณด์ด๋) ์ฝํ
์ธ ๊น์ง ์ด๊ธฐ ๋ ๋์ ํฌํจ๋์ด ๋ ์ด์์ยทํ์ธํธ ๋น์ฉ์ด ์ปค์ง๋ค.
โก ์๋ฆฌ. content-visibility: auto ๋ ํ๋ฉด ๋ฐ ์์์ ๋ ๋๋ง(๋ ์ด์์ยทํ์ธํธ)์ ํ์ํ ๋๊น์ง ๊ฑด๋๋ด๋ค. ๋จ, ๋ ๋๋ฅผ ์คํตํ๋ฉด ํฌ๊ธฐ๋ฅผ ๋ชจ๋ฅด๊ฒ ๋์ด ์คํฌ๋กค๋ฐ๊ฐ ํ๋ฏ๋ก contain-intrinsic-size ๋ก ์์ ํฌ๊ธฐ๋ฅผ ์๋ ค์ค์ผ ํ๋ค.
โข ์ ์ฉ. ์ธ๋ก๋ก ๊ธด, ๋
๋ฆฝ์ ์ธ ์น์
(์นด๋ ๋ชฉ๋ก, ์ํฐํด ๋ธ๋ก)์ ์ ์ฉ. ์ฃผ์: display:none ์ผ๋ก ์ด๋ฏธ ์จ๊ธด ์์์ ์๋ฏธ๊ฐ ์๊ณ (๋ ๋ ๋์์ด ์๋), ์ต์ปคํ display:block ์น์
์์ ํจ๊ณผ๊ฐ ์๋ค.
โฃ ์ฝ๋
/* ๊ฐ์ : ํ๋ฉด ๋ฐ ์น์
๋ ๋ ์คํต + ํฌ๊ธฐ ์์ฝ */
.section {
content-visibility: auto;
contain-intrinsic-size: auto 600px; /* ์์ ๋์ด โ ์คํฌ๋กค ์ ํ ๋ฐฉ์ง */
}
โค ๊ฒ์ฆ. DevTools Performance์์ ์ด๊ธฐ ๋ ๋์ Layout/Paint ์๊ฐ ๊ฐ์๋ฅผ ํ์ธ. ์คํฌ๋กค ์ ๋ ์ด์์ ์ ํ(CLS)๊ฐ ์๊ธฐ์ง ์๋์ง ํจ๊ป ๋ณธ๋ค.
5.2 ๊ฐ์ ๋ฆฌํ๋ก์ฐ(๋ ์ด์์ ์ค๋์ฑ) ํํผ
โ ๋ฌธ์ . ๋ฃจํ ์์์ ์ฝ๊ธฐ(์ธก์ )์ ์ฐ๊ธฐ(์คํ์ผ ๋ณ๊ฒฝ)๋ฅผ ๋ฒ๊ฐ์ ํ๋ฉด, ๋ธ๋ผ์ฐ์ ๊ฐ ๋งค๋ฒ ๋ ์ด์์์ ๋ค์ ๊ณ์ฐ(๊ฐ์ ๋ฆฌํ๋ก์ฐ)ํด ๋ฉ์ธ ์ค๋ ๋๋ฅผ ์ก์๋จน๋๋ค. โก ์๋ฆฌ. ๋ ์ด์์ ๊ฐ์ ์ฝ๋ ์๊ฐ ๋ธ๋ผ์ฐ์ ๋ ์ต์ ๋ ์ด์์์ ์ฆ์ ๊ณ์ฐํด์ผ ํ๋ค. ์ฝ๊ธฐโ์ฐ๊ธฐโ์ฝ๊ธฐ๊ฐ ์์ด๋ฉด ๊ณ์ฐ์ด ๋ฐ๋ณต๋๋ค. ์ฝ๊ธฐ๋ฅผ ๋จผ์ ๋ชฐ์์ ํ๊ณ , ์ฐ๊ธฐ๋ฅผ ๋์ค์ ๋ชฐ์์ ํ๋ฉด ๋ฆฌํ๋ก์ฐ๊ฐ ํ ๋ฒ์ผ๋ก ์ค์ด๋ ๋ค. โข ์ ์ฉ. ์ธก์ ๊ฐ์ ์บ์ฑํ๊ณ , DOM ์ฐ๊ธฐ๋ ๋ฐฐ์นญํ๋ค.
โฃ ์ฝ๋
// ์ํฐํจํด: ์ฝ๊ธฐ์ ์ฐ๊ธฐ๊ฐ ๊ต์ฐจ โ ๋งค ๋ฐ๋ณต ๊ฐ์ ๋ฆฌํ๋ก์ฐ
items.forEach((el) => {
const w = el.getBoundingClientRect().width; // ์ฝ๊ธฐ
el.style.width = w * 1.1 + 'px'; // ์ฐ๊ธฐ โ ๋ค์ ์ฝ๊ธฐ์์ ๋ฆฌํ๋ก์ฐ
});
// ๊ฐ์ : ์ฝ๊ธฐ ๋ฐฐ์นญ โ ์ฐ๊ธฐ ๋ฐฐ์นญ
const widths = items.map((el) => el.getBoundingClientRect().width); // ์ฝ๊ธฐ ๋ชฐ์์
items.forEach((el, i) => { el.style.width = widths[i] * 1.1 + 'px'; }); // ์ฐ๊ธฐ ๋ชฐ์์
โค ๊ฒ์ฆ. Performance ํธ๋ ์ด์ค์์ "Recalculate Style / Layout"์ด ๋ฐ๋ณต์ ์ผ๋ก ์ฐํ๋ ๋ณด๋ผ์ ๊ตฌ๊ฐ์ด ์ค์๋์ง ํ์ธ.
5.3 ๊ธด ์์ (Long Task, >50ms) ๋ถํ
โ ๋ฌธ์ . 50ms๋ฅผ ๋๋ ์์ ์ ๊ทธ ๋์ ๋ฉ์ธ ์ค๋ ๋๋ฅผ ๋ ์ ํด ์ธํฐ๋์ ์ ๋ง๋๋ค(์ ๋ ฅ ์ง์ฐ โ INP ์ ํ). โก ์๋ฆฌ. ํฐ ์์ ์ ์๊ฒ ์ชผ๊ฐ ์ค๊ฐ์ค๊ฐ ๋ฉ์ธ ์ค๋ ๋๋ฅผ ์๋ณด(yield) ํ๋ฉด, ์ฌ์ด์ฌ์ด ์ฌ์ฉ์ ์ ๋ ฅ์ด ์ฒ๋ฆฌ๋ ํ์ด ์๊ธด๋ค. โข ์ ์ฉ. ๋๋ ๋ฐ๋ณตยท์ง๋ ฌ ๊ณ์ฐ์ ์ฒญํนํ๊ณ , ๊ธํ์ง ์์ ์์ ์ ์ ํด ์๊ฐ์ ๋ฏธ๋ฃฌ๋ค.
โฃ ์ฝ๋
// ๊ฐ์ : ์ค๊ฐ์ ๋ฉ์ธ ์ค๋ ๋ ์๋ณด (scheduler.yield ์ง์ ์)
async function processAll(items) {
for (let i = 0; i < items.length; i++) {
doHeavyWork(items[i]);
// ์ผ์ ์ฃผ๊ธฐ๋ง๋ค ์๋ณด โ ์
๋ ฅ ์ฒ๋ฆฌ ํ์ ํ๋ณด
if (i % 50 === 0 && 'scheduler' in window && 'yield' in scheduler) {
await scheduler.yield();
}
}
}
// ๊ธํ์ง ์์ ์์
์ ์ ํด ์๊ฐ์
requestIdleCallback(() => precomputeCache());
scheduler.yield() ๋ ๋น๊ต์ ์ต์ API๋ก ๋ธ๋ผ์ฐ์ ์ง์ ๋ฒ์๊ฐ ์ ํ์ ์ผ ์ ์์ผ๋ ํด๋ฐฑ(์: setTimeout(0)/await new Promise(r=>setTimeout(r)))๊ณผ ํจ๊ป ์ฐ๊ณ , ์ต์ ์ง์ ํํฉ์ ๊ณต์ ๋ฌธ์๋ฅผ ํ์ธํ๋ค.
โค ๊ฒ์ฆ. Performance์์ 50ms๋ฅผ ๋๋ Long Task(๋นจ๊ฐ ์ผ๊ฐํ)๊ฐ ์ค์๋์ง, ํ๋ INP(RUM)๊ฐ ๊ฐ์ ๋๋์ง ํ์ธ.
5.4 ์ด๋ฒคํธยท์คํฌ๋กค ์ฑ๋ฅ
โ ๋ฌธ์ . ์คํฌ๋กคยทํฐ์นยทresize ๊ฐ์ ๊ณ ๋น๋ ์ด๋ฒคํธ์์ ๋ฌด๊ฑฐ์ด ํธ๋ค๋ฌ๊ฐ ๋งค ํ๋ ์ ์คํ๋๋ฉด ์คํฌ๋กค์ด ๋๊ธด๋ค.
โก ์๋ฆฌ. passive ๋ฆฌ์ค๋๋ก ์คํฌ๋กค ๋ธ๋กํน์ ์์ ๊ณ , ์๊ฐ ๊ฐฑ์ ์ requestAnimationFrame ์ ๋ง์ถ๋ค. ๊ณ ๋น๋ ์
๋ ฅ์ debounce/throttle ๋ก ์คํ ๋น๋๋ฅผ ๋ฎ์ถ๋ค.
โฃ ์ฝ๋
// ๊ฐ์ : passive + rAF๋ก ์คํฌ๋กค ํธ๋ค๋ฌ ์ต์ ํ
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(() => { updateOnScroll(); ticking = false; });
ticking = true;
}
}, { passive: true });
โค ๊ฒ์ฆ. ์คํฌ๋กค ์ค Performance ํธ๋ ์ด์ค์์ ํ๋ ์ ๋๋กญ(๊ธด ํ๋ ์)์ด ์ค๊ณ 60fps์ ๊ทผ์ ํ๋์ง ํ์ธ.
5.5 ์ด๋ฏธ์ง ์ต์ ํ
โ ๋ฌธ์ . ์ด๋ฏธ์ง๋ ๋๊ฐ ํ์ด์ง์์ ๊ฐ์ฅ ๋ฌด๊ฑฐ์ด ๋ฆฌ์์ค์ด์ LCP ์์๋ค. ๋ฌด๊ฒ๊ฑฐ๋ ๋ฆ๊ฒ ๋ฐ๊ฒฌ๋๋ฉด LCP๊ฐ ๋๋น ์ง๊ณ , ํฌ๊ธฐ ๋ฏธ์ง์ ์ด๋ฉด CLS๋ฅผ ์ ๋ฐํ๋ค. โก ์๋ฆฌ. โด ํฌ๋งท์ ๊ฐ๋ณ๊ฒ(WebP/AVIF), โต ํ๋ฉด ํฌ๊ธฐ์ ๋ง๋ ํด์๋๋ง ์ ๋ฌ(๋ฐ์ํ), โถ ํ๋ฉด ๋ฐ ์ด๋ฏธ์ง๋ ์ง์ฐ ๋ก๋, โท LCP ์ด๋ฏธ์ง๋ ์ผ์ฐยท๋์ ์ฐ์ ์์๋ก ๋ก๋. โข ์ ์ฉ.
โฃ ์ฝ๋
<!-- ์ํฐํจํด: ํฌ๊ธฐ ๋ฏธ์ง์ + ์๋ณธ ๊ทธ๋๋ก โ CLS + ๊ณผ๋ ์ ์ก --> <img src="/hero.png" /> <!-- ๊ฐ์ : ํฌ๊ธฐ ์ง์ (CLS ๋ฐฉ์ง) + ๋ฐ์ํ + ์ง์ฐ/์ฐ์ ์์ --> <img src="/hero-800.avif" srcset="/hero-400.avif 400w, /hero-800.avif 800w, /hero-1600.avif 1600w" sizes="(max-width: 768px) 100vw, 800px" width="800" height="450" loading="lazy" decoding="async" alt="์ค๋ช " /> <!-- LCP ์ด๋ฏธ์ง๋ ์ง์ฐ ๋ก๋ํ์ง ๋ง๊ณ preload + ๋์ ์ฐ์ ์์ --> <link rel="preload" as="image" href="/hero-800.avif" fetchpriority="high" />
์ฃผ์: LCP ์ด๋ฏธ์ง์๋ loading="lazy" ๋ฅผ ์ฐ์ง ์๋๋ค(๋ฐ๊ฒฌยท๋ก๋๊ฐ ๋ฆ์ด์ ธ ์คํ๋ ค LCP ์
ํ). lazy๋ ํ๋ฉด ๋ฐ ์ด๋ฏธ์ง์๋ง.
โค ๊ฒ์ฆ. LCP ์์๊ฐ ์ด๋ฏธ์ง๋ฉด ๊ทธ ๋ก๋ ์์ ์ด ์๋น๊ฒจ์ก๋์ง, ์ด๋ฏธ์ง ํฌ๊ธฐ ์ง์ ์ผ๋ก CLS๊ฐ ์ฌ๋ผ์ก๋์ง ํ์ธ.
5.6 ํฐํธ ์ต์ ํ
โ ๋ฌธ์ . ์นํฐํธ ๋ก๋ ์ค ํ
์คํธ๊ฐ ์ ๋ณด์ด๊ฑฐ๋(FOIT), ์์คํ
ํฐํธ๋ก ๋ณด์๋ค๊ฐ ๊ต์ฒด๋๋ฉฐ(FOUT) ๋ ์ด์์์ด ๋ฐ๋ ค CLSยทFCP๊ฐ ๋๋น ์ง๋ค.
โก ์๋ฆฌ. font-display ๋ก ๊ต์ฒด ์ ์ฑ
์ ์ ํ๊ณ , ํฐํธ๋ฅผ preload ๋ก ์ผ์ฐ ๋ฐ์ผ๋ฉฐ, ์ฌ์ฉ ๊ธ์๋ง ์๋ธ์
์ผ๋ก ์ค์ฌ ์ฉ๋์ ๋ฎ์ถ๋ค.
โฃ ์ฝ๋
@font-face {
font-family: 'Brand';
src: url('/fonts/brand-subset.woff2') format('woff2');
font-display: swap; /* ํ
์คํธ ์ฆ์ ํ์ ํ ๊ต์ฒด (FOIT ๋ฐฉ์ง) */
font-weight: 400 700; /* ๊ฐ๋ณํฐํธ๋ฉด ๋ฒ์ ์ง์ */
}
<link rel="preload" as="font" type="font/woff2" href="/fonts/brand-subset.woff2" crossorigin />
๊ต์ฒด ์ CLS๋ฅผ ๋ ์ค์ด๋ ค๋ฉด ํด๋ฐฑ ํฐํธ์ ๋ฉํธ๋ฆญ์ ๋ง์ถ๋ ๊ธฐ๋ฒ(์: size-adjust/ascent-override ๋ฑ)์ ํจ๊ป ๊ฒํ ํ๋ค. ์ธ๋ถ ์ง์์ ๊ณต์ ๋ฌธ์ ํ์ธ ๊ถ์ฅ.
โค ๊ฒ์ฆ. ํฐํธ ๊ต์ฒด ์์ ์ ๋ ์ด์์ ์ด๋(CLS)๊ณผ ํ
์คํธ ํ์ ์์ (FCP)์ ํ์ธ.
5.7 ๋ฆฌ์์ค ์ ๋ฌ โ ์ฝ๋ ์คํ๋ฆฌํ ยทํฌ๋ฆฌํฐ์ปฌ CSSยทํ๋ฆฌ์ปค๋ฅํธ
โ ๋ฌธ์ . ์ด๊ธฐ ๋ก๋์ ๋ถํ์ํ JS/CSS๊น์ง ํจ๊ป ๋ฐ์ผ๋ฉด ๋ ๋๊ฐ ๋ฆ์ด์ง๋ค(๋ ๋ ์ฐจ๋จ).
โก ์๋ฆฌ. โด ์ด๊ธฐ ํ๋ฉด์ ํ์ํ ์ฝ๋๋ง ๋๋์ด ๋ก๋(์ฝ๋ ์คํ๋ฆฌํ
), โต ์ฒซ ํ๋ฉด์ ํ์ํ CSS๋ง ์ฐ์ (ํฌ๋ฆฌํฐ์ปฌ CSS), โถ ๊ณง ์ฐ๊ฒฐํ ๋๋ฉ์ธ์ ๋ฏธ๋ฆฌ ์ปค๋ฅํธ(preconnect), ์ค์ํ ๋ฆฌ์์ค๋ preload, โท ๋ ๋ ์ฐจ๋จ ๋ฆฌ์์ค ์ ๊ฑฐ.
โฃ ์ฝ๋
<!-- ๊ณง ์ธ ์๋ํํฐ ๋๋ฉ์ธ ์ฐ๊ฒฐ ์ค๋น --> <link rel="preconnect" href="https://cdn.example.com" crossorigin />
// ๊ฐ์ : ํ์ํ ๋๋ง ๋ฌด๊ฑฐ์ด ๋ชจ๋ ๋ก๋(์ฝ๋ ์คํ๋ฆฌํ
)
button.addEventListener('click', async () => {
const { openEditor } = await import('./editor.js'); // ์ด๊ธฐ ๋ฒ๋ค์์ ๋ถ๋ฆฌ
openEditor();
});
โค ๊ฒ์ฆ. ์ด๊ธฐ ๋ฒ๋ค ํฌ๊ธฐยท๋ ๋ ์ฐจ๋จ ๋ฆฌ์์ค ์ ๊ฐ์, FCP/LCP ๊ฐ์ ์ ํ์ธ.
5.8 ์๋ํํฐ ์คํฌ๋ฆฝํธ ๊ฑฐ๋ฒ๋์ค (๋ถ์ยท๋ง์ผํ ํ๊ทธ)
โ ๋ฌธ์ . ๋ถ์ยท๊ด๊ณ ยท์ฑ๋ด ๋ฑ ์๋ํํฐ ํ๊ทธ๋ ๋๋ถ๋ถ ๋ฉ์ธ ์ค๋ ๋์์ ์คํ๋๋ค. ํ๊ทธ๊ฐ ๋์๋ก ์ฐ๋ฆฌ ์ฝ๋์ ๋ฉ์ธ ์ค๋ ๋๋ฅผ ๋๊ณ ๊ฒฝ์ํด ์
๋ ฅ ์ง์ฐ โ INP๊ฐ ์
ํ๋๋ค. ๋ํ ๋ ๋ ์ฐจ๋จยท์ถ๊ฐ ์ปค๋ฅ์
์ผ๋ก LCP์๋ ์ํฅ์ ์ค๋ค.
โก ์๋ฆฌ. โด ๋ก๋ฉ์ ๋น์ฐจ๋จ์ผ๋ก(async/defer), โต ์ฆ์ ํ์ ์๋ ํ๊ทธ๋ ์กฐ๊ฑด๋ถยท์ง์ฐ ๋ก๋ฉ(๊ฐ์์ฑยท์ํธ์์ฉ ์์ ์), โถ ํ๊ทธ ๋งค๋์ ์ ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ต์ํ, โท ๊ฐ๋ฅํ๋ฉด ์๋ฒ์ฌ์ด๋ ํ๊น
์ผ๋ก ํด๋ผ์ด์ธํธ ๋ถ๋ด ์ด์ , โธ ๋ฌด๊ฑฐ์ด ์๋ํํฐ JS๋ ์น์์ปค๋ก ์คํ๋ก๋(Partytown ๋ฑ)ํด ๋ฉ์ธ ์ค๋ ๋์์ ๋บ๋ค.
โข ์ ์ฉ. "์ด ํ๊ทธ๊ฐ ์ด๊ธฐ ํ๋ฉดยท์ฒซ ์ธํฐ๋์
์ ๊ผญ ํ์ํ๊ฐ?"๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ก๋ ์์ ์ ๋ฏธ๋ฃฌ๋ค.
โฃ ์ฝ๋
<!-- ์ํฐํจํด: ๋๊ธฐ ๋ก๋ โ ๋ ๋ยท๋ฉ์ธ์ค๋ ๋ ์ฐจ๋จ --> <script src="https://third-party.example.com/tag.js"></script> <!-- ๊ฐ์ : ๋น์ฐจ๋จ ๋ก๋ --> <script src="https://third-party.example.com/tag.js" async></script>
// ๊ฐ์ : ์ํธ์์ฉ/์ ํด ์์ ๊น์ง ์ง์ฐ ๋ก๋
const load = () => import('./analytics.js');
if ('requestIdleCallback' in window) requestIdleCallback(load);
else window.addEventListener('load', load);
Partytownยท์๋ฒ์ฌ์ด๋ ํ๊น ๋ฑ์ ๊ตฌ์ฑยทํธํ์ฑ ๊ณ ๋ ค๊ฐ ํ์ํ๋ฉฐ ๋ชจ๋ ํ๊ทธ์ ์ ์ฉ๋์ง๋ ์๋๋ค. ๋์ ์ ๋์ ํ๊ทธ์ ๋์ยท์ง์์ ๊ฒ์ฆํ๋ค. โค ๊ฒ์ฆ. DevTools Performance์ Group by ์๋ํํฐ ์ฃผ์ฒด๋ก ๊ฐ ํ๊ทธ์ ๋ฉ์ธ ์ค๋ ๋ ์ ์ ๋ฅผ ์ธก์ ํ๊ณ , ๊ฐ์ ํ TBT(Lab)ยทINP(RUM) ๋ณํ๋ฅผ ํ์ธ.
5.9 ์ต์ ํ ๊ธฐ๋ฒ ์์ฝํ
| ๋ชฉํ ์งํ | ๊ธฐ๋ฒ | ํต์ฌ ํ ์ค |
|---|---|---|
| LCP | LCP ์ด๋ฏธ์ง preload + fetchpriority | ๊ฐ์ฅ ํฐ ์์๋ฅผ ์ผ์ฐยท์ฐ์ ๋ก๋ |
| LCP/FCP | ๋ ๋ ์ฐจ๋จ ์ ๊ฑฐยทํฌ๋ฆฌํฐ์ปฌ CSSยท์ฝ๋ ์คํ๋ฆฌํ | ์ด๊ธฐ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ณ๊ฒ |
| INP | Long Task ๋ถํ ยทyield, ์๋ํํฐ ๊ฑฐ๋ฒ๋์ค | ๋ฉ์ธ ์ค๋ ๋๋ฅผ ๋น์ ์ ๋ ฅ์ ๋ฐ๋๋ค |
| INP | ๋ฆฌํ๋ก์ฐ ํํผ(์ฝ๊ธฐ/์ฐ๊ธฐ ๋ฐฐ์นญ) | ๋ถํ์ํ ๋ ์ด์์ ์ฌ๊ณ์ฐ ์ ๊ฑฐ |
| CLS | ์ด๋ฏธ์งยท๋ฏธ๋์ด ํฌ๊ธฐ ์ง์ , ๊ณต๊ฐ ์์ฝ | ๋ฐ๋ฆผ์ ์์ฒ ์ฐจ๋จ |
| CLS | font-displayยทํฐํธ preloadยท์๋ธ์ | ํฐํธ ๊ต์ฒด๋ก ์ธํ ์ฌ๋ฐฐ์น ์ต์ํ |
| ๋ ๋ ๋น์ฉ | content-visibility + contain-intrinsic-size | ํ๋ฉด ๋ฐ ๋ ๋ ์คํต |
ํต์ฌ ์์ฝ: ๊ธฐ๋ฒ์ ๊ฒฐ๊ตญ "โ ์ด๊ธฐ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ณ๊ฒ(LCP) โก ๋ฉ์ธ ์ค๋ ๋๋ฅผ ๋น์ ์ ๋ ฅ์ ๋ฐ๊ฒ(INP) โข ๊ณต๊ฐ์ ๋ฏธ๋ฆฌ ์์ฝํด ์ ๋ฐ๋ฆฌ๊ฒ(CLS)"๋ก ์๋ ดํ๋ค.
6. ํ์ด์ง ์์ฑ ํ ์ฑ๋ฅ ์ ๊ฒ ์ํฌํ๋ก์ฐ
6.1 ๊ถ์ฅ ์ ์ฐจ (4๋จ๊ณ)
- ๊ฐ๊ด ํ์ธ โ PageSpeed Insights: ํ URL์ ๋ํด Lab ์ ์ + ํ๋ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ๊ฐ๊ดํ๋ค.
- ํ๋ ํ์ธ โ CrUX/RUM: ์ค์ ์ฌ์ฉ์ ๊ธฐ์ค CWV, ํนํ Lab์์ ์ ๋์ค๋ INP๋ฅผ P75๋ก ํ์ธํ๋ค.
- ์์ธ ๊ท์ โ DevTools Performance: ๋ฌธ์ ์งํ์ ๋ณ๋ชฉ์ Bottom-Up/Call Tree + Group by๋ก ๊ท์ํ๋ค.
- ๊ฐ์ ํ ์ฌ์ธก์ : ๊ฐ์ค์ ํ๋์ฉ ์ ์ฉํ๊ณ ๋์ผ ์กฐ๊ฑด์์ ์ฌ์ธก์ ํด ์ธ๊ณผ๋ฅผ ํ์ธํ๋ค.
6.2 ๋๊ตฌ ๋น๊ตํ (๊ณต๊ฐ ๋๊ตฌ)
| ๋๊ตฌ | ์ฑ๊ฒฉ | ์ฃผ ์ฉ๋ |
|---|---|---|
| PageSpeed Insights | Lab + ํ๋ ์์ฝ | ๋ฐฐํฌ URL์ ์ํ ๊ฐ๊ด |
| Chrome DevTools Performance | Lab / ์์ธ ๋ถ์ | ๋ณ๋ชฉ ํธ๋ ์ด์คยท์์ธ ๊ท์ |
| WebPageTest | Lab(๋ค์ํ ์กฐ๊ฑด) | ์กฐ๊ฑด๋ณ ์์ธ ์ธก์ ยท๋น๊ต |
| CrUX (Chrome UX Report) | RUM(ํ๋) | ์ค์ฌ์ฉ์ CWV(P75) |
| web-vitals ๋ผ์ด๋ธ๋ฌ๋ฆฌ | RUM(์์ฒด ์์ง) | ์์ฌ ํ์ด์ง์์ CWVยท์ดํธ๋ฆฌ๋ทฐ์ ์์ง |
6.3 ํ์ ์์น
- ํ์ ์ Google ๊ณต์ CWV ๊ธฐ์ค(web.devยทChrome ๋ฌธ์) (2.5s / 200ms / 0.1, P75)์ ์ฌ์ฉํ๋ค.
- Lab ๋จ์ผ ์ ์์ ์ง์ฐฉํ์ง ๋ง ๊ฒ. Lab ์ ์๋ ์กฐ๊ฑด์ ๋ฏผ๊ฐํ๊ณ INP๋ฅผ ๋ด์ง ๋ชปํ๋ค. ๋ฐ๋์ ํ๋ ๋ฐ์ดํฐ์ ๋ณํํด "์ค์ฌ์ฉ์๊ฐ ์ค์ ๋ก ๊ฐ์ ๋์๋๊ฐ"๋ก ์ต์ข ํ์ ํ๋ค.
ํต์ฌ ์์ฝ: PSI(๊ฐ๊ด) โ ํ๋(INP ํฌํจ) โ DevTools(๊ท์) โ ์ฌ์ธก์ . Lab ์ ์ ํ๋๊ฐ ์๋๋ผ ํ๋ ๋ฐ์ดํฐ๋ก ํ์ ํ๋ค.
7. ๊ฒฐ๋ก โ ์ฑ๋ฅ์ ์ํ๊ฐ ์๋๋ผ ์ฌ์ดํด์ด๋ค
์ฑ๋ฅ ์ต์ ํ๋ "ํ ๋ฒ ๋๋ด๋ ์์ "์ด ์๋๋ผ ์ธก์ โ ์์ธ ๊ท์ โ ๊ฐ์ โ ์ฌ์ธก์ ์ ๋ฐ๋ณตํ๋ ์ง์์ ํ๋ก์ธ์ค๋ค. ์ฝ๋ยท์ฝํ ์ธ ยท์๋ํํฐ ํ๊ทธ๋ ์๊ฐ์ด ์ง๋๋ฉฐ ๊ณ์ ๋๊ณ ๋ณํ๋ฏ๋ก, ํ ๋ฒ ์ข์๋ ์งํ๋ ๊ด๋ฆฌํ์ง ์์ผ๋ฉด ํดํํ๋ค.
ํต์ฌ ํ๋๋ ์ธ ๊ฐ์ง๋ค. โด ๋๋์ด ์๋๋ผ ๋ฐ์ดํฐ๋ก ๋งํ๋ค(Lab+ํ๋ ๋ณํ). โต ๊ฐ์ฅ ๋ถ๋ฆฌํ ์ฌ์ฉ์(๋๋ฆฐ ๊ธฐ๊ธฐยทํ์ )๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๊ณํ๋ค. โถ ๊ฐ์ ์ ํ ๋ฒ์ ํ๋์ฉ, ์ฌ์ธก์ ์ผ๋ก ์ธ๊ณผ๋ฅผ ํ์ธํ๋ค.
์คํ ์ฒดํฌ๋ฆฌ์คํธ (๋ฐ์นญ ์ )
- LCP ์์๋ฅผ ์๋ณํ๊ณ , LCP ์ด๋ฏธ์ง๋
preload + fetchpriority="high"(lazy ๊ธ์ง). - ๋ชจ๋ ์ด๋ฏธ์งยท๋ฏธ๋์ด์
width/height(๋๋ aspect-ratio) ์ง์ โ CLS ๋ฐฉ์ง. - ์นํฐํธ
font-display: swap+ preload + ์๋ธ์ ์ ์ฉ. - ์ด๊ธฐ ๋ ๋ ์ฐจ๋จ JS/CSS ์ ๊ฑฐ, ์ฝ๋ ์คํ๋ฆฌํ ยทํฌ๋ฆฌํฐ์ปฌ CSS ์ ์ฉ.
- Long Task(>50ms) ํ์ธยท๋ถํ , ๊ณ ๋น๋ ์ด๋ฒคํธ
passive+rAF+throttle. - ์๋ํํฐ ํ๊ทธ ๋ชฉ๋กํ โ ๋น์ฐจ๋จ/์ง์ฐ/์กฐ๊ฑด๋ถ ๋ก๋ฉ, ๋ถํ์ ํ๊ทธ ์ ๊ฑฐ.
content-visibility๋ก ๊ธด ํ์ด์ง์ ํ๋ฉด ๋ฐ ๋ ๋ ๋น์ฉ ์ ๊ฐ(display:none ์์ ์ ์ธ).- PSI๋ก ๊ฐ๊ด โ ํ๋(CrUX/RUM)์์ INP ํฌํจ P75 ํ์ธ โ DevTools๋ก ๊ท์ โ ์ฌ์ธก์ .
- ํ์ ์ Google ๊ณต์ ๊ธฐ์ค(2.5s / 200ms / 0.1, P75)์ผ๋ก, Lab+ํ๋ ๋ณํ.
์ฐธ๊ณ ์๋ฃ (๊ณต์ยท๊ณต๊ฐ ๋ฌธ์)
๋ณธ๋ฌธ์ ๋ชจ๋ ์๊ณ๊ฐยท์ ์๋ ์๋ โ Core Web Vitals ๊ณต์ ๊ธฐ์ค(Google) ์ 1์ฐจ ์์ถ์ฒ๋ก ์ผ๋๋ค. web.dev๋ Google์ด ์ด์ํ๋ ์น ๊ฐ๋ฐ ๊ณต์ ๋ฌธ์ ์ฌ์ดํธ์ด๋ฉฐ, developer.chrome.com์ Chrome ๊ฐ๋ฐ์ ๊ณต์ ๋ฌธ์๋ค. ์๋ ๋งํฌ๋ ์์ฑ ์์ ์ ๊ทผ ๊ฐ๋ฅ(200 ์๋ต) ํ์ธ.
โ Core Web Vitals ๊ณต์ ๊ธฐ์ค โ Google (1์ฐจ ์์ถ์ฒ)
Core Web Vitals ๊ฐ์ยท์๊ณ๊ฐweb.dev/articles/vitalsLCP(์ ์ยท๊ธฐ์ค)web.dev/articles/lcpINP(์ ์ยท๊ธฐ์ค)web.dev/articles/inpCLS(์ ์ยท๊ธฐ์ค)web.dev/articles/clsTTFBweb.dev/articles/ttfbโก ์ต์ ํ ๊ฐ์ด๋ โ Google
LCP ์ต์ ํweb.dev/articles/optimize-lcpINP ์ต์ ํweb.dev/articles/optimize-inpLong Animation Frames(LoAF)developer.chrome.com/docs/web-platform/long-animation-framesโข ์ธก์ ยท์ง๋จ ๋๊ตฌ
PageSpeed Insights(Lab+ํ๋)pagespeed.web.dev/Chrome DevTools Performance(Labยท์์ธ ๋ถ์)developer.chrome.com/docs/devtools/performanceChrome UX Report / CrUX(ํ๋ ๋ฐ์ดํฐ)developer.chrome.com/docs/cruxweb-vitals ๋ผ์ด๋ธ๋ฌ๋ฆฌ(ํ๋ CWVยท์ดํธ๋ฆฌ๋ทฐ์
์์ง, Google Chrome)github.com/GoogleChrome/web-vitalsWebPageTest(Lab ์ธก์ , ์๋ํํฐ ๊ณต๊ฐ ๋๊ตฌ)www.webpagetest.org/๋๊ตฌ์ UIยทAPIยท๋ธ๋ผ์ฐ์ ์ง์ ๋ฒ์๋ ์์ ์ ๋ฐ๋ผ ๋ฐ๋๋ฏ๋ก, ์ธ๋ถ ์ฌ์ฉ๋ฒยท์ง์ ํํฉ์ ๊ฐ ์ต์ ๊ณต์ ๋ฌธ์๋ฅผ ํ์ธํ๋ค. ๋ณธ๋ฌธ์์ ์์น๋ฅผ ์๋ก ๋ ์ค๋กํ๋ง ๋ฐฐ์จ(์: 4ร/6ร)ยท๋คํธ์ํฌ ํ๋กํ์ผ ๋ฑ์ ํ๊ฒฝ ์์์ด๋ฉฐ ์ ๋ ๊ธฐ์ค์ด ์๋๋ค.