SlideShare a Scribd company logo
1 of 114
Download to read offline
다음 통합검색 로딩 속도 개선다음 통합검색 로딩 속도 개선
카카오 @김정윤
#검색 #탭 검색 다음 검색
담당 업무담당 업무
Frontend Guide(Convention, Linting, Testing...)
담당 업무담당 업무
Frontend Guide(Convention, Linting, Testing...)
서비스 공통 JS 개발(Polyfill, Libirary, Module...)
담당 업무담당 업무
Frontend Guide(Convention, Linting, Testing...)
서비스 공통 JS 개발(Polyfill, Libirary, Module...)
서비스 JS 개발(News.js, Blog.js, Image.js...)
담당 업무담당 업무
Frontend Guide(Convention, Linting, Testing...)
서비스 공통 JS 개발(Polyfill, Libirary, Module...)
서비스 JS 개발(News.js, Blog.js, Image.js...)
Static Resource Deploy(CSS, JS, Image...)
담당 업무담당 업무
Frontend Guide(Convention, Linting, Testing...)
서비스 공통 JS 개발(Polyfill, Libirary, Module...)
서비스 JS 개발(News.js, Blog.js, Image.js...)
Static Resource Deploy(CSS, JS, Image...)
Web Performance Optimization
담당 업무담당 업무
Web PerformanceWeb Performance
OptimizationOptimization
로딩 속도가 중요한 이유로딩 속도가 중요한 이유
업체 성능 결과
Pinterest 인지 대기 시간 40% 개선 검색엔진 트래픽 15% 증가
가입 전환율 15% 증가
COOK 평균 로드 시간 850ms 개선 전환율 7%증가
이탈율 7% 감소
페이지당 세션 10% 증가
AutoAnything 평균 로드 시간 50% 개선 판매랑 12~13% 증가
로딩 속도 개선 사례로딩 속도 개선 사례
측정할 수 없으면 개선할 수 없다측정할 수 없으면 개선할 수 없다
MeasurementMeasurement
MeasurementMeasurement
ManagementManagement
MeasurementMeasurement
ManagementManagement
ImprovementImprovement
ToolsTools
PageSpeed InsightsPageSpeed Insights
LighthouseLighthouse
WebPageTestWebPageTest
ProblemProblem
WebPageTestWebPageTest
2018.11.26 / Dulles, VA - Chrome - 4G / q=아이유
DAUMDAUM
DOMContentLoaded 8.007s
onLoad 10.352s
NAVERNAVER
DOMContentLoaded 4.268s
onLoad 4.362s
OS(AOS, iOS, 기타) 필터가 없음
네트워크(4G, 3G, 2G, wi-fi) 필터가 없음
1분 단위 평균으로 너무 많은 데이터가 쌓임
최근 6개월 데이터만 적재
일주일 이상의 로그 확인 불가
기존 랜더링 대시보드의 문제점기존 랜더링 대시보드의 문제점
MSA(MicroService Architecture)MSA(MicroService Architecture)
다양한 개별 검색 서비스를 통합해서 노출
MSA(MicroService Architecture)MSA(MicroService Architecture)
다양한 개별 검색 서비스를 통합해서 노출
HTTP/2 최적화HTTP/2 최적화
GoalGoal
ToDo ListToDo List
ToDo 기대 효과
모니터링 툴 개발 로딩 속도 개선 측정
Validator 개발 가이드 준수 여부 체크
Image Lazyloading 적용 Request 감소
JS 동적 로딩 적용 Request 감소
WebP 이미지 적용 Size 감소
HTML Compress 적용 Size 감소
Resource Hints 적용 HTTP/2 대응
공통 CSS 분리 HTTP/2 대응
Global CDN 적용 Global 사용자 대응
Monitoring ToolMonitoring Tool
Real User MonitoringReal User Monitoring
Performance Timing APIPerformance Timing API
performance.timingperformance.timing
Rendering LogRendering Log
// performance timing
{
"rendering": {
"browser": "chrome",
"os": "mac",
"connection": {
"effective": "4g"
},
"navigation": {
"timing": {
"navigationStart": 1570595771462,
"redirectEnd": 0,
"requestStart": 1570595771508,
"responseEnd": 1570595772827,
"domLoading": 1570595772844,
"domContentLoadedEventStart": 1570595774215,
"domContentLoadedEventEnd": 1570595774245,
"domComplete": 1570595774535,
"loadEventStart": 1570595774535,
"loadEventEnd": 1570595775417
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Navigation TimelineNavigation Timeline
Category Timing
browser navigationStart ~ requestStart
network requestStart ~ responseEnd
domLoad domLoading ~
domContentLoadedEventStart
domContentLoaded domContentLoadedEventStart ~
domContentLoadedEventEnd
domComplete domContentLoadedEventEnd ~
loadEventStart
onload loadEventStart ~ loadEventEnd
performance.getEntriesperformance.getEntries
// resource count
{
"rendering": {
"resource": {
"count": {
"timing": {
"afterDomLoad": {
"script": 0,
"css": 0,
"image": 4,
"xhr": 0,
"media": 0,
"other": 0
},
"beforeDomLoad": {
"script": 10,
"css": 1,
"image": 16,
"xhr": 0,
"media": 0,
"other": 0
}
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// resource size
{
"rendering": {
"resource": {
"size": {
"timing": {
"afterDomLoad": {
"script": 0,
"css": 0,
"image": 58.9619140625,
"xhr": 0,
"media": 0,
"other": 0
},
"beforeDomLoad": {
"script": 206.8740234375,
"css": 2.921875,
"image": 102.533203125,
"xhr": 0,
"media": 0,
"other": 0
}
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Rendering LogRendering Log
Timing-Allow-OriginTiming-Allow-Origin
CDN과 같은 외부 리소스의 경우
를 지원해야만
request 사이즈를 가져올 수 있습니다.
Timing-Allow-Origin Header
Synthetic User MonitoringSynthetic User Monitoring
WebPageTestWebPageTest
WebPageTest AutomationWebPageTest Automation
RESTful APIsRESTful APIs
/**
* Test URLs
**/
module.exports = {
'daum': [
{'title': 'weather', 'keyword': '날씨', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'dust', 'keyword': '미세먼지', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'exchange', 'keyword': '환율', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'fortune', 'keyword': '운세', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'baseball', 'keyword': '프로야구', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'movie', 'keyword': '영화', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'tv', 'keyword': 'tv 편성표', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'map', 'keyword': '지도', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'subway', 'keyword': '지하철노선도', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'iu', 'keyword': '아이유', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'},
{'title': 'weather', 'keyword': '날씨', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'dust', 'keyword': '미세먼지', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'exchange', 'keyword': '환율', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'fortune', 'keyword': '운세', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'baseball', 'keyword': '프로야구', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'movie', 'keyword': '영화', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'tv', 'keyword': 'tv 편성표', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'map', 'keyword': '지도', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'subway', 'keyword': '지하철노선도', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'},
{'title': 'iu', 'keyword': '아이유', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}
],
'naver': [
{'title': 'weather', 'keyword': '날씨', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'dust', 'keyword': '미세먼지', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'exchange', 'keyword': '환율', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'fortune', 'keyword': '운세', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'baseball', 'keyword': '프로야구', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'movie', 'keyword': '영화', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'tv', 'keyword': 'tv 편성표', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'map', 'keyword': '지도', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'subway', 'keyword': '지하철노선도', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'iu', 'keyword': '아이유', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'},
{'title': 'weather', 'keyword': '날씨', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'dust', 'keyword': '미세먼지', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'exchange', 'keyword': '환율', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'fortune', 'keyword': '운세', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'baseball', 'keyword': '프로야구', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'movie', 'keyword': '영화', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'tv', 'keyword': 'tv 편성표', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'map', 'keyword': '지도', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'subway', 'keyword': '지하철노선도', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'},
{'title': 'iu', 'keyword': '아이유', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}
]
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Agent DiagramAgent Diagram
Site DiagramSite Diagram
ValidatorValidator
SF.OverlordSF.Overlord
validate dev tool
SF.OverlordSF.Overlord
오류 리포팅
마크업 오류 체크
마크업 주석 체크
CDN 경로 오류 체크
JS 동적로딩 체크
Image Lazyloading 체크
validate dev tool
SF.OverlordSF.Overlord
오류 리포팅
마크업 오류 체크
마크업 주석 체크
CDN 경로 오류 체크
JS 동적로딩 체크
Image Lazyloading 체크
가이드 제공
validate dev tool
Global CDNGlobal CDN
with. Moneywith. Money
Global CDN 적용Global CDN 적용
Coverage: 3%
DOMContentLoaded: 8.007s
onLoad: 10.352s
기존
Global CDN 적용Global CDN 적용
Coverage: 3%
DOMContentLoaded: 8.007s
onLoad: 10.352s
Coverage: 98%
DOMContentLoaded: 4.788s
onLoad: 5.306s
기존
개선
with. Intersection Observer APIwith. Intersection Observer API
LazyLoad ModulesLazyLoad Modules
getBoundClientRect()getBoundClientRect()
function isInViewport(element) {
const bounding = element.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
const domElements = document.querySelectorAll('.my-elems');
document.addEventListener('scroll', () => {
domElements.forEach(domElem => {
if (isInviewport(domElem)) {
// Do something
}
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
IntersectionObserver()IntersectionObserver()
const io = new IntersectionObserver(function(entries, observer) {
entries.forEach(entry => {
const { isIntersecting } = entry;
if (isIntersecting) {
// Do something with your entry.
observer.unobserve(entry.target);
}
});
});
const domElements = document.querySelectorAll('.my-elems');
domElements.forEach(domElem => {
io.observe(domElem);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
https://codepen.io/bowaxwing/embed/QWWbJJm?height=300&theme-id=20849&default-
tab=result
https://github.com/w3c/IntersectionObserver/tree/master/polyfill
SF.viewportSF.viewport
IntersectionObserver API를 사용한 viewport observer module
// Image Lazyload
// element(s)가 뷰포트에 들어오면 SF.loadImage를 실행하여 entry{target}을 로드한다.
SF.viewport('element(s)', function(entry, status) {
SF.loadImage(entry);
});
// 동영상 제어
// viewport에 들어오면 동영상을 재생하고, 나가면 동영상을 일시정지한다
var player = document.getElementById('videoTag');
SF.viewport('element(s)', function(entry, status) {
if (status === 'enter') {
player.play();
} else if(status === 'exit') {
player.pause();
}
});
// JS Lazyload
// element가 뷰포트에 들어오면 'xxx.js'를 로드한다.
// 로드할 'xxx.js' 내부 로직에는 window onload/DOMContentLoaded 콜백 사용을 권장하지 않는다.
SF.viewport('element', function() {
SF.loadJS({
url: 'xxx.js',
done: function() {
// do something
}
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
WebPWebP
“ WebP is a modern image format that provides superior
lossless and lossy compression for images on the web.
Using WebP, webmasters and web developers can create
smaller, richer images that make the web faster.
 
WebP lossless images are  in size compared to
PNGs. WebP lossy images are  than
comparable JPEG images at equivalent  quality index.
 
Lossless WebP supports transparency (also known as
alpha channel) at a cost of just . For
cases when lossy RGB compression is acceptable, lossy
WebP also supports transparency, typically providing 3×
smaller file sizes compared to PNG.
26% smaller
25-34% smaller
SSIM
22% additional bytes
What is WebP? Why should I use it?What is WebP? Why should I use it?
손실/무손실 압축 지원
투명(알파채널) 지원
애니메이션 지원
png대비 26% 적은 용량
JPEG대비 25~34% 적은 용량
구글이 제안한 신규 웹용 이미지 포맷
A new image format for the webA new image format for the web
Browser supportBrowser support
Using WebP in HTMLUsing WebP in HTML
<picture>
<source srcset="some-image.webp" type="image/webp" />
<source srcset="other-image.jpg" type="image/jpeg" />
<img src="other-image.jpg" />
</picture>
1
2
3
4
5
Detecting WebPDetecting WebP
const {SF = {}} = window;
SF.isWebP = false;
const supportWebp = () => {
const $deferred = $.Deferred();
const img = new Image();
img.onload = () => {
$deferred.resolve();
};
img.onerror = () => {
$deferred.reject();
};
img.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA='
return $deferred.promise();
};
supportWebp().then(() => {
SF.isWebP = true;
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SF.loadImageSF.loadImage
SF.viewport를 이용한 Image Lazyloding 모듈
WebP를 지원하는 환경에선 WebP로 변환하여 로딩
SF.loadImageSF.loadImage
with Safari
SF.loadImageSF.loadImage
with Chrome
Resource HintsResource Hints
미리 로드미리 로드<link rel="preload" as="script" href="super-important.js">
<link rel="preload" as="style" href="critical.css">
<link rel="preload" as="font" crossorigin="crossorigin" type="font/woff2" href="myfont.woff2">
1
2
3
미리 연결미리 연결<link rel="preconnect" href="https://example.com">1
미리 가져오기미리 가져오기<link rel="prefetch" href="page-2.html">1
Resource Hints: preconnectResource Hints: preconnect
Resource Hints: preconnectResource Hints: preconnect
공통 CSS 분리 및 최적화공통 CSS 분리 및 최적화
공통 CSS 분리 및 최적화공통 CSS 분리 및 최적화
이전
m_common.css(106/588kb)
이후
m_common.css(45/205kb)
m_engine.css(10.1/57.2kb)
{service} .css
ResultResult
다음 통합검색다음 통합검색AOS/Chrome/4g(1/5~8/1)
다음 통합검색다음 통합검색AOS/Chrome/4g(1/5~8/1)
다음 통합검색다음 통합검색AOS/Chrome/4g(1/5~8/1)
다음 통합검색다음 통합검색AOS/Chrome/4g(1/5~8/1)
속도 개선 이전속도 개선 이전Dulles,VA/Chrome/4g
속도 개선 이전속도 개선 이전
DOMContentLoaded 8.007s
onLoad 10.352s
Dulles,VA/Chrome/4g
속도 개선 이후속도 개선 이후Dulles,VA/Chrome/4g
속도 개선 이후속도 개선 이후
DOMContentLoaded 4.788s
onLoad 5.406s
Dulles,VA/Chrome/4g
Thank YouThank You

More Related Content

Similar to 다음 통합검색 로딩 속도 개선 삽질기

MongoDB 도입을 위한 제언
MongoDB 도입을 위한 제언MongoDB 도입을 위한 제언
MongoDB 도입을 위한 제언DongHan Kim
 
MongoDB 도입을 위한 제언 @krmug
MongoDB 도입을 위한 제언 @krmug MongoDB 도입을 위한 제언 @krmug
MongoDB 도입을 위한 제언 @krmug Ha-Yang(White) Moon
 
Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나JeongHun Byeon
 
WebKit at the Future Web Forum 2010
WebKit at the Future Web Forum 2010WebKit at the Future Web Forum 2010
WebKit at the Future Web Forum 2010Joone Hur
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs기동 이
 
IoT Web App - 수집된 정보의 가공, 처리, 융합
IoT Web App - 수집된 정보의 가공, 처리, 융합IoT Web App - 수집된 정보의 가공, 처리, 융합
IoT Web App - 수집된 정보의 가공, 처리, 융합Hyunghun Cho
 
Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발지수 윤
 
ecdevday3 효율적인 유지보수를 위한 개발 및 관리
ecdevday3 효율적인 유지보수를 위한 개발 및 관리ecdevday3 효율적인 유지보수를 위한 개발 및 관리
ecdevday3 효율적인 유지보수를 위한 개발 및 관리Kenu, GwangNam Heo
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수NAVER D2
 
오픈소스로 만드는 DB 모니터링 시스템 (w/graphite+grafana)
오픈소스로 만드는 DB 모니터링 시스템 (w/graphite+grafana)오픈소스로 만드는 DB 모니터링 시스템 (w/graphite+grafana)
오픈소스로 만드는 DB 모니터링 시스템 (w/graphite+grafana)I Goo Lee
 
글로벌 지도 API 서비스 현황과 미래 - 한국지리정보학회 (2014)
글로벌 지도 API 서비스 현황과 미래 - 한국지리정보학회 (2014)글로벌 지도 API 서비스 현황과 미래 - 한국지리정보학회 (2014)
글로벌 지도 API 서비스 현황과 미래 - 한국지리정보학회 (2014)Channy Yun
 
딥러닝(Deep Learing) using DeepDetect
딥러닝(Deep Learing) using DeepDetect딥러닝(Deep Learing) using DeepDetect
딥러닝(Deep Learing) using DeepDetectJunyi Song
 
Python codelab1
Python codelab1Python codelab1
Python codelab1건희 김
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기현철 조
 
응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angularredribbon1307
 
Clean Front-End Development
Clean Front-End DevelopmentClean Front-End Development
Clean Front-End Development지수 윤
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우Arawn Park
 

Similar to 다음 통합검색 로딩 속도 개선 삽질기 (20)

MongoDB 도입을 위한 제언
MongoDB 도입을 위한 제언MongoDB 도입을 위한 제언
MongoDB 도입을 위한 제언
 
MongoDB 도입을 위한 제언 @krmug
MongoDB 도입을 위한 제언 @krmug MongoDB 도입을 위한 제언 @krmug
MongoDB 도입을 위한 제언 @krmug
 
Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나
 
WebKit at the Future Web Forum 2010
WebKit at the Future Web Forum 2010WebKit at the Future Web Forum 2010
WebKit at the Future Web Forum 2010
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 
IoT Web App - 수집된 정보의 가공, 처리, 융합
IoT Web App - 수집된 정보의 가공, 처리, 융합IoT Web App - 수집된 정보의 가공, 처리, 융합
IoT Web App - 수집된 정보의 가공, 처리, 융합
 
What's new in IE11
What's new in IE11What's new in IE11
What's new in IE11
 
Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발
 
ecdevday3 효율적인 유지보수를 위한 개발 및 관리
ecdevday3 효율적인 유지보수를 위한 개발 및 관리ecdevday3 효율적인 유지보수를 위한 개발 및 관리
ecdevday3 효율적인 유지보수를 위한 개발 및 관리
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수
 
오픈소스로 만드는 DB 모니터링 시스템 (w/graphite+grafana)
오픈소스로 만드는 DB 모니터링 시스템 (w/graphite+grafana)오픈소스로 만드는 DB 모니터링 시스템 (w/graphite+grafana)
오픈소스로 만드는 DB 모니터링 시스템 (w/graphite+grafana)
 
글로벌 지도 API 서비스 현황과 미래 - 한국지리정보학회 (2014)
글로벌 지도 API 서비스 현황과 미래 - 한국지리정보학회 (2014)글로벌 지도 API 서비스 현황과 미래 - 한국지리정보학회 (2014)
글로벌 지도 API 서비스 현황과 미래 - 한국지리정보학회 (2014)
 
딥러닝(Deep Learing) using DeepDetect
딥러닝(Deep Learing) using DeepDetect딥러닝(Deep Learing) using DeepDetect
딥러닝(Deep Learing) using DeepDetect
 
Python codelab1
Python codelab1Python codelab1
Python codelab1
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular
 
Clean Front-End Development
Clean Front-End DevelopmentClean Front-End Development
Clean Front-End Development
 
요즘웹개발
요즘웹개발요즘웹개발
요즘웹개발
 
딥러닝이 바꾸는 애자일 테스팅
딥러닝이 바꾸는 애자일 테스팅딥러닝이 바꾸는 애자일 테스팅
딥러닝이 바꾸는 애자일 테스팅
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 

다음 통합검색 로딩 속도 개선 삽질기

  • 1. 다음 통합검색 로딩 속도 개선다음 통합검색 로딩 속도 개선 카카오 @김정윤
  • 2. #검색 #탭 검색 다음 검색
  • 4. Frontend Guide(Convention, Linting, Testing...) 담당 업무담당 업무
  • 5. Frontend Guide(Convention, Linting, Testing...) 서비스 공통 JS 개발(Polyfill, Libirary, Module...) 담당 업무담당 업무
  • 6. Frontend Guide(Convention, Linting, Testing...) 서비스 공통 JS 개발(Polyfill, Libirary, Module...) 서비스 JS 개발(News.js, Blog.js, Image.js...) 담당 업무담당 업무
  • 7. Frontend Guide(Convention, Linting, Testing...) 서비스 공통 JS 개발(Polyfill, Libirary, Module...) 서비스 JS 개발(News.js, Blog.js, Image.js...) Static Resource Deploy(CSS, JS, Image...) 담당 업무담당 업무
  • 8. Frontend Guide(Convention, Linting, Testing...) 서비스 공통 JS 개발(Polyfill, Libirary, Module...) 서비스 JS 개발(News.js, Blog.js, Image.js...) Static Resource Deploy(CSS, JS, Image...) Web Performance Optimization 담당 업무담당 업무
  • 10. 로딩 속도가 중요한 이유로딩 속도가 중요한 이유
  • 11.
  • 12. 업체 성능 결과 Pinterest 인지 대기 시간 40% 개선 검색엔진 트래픽 15% 증가 가입 전환율 15% 증가 COOK 평균 로드 시간 850ms 개선 전환율 7%증가 이탈율 7% 감소 페이지당 세션 10% 증가 AutoAnything 평균 로드 시간 50% 개선 판매랑 12~13% 증가 로딩 속도 개선 사례로딩 속도 개선 사례
  • 13. 측정할 수 없으면 개선할 수 없다측정할 수 없으면 개선할 수 없다
  • 19.
  • 20.
  • 21.
  • 23.
  • 24.
  • 25.
  • 27.
  • 28.
  • 29.
  • 30.
  • 32. WebPageTestWebPageTest 2018.11.26 / Dulles, VA - Chrome - 4G / q=아이유
  • 35.
  • 36. OS(AOS, iOS, 기타) 필터가 없음 네트워크(4G, 3G, 2G, wi-fi) 필터가 없음 1분 단위 평균으로 너무 많은 데이터가 쌓임 최근 6개월 데이터만 적재 일주일 이상의 로그 확인 불가 기존 랜더링 대시보드의 문제점기존 랜더링 대시보드의 문제점
  • 37.
  • 38. MSA(MicroService Architecture)MSA(MicroService Architecture) 다양한 개별 검색 서비스를 통합해서 노출
  • 39. MSA(MicroService Architecture)MSA(MicroService Architecture) 다양한 개별 검색 서비스를 통합해서 노출
  • 40.
  • 42.
  • 44. ToDo ListToDo List ToDo 기대 효과 모니터링 툴 개발 로딩 속도 개선 측정 Validator 개발 가이드 준수 여부 체크 Image Lazyloading 적용 Request 감소 JS 동적 로딩 적용 Request 감소 WebP 이미지 적용 Size 감소 HTML Compress 적용 Size 감소 Resource Hints 적용 HTTP/2 대응 공통 CSS 분리 HTTP/2 대응 Global CDN 적용 Global 사용자 대응
  • 46. Real User MonitoringReal User Monitoring
  • 49. Rendering LogRendering Log // performance timing { "rendering": { "browser": "chrome", "os": "mac", "connection": { "effective": "4g" }, "navigation": { "timing": { "navigationStart": 1570595771462, "redirectEnd": 0, "requestStart": 1570595771508, "responseEnd": 1570595772827, "domLoading": 1570595772844, "domContentLoadedEventStart": 1570595774215, "domContentLoadedEventEnd": 1570595774245, "domComplete": 1570595774535, "loadEventStart": 1570595774535, "loadEventEnd": 1570595775417 } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  • 50. Navigation TimelineNavigation Timeline Category Timing browser navigationStart ~ requestStart network requestStart ~ responseEnd domLoad domLoading ~ domContentLoadedEventStart domContentLoaded domContentLoadedEventStart ~ domContentLoadedEventEnd domComplete domContentLoadedEventEnd ~ loadEventStart onload loadEventStart ~ loadEventEnd
  • 51.
  • 52.
  • 53.
  • 55. // resource count { "rendering": { "resource": { "count": { "timing": { "afterDomLoad": { "script": 0, "css": 0, "image": 4, "xhr": 0, "media": 0, "other": 0 }, "beforeDomLoad": { "script": 10, "css": 1, "image": 16, "xhr": 0, "media": 0, "other": 0 } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // resource size { "rendering": { "resource": { "size": { "timing": { "afterDomLoad": { "script": 0, "css": 0, "image": 58.9619140625, "xhr": 0, "media": 0, "other": 0 }, "beforeDomLoad": { "script": 206.8740234375, "css": 2.921875, "image": 102.533203125, "xhr": 0, "media": 0, "other": 0 } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Rendering LogRendering Log
  • 56. Timing-Allow-OriginTiming-Allow-Origin CDN과 같은 외부 리소스의 경우 를 지원해야만 request 사이즈를 가져올 수 있습니다. Timing-Allow-Origin Header
  • 57.
  • 58.
  • 63. /** * Test URLs **/ module.exports = { 'daum': [ {'title': 'weather', 'keyword': '날씨', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'dust', 'keyword': '미세먼지', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'exchange', 'keyword': '환율', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'fortune', 'keyword': '운세', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'baseball', 'keyword': '프로야구', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'movie', 'keyword': '영화', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'tv', 'keyword': 'tv 편성표', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'map', 'keyword': '지도', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'subway', 'keyword': '지하철노선도', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'iu', 'keyword': '아이유', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '4G'}, {'title': 'weather', 'keyword': '날씨', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'dust', 'keyword': '미세먼지', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'exchange', 'keyword': '환율', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'fortune', 'keyword': '운세', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'baseball', 'keyword': '프로야구', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'movie', 'keyword': '영화', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'tv', 'keyword': 'tv 편성표', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'map', 'keyword': '지도', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'subway', 'keyword': '지하철노선도', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'}, {'title': 'iu', 'keyword': '아이유', 'url': 'https://m.search.daum.net/search?w=tot&q=', 'connectivity': '3G'} ], 'naver': [ {'title': 'weather', 'keyword': '날씨', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'dust', 'keyword': '미세먼지', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'exchange', 'keyword': '환율', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'fortune', 'keyword': '운세', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'baseball', 'keyword': '프로야구', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'movie', 'keyword': '영화', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'tv', 'keyword': 'tv 편성표', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'map', 'keyword': '지도', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'subway', 'keyword': '지하철노선도', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'iu', 'keyword': '아이유', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '4G'}, {'title': 'weather', 'keyword': '날씨', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'dust', 'keyword': '미세먼지', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'exchange', 'keyword': '환율', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'fortune', 'keyword': '운세', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'baseball', 'keyword': '프로야구', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'movie', 'keyword': '영화', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'tv', 'keyword': 'tv 편성표', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'map', 'keyword': '지도', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'subway', 'keyword': '지하철노선도', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'}, {'title': 'iu', 'keyword': '아이유', 'url': 'https://m.search.naver.com/search.naver?query=', 'connectivity': '3G'} ] }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 74. SF.OverlordSF.Overlord 오류 리포팅 마크업 오류 체크 마크업 주석 체크 CDN 경로 오류 체크 JS 동적로딩 체크 Image Lazyloading 체크 validate dev tool
  • 75. SF.OverlordSF.Overlord 오류 리포팅 마크업 오류 체크 마크업 주석 체크 CDN 경로 오류 체크 JS 동적로딩 체크 Image Lazyloading 체크 가이드 제공 validate dev tool
  • 76. Global CDNGlobal CDN with. Moneywith. Money
  • 77. Global CDN 적용Global CDN 적용 Coverage: 3% DOMContentLoaded: 8.007s onLoad: 10.352s 기존
  • 78. Global CDN 적용Global CDN 적용 Coverage: 3% DOMContentLoaded: 8.007s onLoad: 10.352s Coverage: 98% DOMContentLoaded: 4.788s onLoad: 5.306s 기존 개선
  • 79. with. Intersection Observer APIwith. Intersection Observer API LazyLoad ModulesLazyLoad Modules
  • 80. getBoundClientRect()getBoundClientRect() function isInViewport(element) { const bounding = element.getBoundingClientRect(); return ( bounding.top >= 0 && bounding.left >= 0 && bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) && bounding.right <= (window.innerWidth || document.documentElement.clientWidth) ); } const domElements = document.querySelectorAll('.my-elems'); document.addEventListener('scroll', () => { domElements.forEach(domElem => { if (isInviewport(domElem)) { // Do something } }); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  • 81. IntersectionObserver()IntersectionObserver() const io = new IntersectionObserver(function(entries, observer) { entries.forEach(entry => { const { isIntersecting } = entry; if (isIntersecting) { // Do something with your entry. observer.unobserve(entry.target); } }); }); const domElements = document.querySelectorAll('.my-elems'); domElements.forEach(domElem => { io.observe(domElem); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 82.
  • 84.
  • 86. SF.viewportSF.viewport IntersectionObserver API를 사용한 viewport observer module // Image Lazyload // element(s)가 뷰포트에 들어오면 SF.loadImage를 실행하여 entry{target}을 로드한다. SF.viewport('element(s)', function(entry, status) { SF.loadImage(entry); }); // 동영상 제어 // viewport에 들어오면 동영상을 재생하고, 나가면 동영상을 일시정지한다 var player = document.getElementById('videoTag'); SF.viewport('element(s)', function(entry, status) { if (status === 'enter') { player.play(); } else if(status === 'exit') { player.pause(); } }); // JS Lazyload // element가 뷰포트에 들어오면 'xxx.js'를 로드한다. // 로드할 'xxx.js' 내부 로직에는 window onload/DOMContentLoaded 콜백 사용을 권장하지 않는다. SF.viewport('element', function() { SF.loadJS({ url: 'xxx.js', done: function() { // do something } }); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
  • 87.
  • 89. “ WebP is a modern image format that provides superior lossless and lossy compression for images on the web. Using WebP, webmasters and web developers can create smaller, richer images that make the web faster.   WebP lossless images are  in size compared to PNGs. WebP lossy images are  than comparable JPEG images at equivalent  quality index.   Lossless WebP supports transparency (also known as alpha channel) at a cost of just . For cases when lossy RGB compression is acceptable, lossy WebP also supports transparency, typically providing 3× smaller file sizes compared to PNG. 26% smaller 25-34% smaller SSIM 22% additional bytes What is WebP? Why should I use it?What is WebP? Why should I use it?
  • 90. 손실/무손실 압축 지원 투명(알파채널) 지원 애니메이션 지원 png대비 26% 적은 용량 JPEG대비 25~34% 적은 용량 구글이 제안한 신규 웹용 이미지 포맷 A new image format for the webA new image format for the web
  • 92. Using WebP in HTMLUsing WebP in HTML <picture> <source srcset="some-image.webp" type="image/webp" /> <source srcset="other-image.jpg" type="image/jpeg" /> <img src="other-image.jpg" /> </picture> 1 2 3 4 5
  • 93. Detecting WebPDetecting WebP const {SF = {}} = window; SF.isWebP = false; const supportWebp = () => { const $deferred = $.Deferred(); const img = new Image(); img.onload = () => { $deferred.resolve(); }; img.onerror = () => { $deferred.reject(); }; img.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=' return $deferred.promise(); }; supportWebp().then(() => { SF.isWebP = true; }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  • 94. SF.loadImageSF.loadImage SF.viewport를 이용한 Image Lazyloding 모듈 WebP를 지원하는 환경에선 WebP로 변환하여 로딩
  • 98. 미리 로드미리 로드<link rel="preload" as="script" href="super-important.js"> <link rel="preload" as="style" href="critical.css"> <link rel="preload" as="font" crossorigin="crossorigin" type="font/woff2" href="myfont.woff2"> 1 2 3 미리 연결미리 연결<link rel="preconnect" href="https://example.com">1 미리 가져오기미리 가져오기<link rel="prefetch" href="page-2.html">1
  • 101. 공통 CSS 분리 및 최적화공통 CSS 분리 및 최적화
  • 102. 공통 CSS 분리 및 최적화공통 CSS 분리 및 최적화 이전 m_common.css(106/588kb) 이후 m_common.css(45/205kb) m_engine.css(10.1/57.2kb) {service} .css
  • 104.
  • 105.
  • 110. 속도 개선 이전속도 개선 이전Dulles,VA/Chrome/4g
  • 111. 속도 개선 이전속도 개선 이전 DOMContentLoaded 8.007s onLoad 10.352s Dulles,VA/Chrome/4g
  • 112. 속도 개선 이후속도 개선 이후Dulles,VA/Chrome/4g
  • 113. 속도 개선 이후속도 개선 이후 DOMContentLoaded 4.788s onLoad 5.406s Dulles,VA/Chrome/4g