Performance Observer APIλ₯Ό μ¬μ©νμ¬ λ°νμ μ±λ₯μ λͺ¨λν°λ§νκ³ , λ³λͺ© νμμ μλ³νλ©°, μΉ μ ν리μΌμ΄μ μ±λ₯μ μ΅μ ννλ μ’ ν© κ°μ΄λμ λλ€. λ λμ μ¬μ©μ κ²½νμ μν΄ μ§νλ₯Ό μμ§νκ³ λΆμνλ λ°©λ²μ λ°°μ보μΈμ.
Performance Observer API: λ°νμ μ±λ₯ μ§ν λ° λ³λͺ© νμ λΆμ
μ€λλ κ²½μμ΄ μΉμ΄ν λμ§νΈ νκ²½μμ μΉμ¬μ΄νΈμ μΉ μ ν리μΌμ΄μ μ μ±λ₯μ μ¬μ©μ μ°Έμ¬μ λΉμ¦λμ€ μ±κ³΅μ λ§€μ° μ€μν©λλ€. λλ¦° λ‘λ© μκ°κ³Ό λ°μ μλ μΈν°νμ΄μ€λ μ¬μ©μμ λΆλ§, κ±°λ ν¬κΈ°, κ·Έλ¦¬κ³ κΆκ·Ήμ μΌλ‘λ μμ΅ μμ€λ‘ μ΄μ΄μ§ μ μμ΅λλ€. Performance Observer APIλ κ°λ°μκ° λ°νμ μ±λ₯ μ§νλ₯Ό λͺ¨λν°λ§ λ° λΆμνκ³ , λ³λͺ© νμμ μλ³νλ©°, μ¬μ©μμ μμΉλ κΈ°κΈ°μ κ΄κ³μμ΄ λ λΆλλ½κ³ λΉ λ₯΄λ©° μ¦κ±°μ΄ μ¬μ©μ κ²½νμ μν΄ μ ν리μΌμ΄μ μ μ΅μ νν μ μλλ‘ μ§μνλ κ°λ ₯ν λꡬμ λλ€.
Performance Observer APIλ 무μμΈκ°?
Performance Observer APIλ μΉ μ ν리μΌμ΄μ μμ μ±λ₯ κ΄λ ¨ μ΄λ²€νΈκ° λ°μν λ μ΄λ₯Ό κ΄μ°°νκ³ λ°μνλ λ©μ»€λμ¦μ μ 곡νλ μλ°μ€ν¬λ¦½νΈ APIμ λλ€. μ£ΌκΈ°μ μΈ μνλ§μ΄λ μλ κ³μΈ‘μ μμ‘΄νλ κΈ°μ‘΄μ μ±λ₯ λͺ¨λν°λ§ κΈ°μ κ³Ό λ¬λ¦¬, Performance Observer APIλ μ€μκ°μΌλ‘ μ±λ₯ λ°μ΄ν°λ₯Ό μΊ‘μ²νλ λ ν¨μ¨μ μ΄κ³ μ μ°ν λ°©λ²μ μ 곡ν©λλ€. μ΄λ₯Ό ν΅ν΄ κ°λ°μλ νΉμ μ±λ₯ νλͺ© μ νμ ꡬλ νκ³ μλ‘μ΄ νλͺ©μ΄ κΈ°λ‘λ λλ§λ€ μλ¦Όμ λ°μ μ μμ΅λλ€.
μ΄λ¬ν "κ΄μ°° ν λ°μ" μ κ·Ό λ°©μμ μ¬μ μλ°©μ μΈ μ±λ₯ λͺ¨λν°λ§μ κ°λ₯νκ² νμ¬, κ°λ°μκ° μ±λ₯ λ¬Έμ κ° μ¬μ©μ κ²½νμ μν₯μ λ―ΈμΉκΈ° μ μ μ΄λ₯Ό μλ³νκ³ ν΄κ²°ν μ μλλ‘ ν©λλ€. μ΄ APIλ μ΅μ λΈλΌμ°μ μ λ°μ κ±Έμ³ νμ€νλμ΄ μμ΄ μΌκ΄λ λμκ³Ό ν¬λ‘μ€ νλ«νΌ νΈνμ±μ 보μ₯ν©λλ€.
μ£Όμ κ°λ λ° κΈ°λ₯
Performance Observer APIλ₯Ό ν¨κ³Όμ μΌλ‘ νμ©νλ €λ©΄ ν΅μ¬ κ°λ κ³Ό κΈ°λ₯μ μ΄ν΄νλ κ²μ΄ μ€μν©λλ€.
- PerformanceEntry: λ¨μΌ μ±λ₯ μΈ‘μ λλ μ΄λ²€νΈλ₯Ό λνλ
λλ€. μ±λ₯ νλͺ©μλ μ΄λ²€νΈ μ ν, μμ λ° μ’
λ£ μκ°, κΈ°ν κ΄λ ¨ μμ±μ λν μ λ³΄κ° ν¬ν¨λ©λλ€. μμλ‘λ
resource
,mark
,measure
,navigation
,longtask
,event
λ±μ΄ μμ΅λλ€. - PerformanceObserver: νΉμ μ±λ₯ νλͺ© μ νμ ꡬλ νκ³ λΈλΌμ°μ μ μ±λ₯ νμλΌμΈμ μλ‘μ΄ νλͺ©μ΄ μΆκ°λ λλ§λ€ μλ¦Όμ λ°μ μ μκ² ν΄μ£Όλ κ°μ²΄μ λλ€.
- observe() λ©μλ: νΉμ μ±λ₯ νλͺ© μ νμ μμ νλλ‘ PerformanceObserverλ₯Ό ꡬμ±νλ λ° μ¬μ©λ©λλ€. κ΄μ°°νλ €λ νλͺ© μ νκ³Ό κ³Όκ±° νλͺ©μ λ°κΈ° μν
buffered
μ΅μ μ μ§μ ν μ μμ΅λλ€. - disconnect() λ©μλ: PerformanceObserverκ° μ±λ₯ μ΄λ²€νΈλ₯Ό μμ νλ κ²μ μ€μ§νλ λ° μ¬μ©λ©λλ€.
- takeRecords() λ©μλ: κ΄μ°°λμμ§λ§ μμ§ μ΅μ λ²μ μ½λ°± ν¨μμ μν΄ μ²λ¦¬λμ§ μμ λͺ¨λ μ±λ₯ νλͺ©μ λ°°μ΄μ λ°νν©λλ€.
- μ½λ°± ν¨μ: μλ‘μ΄ μ±λ₯ νλͺ©μ΄ κ΄μ°°λ λλ§λ€ μ€νλλ ν¨μμ
λλ€. μ΄ ν¨μλ κ΄μ°°λ νλͺ©μ ν¬ν¨νλ
PerformanceObserverEntryList
κ°μ²΄λ₯Ό λ°μ΅λλ€.
μ§μλλ μ±λ₯ νλͺ© μ ν
Performance Observer APIλ λ€μν μ±λ₯ νλͺ© μ νμ μ§μνλ©°, κ° μ νμ μΉ μ ν리μΌμ΄μ μ±λ₯μ λ€μν μΈ‘λ©΄μ λν ꡬ체μ μΈ ν΅μ°°λ ₯μ μ 곡ν©λλ€. κ°μ₯ μΌλ°μ μΌλ‘ μ¬μ©λλ νλͺ© μ νμ λ€μκ³Ό κ°μ΅λλ€.
resource
: μ΄λ―Έμ§, μ€ν¬λ¦½νΈ, μ€νμΌμνΈ, ν°νΈμ κ°μ κ°λ³ 리μμ€μ λ‘λ©μ λν μ 보λ₯Ό μ 곡ν©λλ€. μ΄ νλͺ© μ νμλ 리μμ€ URL, μμ λ° μ’ λ£ μκ°, κ°μ Έμ€κΈ°(fetch) μκ°, μ μ‘ ν¬κΈ° λ±μ μΈλΆ μ λ³΄κ° ν¬ν¨λ©λλ€.mark
: νΉμ μ½λ μΉμ μ μ§μ μκ°μ μΈ‘μ νκΈ° μν΄ μ½λ λ΄μ μ¬μ©μ μ§μ νμμ€ν¬νλ₯Ό μμ±ν μ μμ΅λλ€. λ§ν¬λ₯Ό μ¬μ©νμ¬ λ°μ΄ν° μ²λ¦¬λ UI λ λλ§κ³Ό κ°μ μ€μν μμ μ μμκ³Ό λμ μΆμ ν μ μμ΅λλ€.measure
: λ λ§ν¬ μ¬μ΄μ μ§μ μκ°μ κ³μ°νλ λ° μ¬μ©λ©λλ€. μ΄ νλͺ© μ νμ μ¬μ©μ μ§μ μ½λ μΉμ μ μ±λ₯μ μΈ‘μ νλ νΈλ¦¬ν λ°©λ²μ μ 곡ν©λλ€.navigation
: DNS μ‘°ν μκ°, TCP μ°κ²° μκ°, μμ² λ° μλ΅ μκ°, DOM μ²λ¦¬ μκ°μ ν¬ν¨ν νμ΄μ§μ λ€λΉκ²μ΄μ νμ΄λ°μ λν μ 보λ₯Ό μ 곡ν©λλ€.longtask
: λ©μΈ μ€λ λλ₯Ό μ₯μκ°(μΌλ°μ μΌλ‘ 50λ°λ¦¬μ΄ μ΄μ) μ°¨λ¨νλ μμ μ μλ³ν©λλ€. κΈ΄ μμ μ UI λ°μμ± μ νμ λ²λ² κ±°λ¦Ό(jank)μ μ λ°ν μ μμ΅λλ€.event
:click
,keydown
,scroll
κ³Ό κ°μ νΉμ λΈλΌμ°μ μ΄λ²€νΈμ λν νμ΄λ° μ 보λ₯Ό κΈ°λ‘ν©λλ€.layout-shift
: νμ΄μ§μμ μκΈ°μΉ μμ λ μ΄μμ λ³κ²½μ μΆμ ν©λλ€. μ΄λ¬ν λ³κ²½μ μ¬μ©μμκ² λΆνΈν¨μ μ£Όκ³ μ¬μ©μ κ²½νμ λΆμ μ μΈ μν₯μ λ―ΈμΉ μ μμ΅λλ€.largest-contentful-paint
: κ°μ₯ ν° μ½ν μΈ μμκ° νμ΄μ§μ νμλκΈ°κΉμ§ 걸리λ μκ°μ μΈ‘μ ν©λλ€.first-input-delay
: λΈλΌμ°μ κ° μ²« λ²μ§Έ μ¬μ©μ μνΈμμ©(μ: ν΄λ¦ λλ ν)μ μλ΅νλ λ° κ±Έλ¦¬λ μκ°μ μΈ‘μ ν©λλ€.element
: νμ΄μ§μ νΉμ μμ λ λλ§μ λν νμ΄λ° μ 보λ₯Ό λ³΄κ³ ν©λλ€.
μ€μ©μ μΈ μμ λ° μ¬μ© μ¬λ‘
Performance Observer APIλ μΉ μ ν리μΌμ΄μ μ±λ₯μ κ°μ νκΈ° μν΄ λ€μν μλ리μ€μμ μ¬μ©λ μ μμ΅λλ€. λ€μμ λͺ κ°μ§ μ€μ©μ μΈ μμ μ λλ€.
1. 리μμ€ λ‘λ© μκ° λͺ¨λν°λ§
resource
νλͺ© μ νμ μ¬μ©νλ©΄ μ΄λ―Έμ§, μ€ν¬λ¦½νΈ, μ€νμΌμνΈμ κ°μ κ°λ³ 리μμ€μ λ‘λ© μκ°μ μΆμ ν μ μμ΅λλ€. μ΄ μ 보λ νμ΄μ§ λ‘λ μκ°μ μν₯μ λ―ΈμΉλ λλ¦° 리μμ€λ₯Ό μλ³νλ λ° μ¬μ©λ μ μμ΅λλ€. μλ₯Ό λ€μ΄, λ€μ μ½λλ₯Ό μ¬μ©νμ¬ λ¦¬μμ€ λ‘λ© μκ°μ λͺ¨λν°λ§ν μ μμ΅λλ€.
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log(`Resource: ${entry.name}, Duration: ${entry.duration}ms`);
});
});
observer.observe({ entryTypes: ["resource"] });
μ΄ μ½λλ resource
νλͺ©μ μμ νκ³ λ¦¬μμ€ URLκ³Ό μ§μ μκ°μ μ½μμ κΈ°λ‘νλ PerformanceObserverλ₯Ό μμ±ν©λλ€. μ΄ λ°μ΄ν°λ₯Ό λΆμνμ¬ λλ¦¬κ² λ‘λ©λλ 리μμ€λ₯Ό μλ³νκ³ μ΄λ―Έμ§λ₯Ό μμΆνκ±°λ, μ½ν
μΈ μ μ‘ λ€νΈμν¬(CDN)λ₯Ό μ¬μ©νκ±°λ, μλ² κ΅¬μ±μ μ΅μ ννμ¬ κ°μ ν μ μμ΅λλ€.
κΈλ‘λ² κ΄μ : 리μμ€ λ‘λ© μκ°μ λͺ¨λν°λ§ν λ μ¬μ©μμ μ§λ¦¬μ μμΉλ₯Ό κ³ λ €νμΈμ. μΈν°λ· μ°κ²°μ΄ λλ¦° μ§μμ μ¬μ©μλ ν¨μ¬ λ κΈ΄ λ‘λ© μκ°μ κ²½νν μ μμ΅λλ€. μ§λ¦¬μ μΌλ‘ λΆμ°λ μλ²λ₯Ό κ°μΆ CDNμ μ¬μ©νλ©΄ μ΄ λ¬Έμ λ₯Ό μννλ λ° λμμ΄ λ μ μμ΅λλ€.
2. μ¬μ©μ μ§μ μ½λ μ€ν μκ° μΈ‘μ
mark
λ° measure
νλͺ© μ νμ μ¬μ©νλ©΄ μ¬μ©μ μ§μ μ½λ μΉμ
μ μ€ν μκ°μ μΈ‘μ ν μ μμ΅λλ€. μ΄λ μ ν리μΌμ΄μ
λ‘μ§μ μ±λ₯ λ³λͺ© νμμ μλ³νλ λ° μ μ©ν©λλ€. μλ₯Ό λ€μ΄, λ€μ μ½λλ₯Ό μ¬μ©νμ¬ νΉμ ν¨μμ μ§μ μκ°μ μΈ‘μ ν μ μμ΅λλ€.
performance.mark("start");
// Code to be measured
for (let i = 0; i < 1000000; i++) {
// Some computationally intensive operation
}
performance.mark("end");
performance.measure("My Function", "start", "end");
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log(`Measurement: ${entry.name}, Duration: ${entry.duration}ms`);
});
});
observer.observe({ entryTypes: ["measure"] });
μ΄ μ½λλ μΈ‘μ νλ €λ μ½λ μΉμ
μλ€μ start
μ end
λΌλ λ κ°μ λ§ν¬λ₯Ό μμ±ν©λλ€. κ·Έλ° λ€μ performance.measure()
λ©μλλ₯Ό μ¬μ©νμ¬ λ λ§ν¬ μ¬μ΄μ μ§μ μκ°μ κ³μ°ν©λλ€. PerformanceObserverλ measure
νλͺ©μ μμ νκ³ μΈ‘μ μ΄λ¦κ³Ό μ§μ μκ°μ μ½μμ κΈ°λ‘ν©λλ€. μ΄ λ°μ΄ν°λ₯Ό λΆμνμ¬ μ±λ₯μ΄ μ νλ μ½λ μΉμ
μ μλ³νκ³ μΊμ±, λ©λͺ¨μ΄μ μ΄μ
λλ μκ³ λ¦¬μ¦ μ΅μ νμ κ°μ κΈ°μ μ μ¬μ©νμ¬ μ΅μ νν μ μμ΅λλ€.
μ€ν κ°λ₯ν μΈμ¬μ΄νΈ: μ ν리μΌμ΄μ μ ν¬λ¦¬ν°μ»¬ ν¨μ€(κ°μ₯ μμ£Ό μ€νλκ³ μ±λ₯μ κ°μ₯ ν° μν₯μ λ―ΈμΉλ μ½λ μνμ€)λ₯Ό μλ³νμΈμ. μ΄λ¬ν ν¬λ¦¬ν°μ»¬ ν¨μ€μ μ΅μ ν λ Έλ ₯μ μ§μ€νμ¬ κ°μ₯ ν° μ±λ₯ ν₯μμ λ¬μ±νμΈμ.
3. κΈ΄ μμ μλ³
longtask
νλͺ© μ νμ λ©μΈ μ€λ λλ₯Ό μ₯μκ° μ°¨λ¨νλ μμ
μ μλ³ν©λλ€. κΈ΄ μμ
μ UI λ°μμ± μ νμ λ²λ²
κ±°λ¦Όμ μ λ°νμ¬ μ¬μ©μ κ²½νμ μ ν΄ν μ μμ΅λλ€. λ€μ μ½λλ₯Ό μ¬μ©νμ¬ κΈ΄ μμ
μ λͺ¨λν°λ§ν μ μμ΅λλ€.
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.warn(`Long Task: ${entry.name}, Duration: ${entry.duration}ms`);
console.warn(`Long Task Attribution: ${JSON.stringify(entry.attribution)}`);
});
});
observer.observe({ entryTypes: ["longtask"] });
μ΄ μ½λλ longtask
νλͺ©μ μμ νκ³ μμ
μ΄λ¦κ³Ό μ§μ μκ°μ μ½μμ κΈ°λ‘νλ PerformanceObserverλ₯Ό μμ±ν©λλ€. μ΄ λ°μ΄ν°λ₯Ό λΆμνμ¬ μ₯μκ° μ€νλλ μμ
μ μλ³νκ³ μ΄λ₯Ό λ μμ λ©μ΄λ¦¬λ‘ λλκ±°λ, λΉλκΈ° μμ
μ μ¬μ©νκ±°λ, μΉ μμ»€λ‘ μ€νλ‘λνμ¬ μ΅μ νν μ μμ΅λλ€.
κΈλ‘λ² μμ± κ°μ΄λλΌμΈ: κΈ°μ μ μΈ κ°λ μ μ€λͺ ν λλ λ€μν μμ€μ κΈ°μ μ λ¬Έ μ§μμ κ°μ§ λ μκ° μ κ·Όν μ μλ λͺ ννκ³ κ°κ²°ν μΈμ΄λ₯Ό μ¬μ©νμΈμ. μ λ¬Έ μ©μ΄λ₯Ό νΌνκ³ μ΅μνμ§ μμ μ©μ΄μ λν λ§₯λ½μ μ 곡νμΈμ.
4. λ€λΉκ²μ΄μ νμ΄λ° λΆμ
navigation
νλͺ© μ νμ DNS μ‘°ν μκ°, TCP μ°κ²° μκ°, μμ² λ° μλ΅ μκ°, DOM μ²λ¦¬ μκ°μ ν¬ν¨ν νμ΄μ§μ λ€λΉκ²μ΄μ
νμ΄λ°μ λν μμΈν μ 보λ₯Ό μ 곡ν©λλ€. μ΄ λ°μ΄ν°λ νμ΄μ§ λ‘λ© νλ‘μΈμ€μ λ³λͺ© νμμ μλ³νλ λ° μ¬μ©λ μ μμ΅λλ€. μλ₯Ό λ€μ΄, λ€μ μ½λλ₯Ό μ¬μ©νμ¬ λ€λΉκ²μ΄μ
νμ΄λ°μ λΆμν μ μμ΅λλ€.
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log(`Navigation: ${entry.name}`);
console.log(`DNS Lookup Time: ${entry.domainLookupEnd - entry.domainLookupStart}ms`);
console.log(`TCP Connection Time: ${entry.connectEnd - entry.connectStart}ms`);
console.log(`Request Time: ${entry.responseStart - entry.requestStart}ms`);
console.log(`Response Time: ${entry.responseEnd - entry.responseStart}ms`);
console.log(`DOM Processing Time: ${entry.domComplete - entry.domInteractive}ms`);
});
});
observer.observe({ entryTypes: ["navigation"] });
μ΄ μ½λλ navigation
νλͺ©μ μμ νκ³ λ€μν νμ΄λ° μ§νλ₯Ό μ½μμ κΈ°λ‘νλ PerformanceObserverλ₯Ό μμ±ν©λλ€. μ΄ λ°μ΄ν°λ₯Ό λΆμνμ¬ λλ¦° DNS μ‘°ν, λλ¦° TCP μ°κ²°, λλ¦° μμ² μ²λ¦¬, λλ¦° μλ΅ μ²λ¦¬ λλ λλ¦° DOM μ²λ¦¬μ κ°μ λ³λͺ© νμμ μλ³ν μ μμ΅λλ€. κ·Έλ° λ€μ DNS ꡬμ±μ μ΅μ ννκ±°λ, μλ² μ±λ₯μ κ°μ νκ±°λ, HTML λ° μλ°μ€ν¬λ¦½νΈ μ½λλ₯Ό μ΅μ ννλ λ± μ΄λ¬ν λ³λͺ© νμμ ν΄κ²°νκΈ° μν μ μ ν μ‘°μΉλ₯Ό μ·¨ν μ μμ΅λλ€.
SEO μ΅μ ν: μ½ν μΈ μ 체μ κ΄λ ¨ ν€μλλ₯Ό μμ°μ€λ½κ² μ¬μ©νμΈμ. μ΄ μΉμ μμλ "λ€λΉκ²μ΄μ νμ΄λ°", "DNS μ‘°ν μκ°", "TCP μ°κ²° μκ°", "νμ΄μ§ λ‘λ© νλ‘μΈμ€"μ κ°μ ν€μλκ° μμ°μ€λ½κ² ν΅ν©λμμ΅λλ€.
5. λ μ΄μμ λ³κ²½ λͺ¨λν°λ§
layout-shift
νλͺ© μ νμ νμ΄μ§μμ μκΈ°μΉ μμ λ μ΄μμ λ³κ²½μ μΆμ ν©λλ€. μ΄λ¬ν λ³κ²½μ μ¬μ©μμκ² λΆνΈν¨μ μ£Όκ³ μ¬μ©μ κ²½νμ λΆμ μ μΈ μν₯μ λ―ΈμΉ μ μμ΅λλ€. μ’
μ’
ν¬κΈ°κ° μ§μ λμ§ μμ μ΄λ―Έμ§, λ¦κ² λ‘λλλ κ΄κ³ λλ λμ μΌλ‘ μ½μ
λ μ½ν
μΈ λ‘ μΈν΄ λ°μν©λλ€. λ€μ μ½λλ₯Ό μ¬μ©νμ¬ λ μ΄μμ λ³κ²½μ λͺ¨λν°λ§ν μ μμ΅λλ€.
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.warn(`Layout Shift: ${entry.name}, Value: ${entry.value}`);
console.warn(`Layout Shift Had Recent Input: ${entry.hadRecentInput}`);
console.warn(`Layout Shift Sources: ${JSON.stringify(entry.sources)}`);
});
});
observer.observe({ entryTypes: ["layout-shift"] });
μ΄ μ½λλ layout-shift
νλͺ©μ μμ νκ³ λ³κ²½ κ°(λ³κ²½μ ν¬κΈ°λ₯Ό λνλ΄λ μ μ)μ μ½μμ κΈ°λ‘νλ PerformanceObserverλ₯Ό μμ±ν©λλ€. κ°μ΄ λμμλ‘ λ ν° λ³κ²½μ λνλ
λλ€. hadRecentInput
μμ±μ λ³κ²½μ΄ μ¬μ©μ μ
λ ₯ ν 500ms μ΄λ΄μ λ°μνλμ§ μ¬λΆλ₯Ό λνλ
λλ€. μ¬μ©μ μ
λ ₯μ μν΄ νΈλ¦¬κ±°λ λ³κ²½μ μΌλ°μ μΌλ‘ λ λ¬Έμ κ° λλ κ²μΌλ‘ κ°μ£Όλ©λλ€. sources
μμ±μ λ³κ²½μ μΌμΌν¨ μμμ λν μΈλΆ μ 보λ₯Ό μ 곡ν©λλ€. μ΄ λ°μ΄ν°λ₯Ό λΆμνμ¬ μ΄λ―Έμ§μ ν¬κΈ°λ₯Ό μ§μ νκ±°λ, κ΄κ³ 곡κ°μ μμ½νκ±°λ, 리νλ‘μ°λ₯Ό μ λ°ν μ μλ μ½ν
μΈ μ λμ μ½μ
μ νΌν¨μΌλ‘μ¨ λ μ΄μμ λ³κ²½ λ¬Έμ λ₯Ό μλ³νκ³ μμ ν μ μμ΅λλ€.
μ€ν κ°λ₯ν μΈμ¬μ΄νΈ: Googleμ Lighthouseμ κ°μ λꡬλ₯Ό μ¬μ©νμ¬ λ μ΄μμ λ³κ²½ λ¬Έμ λ₯Ό μλ³νκ³ μμ κΆμ₯ μ¬νμ μ»μΌμΈμ. μ¬μ©μ μ λ ₯ μμ΄ λ°μνλ λ³κ²½μ μ°μ μ μΌλ‘ μμ νμΈμ.
6. μ΅λ μ½ν μΈ ν νμΈνΈ(LCP) μΈ‘μ
largest-contentful-paint
νλͺ© μ νμ κ°μ₯ ν° μ½ν
μΈ μμκ° νμ΄μ§μ νμλκΈ°κΉμ§ 걸리λ μκ°μ μΈ‘μ ν©λλ€. LCPλ νμ΄μ§μ μΈμ§λ λ‘λ© μλλ₯Ό λ°μνλ ν΅μ¬ μΉ λ°μ΄νμ
λλ€. μ’μ LCP μ μλ 2.5μ΄ μ΄νμ
λλ€. λ€μ μ½λλ₯Ό μ¬μ©νμ¬ LCPλ₯Ό μΈ‘μ ν μ μμ΅λλ€.
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log(`Largest Contentful Paint: ${entry.startTime}ms`);
console.log(`LCP Element: ${entry.element}`);
console.log(`LCP URL: ${entry.url}`);
});
});
observer.observe({ entryTypes: ["largest-contentful-paint"] });
μ΄ μ½λλ largest-contentful-paint
νλͺ©μ μμ νκ³ μμ μκ°, μμ λ° URLμ μ½μμ κΈ°λ‘νλ PerformanceObserverλ₯Ό μμ±ν©λλ€. μ΄ λ°μ΄ν°λ₯Ό λΆμνμ¬ κ°μ₯ ν° μ½ν
μΈ μμλ₯Ό μλ³νκ³ μ΄λ―Έμ§ ν¬κΈ°λ₯Ό μ΅μ ννκ±°λ, CDNμ μ¬μ©νκ±°λ, 리μμ€λ₯Ό 미리 λ‘λνμ¬ λ‘λ© μκ°μ μ΅μ νν μ μμ΅λλ€.
κΈλ‘λ² κ΄μ : μ¬μ©μμ νλ©΄ ν¬κΈ°μ ν΄μλμ λ°λΌ LCP μμκ° λ¬λΌμ§ μ μλ€λ μ μ κ³ λ €νμΈμ. λ€μν κΈ°κΈ°μ νλ©΄ ν¬κΈ°μμ μ’μ LCP μ μλ₯Ό 보μ₯νλλ‘ μ ν리μΌμ΄μ μ μ€κ³νμΈμ.
7. μ΅μ΄ μ λ ₯ μ§μ°(FID) μΈ‘μ
first-input-delay
νλͺ© μ νμ λΈλΌμ°μ κ° μ²« λ²μ§Έ μ¬μ©μ μνΈμμ©(μ: ν΄λ¦ λλ ν)μ μλ΅νλ λ° κ±Έλ¦¬λ μκ°μ μΈ‘μ ν©λλ€. FIDλ νμ΄μ§μ μνΈμμ©μ±μ λ°μνλ λ λ€λ₯Έ ν΅μ¬ μΉ λ°μ΄νμ
λλ€. μ’μ FID μ μλ 100λ°λ¦¬μ΄ μ΄νμ
λλ€. λ€μ μ½λλ₯Ό μ¬μ©νμ¬ FIDλ₯Ό μΈ‘μ ν μ μμ΅λλ€.
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log(`First Input Delay: ${entry.processingStart - entry.startTime}ms`);
console.log(`Event Type: ${entry.name}`);
console.log(`Target Element: ${entry.target}`);
});
});
observer.observe({ type: "first-input", buffered: true });
μ΄ μ½λλ first-input
νλͺ©μ μμ νκ³ μ§μ° μκ°, μ΄λ²€νΈ μ ν λ° λμ μμλ₯Ό μ½μμ κΈ°λ‘νλ PerformanceObserverλ₯Ό μμ±ν©λλ€. μ΄ λ°μ΄ν°λ₯Ό λΆμνμ¬ κΈ΄ μ
λ ₯ μ§μ°μ μμΈμ μλ³νκ³ μλ°μ€ν¬λ¦½νΈ μ½λλ₯Ό μ΅μ ννμ¬ λ©μΈ μ€λ λμμ μμλλ μκ°μ μ€μΌ μ μμ΅λλ€.
μ€ν κ°λ₯ν μΈμ¬μ΄νΈ: μ₯μκ° μ€νλλ μμ μ λ μμ λ©μ΄λ¦¬λ‘ λλκ³ , μΉ μ컀λ₯Ό μ¬μ©νμ¬ μμ μ λ°±κ·ΈλΌμ΄λ μ€λ λλ‘ μ€νλ‘λνλ©°, μ΄λ²€νΈ 리μ€λλ₯Ό μ΅μ ννμ¬ μ¬μ©μ μνΈμμ©μ μ²λ¦¬ μκ°μ μ€μ΄μΈμ.
κ³ κΈ κΈ°μ λ° κ³ λ € μ¬ν
μμ μ€λͺ λ κΈ°λ³Έ μ¬μ© μ¬λ‘ μΈμλ Performance Observer APIλ μΉ μ ν리μΌμ΄μ μ±λ₯μ λν λ κΉμ ν΅μ°°λ ₯μ μ»κΈ° μν΄ λ κ³ κΈ μλ리μ€μμ μ¬μ©λ μ μμ΅λλ€. λ€μμ λͺ κ°μ§ κ³ κΈ κΈ°μ λ° κ³ λ € μ¬νμ λλ€.
1. λ²νΌλ§ μ¬μ©
observe()
λ©μλμ buffered
μ΅μ
μ μ¬μ©νλ©΄ PerformanceObserverκ° μμ±λκΈ° μ μ κΈ°λ‘λ κ³Όκ±° μ±λ₯ νλͺ©μ κ²μν μ μμ΅λλ€. μ΄λ μ΄κΈ° νμ΄μ§ λ‘λ μ€μ΄λ λͺ¨λν°λ§ μ½λκ° λ‘λλκΈ° μ μ λ°μνλ μ±λ₯ λ°μ΄ν°λ₯Ό μΊ‘μ²νλ λ° μ μ©ν©λλ€. μλ₯Ό λ€μ΄:
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log(`Entry: ${entry.name}, Type: ${entry.entryType}, Duration: ${entry.duration}ms`);
});
});
observer.observe({ entryTypes: ["navigation", "resource"], buffered: true });
μ΄ μ½λλ navigation
λ° resource
νλͺ©μ μμ νκ³ μ΅μ λ²κ° μμ±λκΈ° μ μ κΈ°λ‘λ λͺ¨λ κ³Όκ±° νλͺ©μ κ²μνλ PerformanceObserverλ₯Ό μμ±ν©λλ€.
2. μ±λ₯ νλͺ© νν°λ§
λΆμμ κ°μ₯ κ΄λ ¨ μλ λ°μ΄ν°μ μ§μ€νκΈ° μν΄ νΉμ κΈ°μ€μ λ°λΌ μ±λ₯ νλͺ©μ νν°λ§ν μ μμ΅λλ€. μλ₯Ό λ€μ΄, URL λλ μ½ν μΈ μ νμ λ°λΌ 리μμ€ νλͺ©μ νν°λ§ν μ μμ΅λλ€.
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.entryType === "resource" && entry.name.endsWith(".jpg")) {
console.log(`Image Resource: ${entry.name}, Duration: ${entry.duration}ms`);
}
});
});
observer.observe({ entryTypes: ["resource"] });
μ΄ μ½λλ resource
νλͺ©μ μμ νκ³ .jpg
νμ₯μλ₯Ό κ°μ§ μ΄λ―Έμ§ 리μμ€ νλͺ©λ§ ν¬ν¨νλλ‘ νν°λ§νλ PerformanceObserverλ₯Ό μμ±ν©λλ€.
3. μΉ μ컀 μ¬μ©
λ©μΈ μ€λ λμ μ±λ₯μ μν₯μ λ―ΈμΉμ§ μμΌλ €λ©΄ μ±λ₯ λͺ¨λν°λ§ λ° λΆμμ μΉ μμ»€λ‘ μ€νλ‘λν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ UIλ₯Ό μ°¨λ¨νμ§ μκ³ λ°±κ·ΈλΌμ΄λμμ μ±λ₯ λ°μ΄ν°λ₯Ό μμ§νκ³ μ²λ¦¬ν μ μμ΅λλ€. μλ₯Ό λ€μ΄, μ±λ₯ μ΄λ²€νΈλ₯Ό μμ νκ³ λΆμμ μν΄ λ°μ΄ν°λ₯Ό λ©μΈ μ€λ λλ‘ λ³΄λ΄λ μΉ μ컀λ₯Ό λ§λ€ μ μμ΅λλ€.
κΈλ‘λ² μμ± κ°μ΄λλΌμΈ: κΈλ‘λ² λ μμκ² κ΄λ ¨ μλ μμ λ₯Ό μ¬μ©νμΈμ. νΉμ κ΅κ°λ λ¬Ένμ κ΅νλ μμ λ νΌνμΈμ.
4. λΆμ νλ«νΌκ³Ό ν΅ν©
Performance Observer APIλ₯Ό λΆμ νλ«νΌκ³Ό ν΅ν©νμ¬ μ€μ μμΉμμ μ±λ₯ λ°μ΄ν°λ₯Ό μμ§νκ³ λΆμν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μκ° κ²½κ³Όμ λ°λ₯Έ μ±λ₯ μΆμΈλ₯Ό μΆμ νκ³ , μ±λ₯ μ νλ₯Ό μλ³νλ©°, μ±λ₯ μ§νλ₯Ό λ€λ₯Έ μ¬μ©μ νλ λ°μ΄ν°μ μ°κ΄μν¬ μ μμ΅λλ€. ν΄λΉ APIλ₯Ό μ¬μ©νκ±°λ μλ² μΈ‘ μλν¬μΈνΈμ λ‘κΉ νμ¬ μ±λ₯ νλͺ©μ λΆμ νλ«νΌμΌλ‘ λ³΄λΌ μ μμ΅λλ€.
5. ꡬν λΈλΌμ°μ λ₯Ό μν ν΄λ¦¬ν μ¬μ©
Performance Observer APIλ λλΆλΆμ μ΅μ λΈλΌμ°μ μμ μ§μλμ§λ§ ꡬν λΈλΌμ°μ μμλ μ¬μ©νμ§ λͺ»ν μ μμ΅λλ€. ꡬν λΈλΌμ°μ λ₯Ό μ§μνλ €λ©΄ APIμ λ체 ꡬνμ μ 곡νλ ν΄λ¦¬νμ μ¬μ©ν μ μμ΅λλ€. μ¨λΌμΈμλ μ ν리μΌμ΄μ μμ μ¬μ©ν μ μλ μ¬λ¬ ν΄λ¦¬νμ΄ μμ΅λλ€.
Performance Observer API μ¬μ©μ μν λͺ¨λ² μ¬λ‘
Performance Observer APIλ₯Ό ν¨κ³Όμ μΌλ‘ νμ©νκ³ μΌλ°μ μΈ ν¨μ μ νΌνλ €λ©΄ λ€μ λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄μΈμ.
- λͺ©νμ κ΄λ ¨λ μ§νλ§ λͺ¨λν°λ§νμΈμ. μ±λ₯μ μν₯μ μ€ μ μλ κ³Όλν λ°μ΄ν° μμ§μ νΌνμΈμ.
- κ°μ₯ μ€μν λ°μ΄ν°μ μ§μ€νκΈ° μν΄ νν°λ§μ μ¬μ©νμΈμ. νΉμ κΈ°μ€μ λ°λΌ μ±λ₯ νλͺ©μ νν°λ§νμ¬ μ²λ¦¬ν΄μΌ ν λ°μ΄ν° μμ μ€μ΄μΈμ.
- μ±λ₯ λͺ¨λν°λ§μ μΉ μμ»€λ‘ μ€νλ‘λνμΈμ. μ΄λ κ² νλ©΄ μ±λ₯ λͺ¨λν°λ§μ΄ λ©μΈ μ€λ λμ μ±λ₯μ μν₯μ λ―ΈμΉλ κ²μ λ°©μ§ν μ μμ΅λλ€.
- μκ° κ²½κ³Όμ λ°λ₯Έ μ±λ₯ μΆμΈλ₯Ό μΆμ νκΈ° μν΄ λΆμ νλ«νΌκ³Ό ν΅ν©νμΈμ. μ΄λ₯Ό ν΅ν΄ μ±λ₯ μ νλ₯Ό μλ³νκ³ μ±λ₯ μ§νλ₯Ό λ€λ₯Έ μ¬μ©μ νλ λ°μ΄ν°μ μ°κ΄μν¬ μ μμ΅λλ€.
- ꡬν λΈλΌμ°μ λ₯Ό μ§μνκΈ° μν΄ ν΄λ¦¬νμ μ¬μ©νμΈμ. μ΄λ κ² νλ©΄ μ±λ₯ λͺ¨λν°λ§ μ½λκ° λ€μν λΈλΌμ°μ μμ μλνλλ‘ λ³΄μ₯ν μ μμ΅λλ€.
- μ±λ₯ λͺ¨λν°λ§ μ½λλ₯Ό μ² μ ν ν μ€νΈνμΈμ. μ½λκ° μ체μ μΌλ‘ μ±λ₯ λ¬Έμ λ₯Ό μΌμΌν€μ§ μλμ§ νμΈνμΈμ.
- λ°μ΄ν° κ°μΈ μ 보 λ³΄νΈ κ·μ μ μ μνμΈμ. μ¬μ©μμ λμ μμ΄ κ°μΈ μλ³ μ 보(PII)λ₯Ό μμ§νμ§ μλλ‘ νμΈμ.
SEO μ΅μ ν: λ§€λ ₯μ μΈ λ©ν μ€λͺ μ μμ±νμΈμ. λΈλ‘κ·Έ κ²μλ¬Όμ λ΄μ©μ μμ½ν κ°κ²°ν μ€λͺ μ΄ JSON λ©νλ°μ΄ν°μ μ 곡λ©λλ€.
κ²°λ‘
Performance Observer APIλ κ°λ°μκ° λ°νμ μ±λ₯ μ§νλ₯Ό λͺ¨λν°λ§ λ° λΆμνκ³ , λ³λͺ© νμμ μλ³νλ©°, λ λΆλλ½κ³ λΉ λ₯΄λ©° μ¦κ±°μ΄ μ¬μ©μ κ²½νμ μν΄ μΉ μ ν리μΌμ΄μ μ μ΅μ νν μ μλλ‘ μ§μνλ κ°λ ₯ν λꡬμ λλ€. APIμ μ£Όμ κ°λ κ³Ό κΈ°λ₯μ μ΄ν΄νκ³ μ¬μ© λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄λ©΄ μ ν리μΌμ΄μ μ±λ₯μ λν κ·μ€ν ν΅μ°°λ ₯μ μ»κ³ μμΉλ κΈ°κΈ°μ κ΄κ³μμ΄ μ¬μ©μμκ² λ λμ μ¬μ©μ κ²½νμ μ 곡ν μ μμ΅λλ€. μΉ μ ν리μΌμ΄μ μ΄ μ μ λ 볡μ‘ν΄μ§μ λ°λΌ Performance Observer APIλ μ΅μ μ μ±λ₯κ³Ό μ¬μ©μ λ§μ‘±μ 보μ₯νλ λ° νμμ μΈ λκ΅¬λ‘ κ³μ λ¨μ κ²μ λλ€.
무μ보λ€λ μ¬μ©μ κ²½νμ μ΅μ°μ μΌλ‘ μκ°νλ κ²μ κΈ°μ΅νμΈμ. μ±λ₯ μ΅μ νλ νμ μ¬μ©μμκ² μννκ³ μ¦κ±°μ΄ κ²½νμ μ 곡νλ €λ λͺ©νμ μν΄ μ£Όλλμ΄μΌ ν©λλ€. Performance Observer APIλ₯Ό ν¨κ³Όμ μΌλ‘ μ¬μ©νλ©΄ μ ν리μΌμ΄μ μ μ±λ₯μ λ κΉμ΄ μ΄ν΄νκ³ μ¬μ©μ κ²½νμ κ°μ νκΈ° μν μ 보μ μ κ°ν κ²°μ μ λ΄λ¦΄ μ μμ΅λλ€.
μ±λ₯μ κΈλ‘λ² μν₯μ μ μ€νκ² κ³ λ €ν¨μΌλ‘μ¨ κ°λ°μλ μ μΈκ³ μ¬μ©μμκ² λΉ λ₯΄κ³ λ°μμ΄ μ’μΌλ©° μ κ·Ό κ°λ₯ν μΉ μ ν리μΌμ΄μ μ λ§λ€ μ μμ΅λλ€. μ΄λ₯Ό μν΄μλ λ€νΈμν¬ μ§μ°, κΈ°κΈ° κΈ°λ₯, λ¬Ένμ μ νΈλμ κ°μ μμλ₯Ό κ³ λ €νλ μ 체μ μΈ μ κ·Ό λ°©μμ΄ νμν©λλ€.