Soft Navigations - The-Next-Web-Research-Lab/the-next-web-research-lab.github.io GitHub Wiki
Overview
"Soft Navigation"์ History API ๋๋ ์๋ก์ด Navigation API๋ฅผ ์ฌ์ฉํ๋ JS ๊ธฐ๋ฐ์ same-document navigation์ผ๋ก, ์ฌ์ฉ์ ์ ์ค์ฒ์ ์ํด ํธ๋ฆฌ๊ฑฐ๋์ด ์ด์ ์ปจํ ์ธ ์ ์ฌ์ฉ์์๊ฒ ํ์๋ URL์ ์์ ํ๊ณ DOM์ ์์ ํฉ๋๋ค.
PerformanceTimeline#168๋ Soft Navigation์ ๋ํ ์ฑ๋ฅ ์งํ๋ฅผ ๋ ์ ๋ฆฌํฌํธํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋ผ๋ ํฌ๋ง์ ๊ฐ์ถ๋ ค์ ์ค๋ช ํฉ๋๋ค. Soft Navigation์ ํ์งํ๊ธฐ ์ํ ํด๋ฆฌ์คํฑ์ ๊ฐ๋ฐ์๊ฐ SPA์ ์ฑ๋ฅ ์งํ๋ฅผ ์ธก์ ํ๊ณ ์ฌ์ฉ์์๊ฒ ์ด์ต์ด ๋๋๋ก ์ต์ ํํ ์ ์์ต๋๋ค.
Motivation
์ ์ฐ๋ฆฌ๋ Soft Navigation์ ์น์์ ๋ ธ์ถ์ํค๋ ค๊ณ ํ ๊น์?
๋ช ๊ฐ์ง ์ด์ :
- ๊ฐ๋ฐ์๋ค์ ๋ค์ํ ์ฑ๋ฅ ํญ๋ชฉ์ ํน์ "Soft Navigation" URL์ ๊ท์์ํค๊ณ ์ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํ๋์ URL์์ ๋ฐ์ํ๋ ๋ ์ด์์ ์ํํธ๋ ํ์ฌ ํด๋น ๋๋ฉ ํ์ด์ง์ ๊ท์๋ ์ ์์ผ๋ฉฐ, ์ด๋ก ์ธํด ์๋ชป๋ ์์ฑ์ด ๋ฐ์ํ๊ณ ์ค์ ์์ธ์ ์ฐพ๊ณ ํด๊ฒฐํ๋ ๋ฐ ์ด๋ ค์์ด ์์ต๋๋ค.
- ๊ฐ๋ฐ์๋ค์ Soft Navigation์ ์ํ ๋ค์ํ "Load" ์ฑ๋ฅ ํญ๋ชฉ์ ๋ฐ๊ธฐ๋ฅผ ์ํฉ๋๋ค. ํนํ, ํ์ธํธ ํ์ด๋ฐ ํญ๋ชฉ์ ๊ทธ๋ฌํ ๋ด๋น๊ฒ์ด์ ์ ์ํ๋ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค.
์ฌ์ฉ์์ ๊ด์ ์์, ์ฌ์ฉ์๋ค์ ๋ฐฉ๋ฌธํ ์ฌ์ดํธ์ ์ํคํ ์ฒ์ ์ ๊ฒฝ ์ฐ์ง๋ ์์ง๋ง, ์ฌ์ฉ์๋ค์ ์๋์๋ ์ ๊ฒฝ์ ์ธ ๊ฒ์ ๋๋ค. ์ด ์ฌ์์์๋ ์ธก์ ์ด ์ฌ์ฉ์ ๊ฒฝํ๊ณผ ์ผ์นํ ์ ์๊ฒ ํ์ฌ, SPA ์ฌ์ดํธ๊ฐ ๋น ๋ฅด๊ฒ ๊ฐ์ ๋์ด ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์๋ ๊ฒ์ ๊ธฐ๋ํฉ๋๋ค.
Proposed Heuristics
- ์ฌ์ฉ์๋ DOM Element๋ฅผ ํด๋ฆญํ์ฌ soft navigation์ ์์ํฉ๋๋ค.
- ์ฐ๋ฆฌ๋ semantic elements๋ง ๊ณ ๋ คํ์ง๋ง, ์ด๊ฒ์ ํ์ฌ ํ์ค ์ธ๊ณ์ ๊ด๋ก์ ์ผ์นํ์ง ์์ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
- ์ด ์์ ์ผ๋ก ์ธํด ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค("ํด๋ฆญ" ์ด๋ฒคํธ ๋๋ "๋ด๋น๊ฒ์ด์ " ์ด๋ฒคํธ)
- ๊ทธ๋ฐ ๋ค์ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์ํด ํธ๋ฆฌ๊ฑฐ๋ ์์
์ ์ํํฉ๋๋ค.
- "๋ด๋น๊ฒ์ด์ " ์ด๋ฒคํธ์ธ ๊ฒฝ์ฐ ์ด๋ฌํ ์์ ์ traverseTo()์ ์ ๋ฌ๋ Promise์ ์ผ๋ถ์ ๋๋ค.
- "ํด๋ฆญ" ์ด๋ฒคํธ์ธ ๊ฒฝ์ฐ ํด๋น ์์ ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์์ฒด์์ ์์ฑ๋ฉ๋๋ค.
- "ํด๋ฆญ" ์ด๋ฒคํธ์ ๊ฒฝ์ฐ ํธ๋ค๋ฌ๋ History.pushState() ๋๋ History.placeState() ํธ์ถ ๋๋ ๋ฌธ์ ์์น ๋ณ๊ฒฝ์ ํฌํจํ๋ ํ์คํฌ๋ฅผ ํธ๋ฆฌ๊ฑฐํ์ต๋๋ค.
- ์์
์ DOM ์์๋ฅผ ์์ ํฉ๋๋ค.
- ์ฐ๋ฆฌ๋ ํด๋ฆฌ์คํฑ์ด ๋๋ฌด ๊ด๋ฒ์ํ๊ณ ๋ด๋น๊ฒ์ด์ ์ผ๋ก ๊ฐ์ฃผ๋์ด์๋ ์ ๋๋ ์์ ์ฌํญ์ ์บก์ฒํ๋ ๊ฒฝ์ฐ๋ฅผ ๋๋นํ์ฌ "์๋ฏธ ์๋" DOM ์์ ์ฌํญ๊ณผ ๊ด๋ จํ์ฌ ํน์ DOM ์์ ๋๋ ๊ธฐํ ํด๋ฆฌ์คํฑ์ผ๋ก ์ ํํ๋ ค๊ณ ํ ์ ์์ต๋๋ค.
- contentful element๊ฐ ํฌํจ๋ ๋ค์ ํ์ธํธ๋ Soft Navigation์ FCP๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
- ๋ค์ largest contentful element๋ LCP ํญ๋ชฉ์ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค.
- ๋ง์ง๋ง์ผ๋ก, ์ฐ๋ฆฌ๋ ํน์ ๊ธฐ๊ฐ(์: Y์ด๋น X)์ ํ์ง๋๋ Soft Navigation์ ์์ ์ ํํ๋ ๊ฒ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
Task attribution
์์ ํด๋ฆฌ์คํฑ์ ์์ ์ ์ถ์ ํ ์ ์๋ ๋ฅ๋ ฅ๊ณผ ๊ทธ ์ฆ๋ช ๋ ฅ์ ์์กดํฉ๋๋ค. ์ฐ๋ฆฌ๋ ํน์ ์์ ์ด ๋ค๋ฅธ ์ฌ๋์ ์ํด ๊ฒ์๋์๋ค๋ ๊ฒ์ ๋งํ ์ ์์ด์ผ ํ๋ฉฐ, DOM dirtying์ Soft Navigation์ ํธ๋ฆฌ๊ฑฐํ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ URL ์์ ์ฌ์ด์ ์ธ๊ณผ๊ด๊ณ ์ฒด์ธ์ ๋ง๋ค ์ ์์ด์ผ ํฉ๋๋ค.
Note: ์์ ํด๋ฆฌ์คํฑ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ง์ ํ๋ ค๋ฉด ์ด๋ฒคํธ ๋ฃจํ ์ฒ๋ฆฌ์ ์ผ๋ถ๋ก TaskAttribution์ ์ง์ ํด์ผ ํฉ๋๋ค.
Proposed API shape
SoftNavigationEntry : PerformanceEntry {
unsigned long NavigationId;
}
NavigationId๋ Performance Timeline ๋ด์ ์ ์๋ฉ๋๋ค. (explainer)
PerformanceEntry ์์์ ์๋ฏธ๋ startTime, name, entryType, duration`์ ํฌํจํ๋ ๊ฒ์
๋๋ค.
startTime์ ์ฌ์ฉ์์ ํด๋ฆญ์ ๋ฐ์ ์์ ์ ์ ์ํฉ๋๋ค.name์ Soft Navigation์ ๋ํ๋ด๋ ํ์คํ ๋ฆฌ ํญ๋ชฉ์ URL ์ ๋๋ค.entryType์ "soft-navigation"์ ๋๋ค.duration์ ์์ง ์ ์ฉํ ๊ฐ์ด ๋ช ํํ์ง ์๋ค.
Examples
์์ง ๊ณต์ ๋ฐฐํฌ ์ ์ผ๋ก chrome://flags/#enable-experimental-web-platform-features ํ์ฑํ ํ ์ฌ์ฉํ ์ ์์
์ง์ ํ์ธ
const isSupportedSoftNavigation = PerformanceObserver.supportedEntryTypes.includes('soft-navigation');
Soft Navigation ํ์ธ
const softNavigations = [];
const observer = new PerformanceObserver(list => {
softNavigations.push(...list.getEntries());
console.log(...list.getEntries());
});
observer.observe({ type: 'soft-navigation' });
{
"name": "https://github.com/WICG/soft-navigations/blob/main/README.md",
"entryType": "soft-navigation",
"startTime": 343297.30000019073,
"duration": 0,
"navigationId": "0e8e49eb-9642-40e3-b212-36b8ae7b30c1"
}
LCP
const softNavigations = [];
const softNavigationObserver = new PerformanceObserver(list => {
softNavigations.push(...list.getEntries());
console.log(...list.getEntries());
});
softNavigationObserver.observe({
type: 'soft-navigation'
});
const lcpObserver = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
const id = entry.navigationId;
const nav = softNavigations.filter(entry => entry.navigationId === id)[0];
console.log(entry);
}
});
lcpObserver.observe({
type: 'largest-contentful-paint',
includeSoftNavigationObservations: true
});
// SoftNavigationEntry
{
"name": "https://github.com/WICG/soft-navigations/blob/main/README.md",
"entryType": "soft-navigation",
"startTime": 20203.599999904633,
"duration": 0,
"navigationId": "4d5a5f9a-ff90-4371-bb28-c03dc4ceb48e"
}
// LargestContentfulPaint
{
"name": "",
"entryType": "largest-contentful-paint",
"startTime": 20803.799999952316,
"duration": 0,
"navigationId": "4d5a5f9a-ff90-4371-bb28-c03dc4ceb48e",
"size": 94129,
"renderTime": 20803.799,
"loadTime": 0,
"firstAnimatedFrameTime": 0,
"id": "",
"url": ""
}