pagespeed¶
/usr/local/m2/setting.json 다음 영역에 대해 기술한다.
{
"functions": {
"contents": {
"pagespeed": {
...
}
}
}
}
How to use¶
Important
이 함수의 optimg 기능은 pagefx 이미지 최적화 동작과 중복 적용 되지 않는다.
명령어 리스트¶
# 이미지 최적화 및 지연로딩, 스크립트 최적화 지원
https://example.com/view.html/pagespeed/optimg/default/optscript/default
# 이미지 지연로딩 배제 지원
# .class - class 영역
# %23id - 문서 ID 영역. CSS selector의 #을 URL 인코딩 한 %23 을 사용한다.
https://example.com/view.html/pagespeed/optimg/lazyload.ignores=.banner img,%23top-section img
명령어 |
파라미터 |
동작 |
|---|---|---|
|
(하위설정) |
optimg 실행 |
|
(하위설정) |
optvideo 실행 |
|
(하위설정) |
|
|
실드명 |
|
|
(하위설정) |
pagespeed 함수 동작시 다음의 <script> 가 삽입된다.
<script src="https://{서비스도메인}/pagespeed/fe/c309507e-ee3d-41bf-9ae2-0e19ccf03126.js/proxy/src/cache" type="text/javascript" charset="utf-8"></script>
메인 도메인 URL 전처리¶
이 함수는 www 로 대변되는 메인페이지 도메인 전체에 대한 최적화 및 비정상 트래픽 제어를 목적으로 개발되었다.
메인페이지 도메인에서 서비스하는 리소스를 일일이 발라내어 함수를 맵핑하는 것은 현실적으로 어렵다.
# hosting[]
"urlRewrites" : [
{
"pattern": "!FUNCTION[*] & $URL[www.example.com/(.*)]",
"replace": "www.example.com/#1/pagespeed/optimg/default/optvideo/default/protectbot/detect/default/flows/default/originshield/waitqueue-100",
"accessLogUrl": "replace"
}
]
urlRewrites 를 이용해 해당 도메인의 모든 트래픽에 대해 이미지 최적화, 지연 로딩, 로봇 트래픽을 제어한다. urlRewrites 는 설정된 순서대로 동작하기에 같은 도메인에서 서비스하는 다른 리소스(이미지, css, js)에 대한 처리는 더 상위에 정의한다.
트래픽 최적화 전용 전처리¶
이 함수를 최적화 기능 전용으로 사용하고자 한다면 !HEADER[Sec-Fetch-Dest: empty] 조건을 추가하여 처리 범위를 좁힌다.
"urlRewrites" : [
{
"pattern": "!FUNCTION[*] & !HEADER[Sec-Fetch-Dest: empty] & $URL[www.example.com/(.*)]",
"replace": "www.example.com/#1/pagespeed/optimg/default/optvideo/default",
"accessLogUrl": "replace"
}
]
Note
pagespeed 는 페이지를 최적화하며, 처리할 수 없는 콘텐츠는 바이패스 시킨다.
따라서 Sec-Fetch-Dest 헤더 조건과 확장자 제외 필터링을 통해 적용 범위를 최적화한다.
SPA 사이트 연동가이드¶
이 함수는 HTML 문서를 분석하여 각 요소의 리소스를 최적화한다.
SPA 사이트는 대부분의 요소를 프론트엔드 시점에 Javascript를 통해 생성한다.
이 경우 Pagespeed 프론트엔드 연동만으로
<img>,<video>를 최적화 할 수 있다.
연동 방법¶
<script>var M2SPD='this_is_an_accessKey'</script>
<script src="https://cdn.example.com/static/m2/c309507e-ee3d-41bf-9ae2-0e19ccf03126.js?v155"></script>
accessKeyM2에서 프로비저닝 된 API 키
Note
- API키 및 스크립트 배포
연동 효과¶
Pagespeed 백엔드 시스템 운용이 불필요하다.
hyperdims 및 transcoder 함수 운용만으로 사이트의 리소스를 최적화한다.
설정 예제¶
www.example.com 서비스를 최적화하는 설정 예제와 주요 설정이다.
메인 트래픽 최적화¶
기존 서비스 URL 변경없이 www.example.com 메인 트래픽의 모든 이미지, 스크립트를 최적화한다.
{
"hosting": [
{
"name": "www.example.com",
"origin": {
"protocol": "https",
"address": [ "10.10.10.10" ]
},
"urlRewrites" : [
{
"pattern": "!FUNCTION[*] & $URL[www.example.com/(.*)]",
"replace": "www.example.com/#1/pagespeed/optimg/default/optvideo/default/protectbot/detect/default/flows/default",
"accessLogUrl": "replace"
}
],
"functions": {
"network": {
"proxy": {
"meta": {
"enable": true,
"keyword": "proxy"
}
}
},
"contents": {
"pagespeed": {
"meta" : {
"enable" : true,
"keyword": "pagespeed"
},
"optimg": {
"matchingList": [
{
"src": "www.example.com",
"dest": "www.example.com"
}
],
"formats": ["avif","webp"]
},
"optscript": {
"load": {
"level" : 4
}
}
},
"hyperdims": {
"meta" : {
"enable" : true,
"keyword": "hdims"
}
}
}
}
}
]
}
중요 설정은 다음과 같다.
urlRewrites[]- 모든 요청에 대해pagespeed의 스크립트 최적화, 이미지 최적화를 적용한다.functions.network.proxy- 원본 리소스를 최적화 된 트래픽으로 전송하기 위해 활성화한다.functions.contents.pagespeed.optimgmatchingList도메인 분리가 안된(=메인 도메인으로 서비스되는) 이미지를 최적화하기 위해 대상으로 지정한다.formats- 이미지 최적화 포맷으로 [avif,webp] 순으로 브라우저가 지원하는 포맷을 선택한다.
functions.contents.hyperdims- 이미지 최적화를 위해 활성화한다.
분리된 이미지 트래픽 확장¶
엔터프라이즈 서비스에서는 이미지 도메인이 분리된 경우가 일반적이다.
이미지 서비스가 image.example.com 으로 분리되었다면 이미지 최적화 범위를 image.example.com 로 확대한다.
{
"env": {
"network": {
"http2": {
"enable": true
}
}
},
"hosting": [
{
"name": "www.example.com",
"origin": {
"protocol": "https",
"address": [ "10.10.10.10" ]
},
"urlRewrites" : [
{
"pattern": "!FUNCTION[*] & !HEADER[Sec-Fetch-Dest: empty] & $URL[www.example.com/(.*)]",
"replace": "www.example.com/#1/pagespeed/optimg/default",
"accessLogUrl": "replace"
}
],
"functions": {
"network": {
"proxy": {
"meta": {
"enable": true,
"keyword": "proxy"
}
},
"http": {
"frontEnd": {
"bypass": {
"getMethod": {
"enable": true
}
}
},
"backEnd": {
"session":{
"reuseTimeout": 3
}
}
}
},
"contents": {
"pagespeed": {
"meta" : {
"enable" : true,
"keyword": "pagespeed"
},
"optimg": {
"matchingList": [
{
"src": "(.*).example.com",
"dest": "image.example.com",
}
],
"formats": ["avif","webp"]
},
"optscript": {
"load": {
"level" : 4
}
}
}
}
}
}
]
}
functions.network.http.frontEnd.bypass.getMethod- 트래픽을 bypass 한다.functions.contents.pagespeed.optimg.matchingList-example.com하위 모든 이미지를image.example.com도메인을 통해 최적화한다.
Note
- 이미지 최적화 도메인
image.example.com운용을 위해 아래 함수를 사용한다. hyperdims 함수 - 이미지를 최적화 한다.
transcoder 함수 - animated avif를 최적화 한다.
proxy 함수 - 이미지를 최적화 트래픽을 통해 전송한다.
{
"env": {
"network": {
"http2": {
"enable": true
}
}
},
"hosting": [
{
"name": "image.example.com",
"origin": {
"protocol": "https",
"address": [ "s3.com" ]
},
"functions": {
"network": {
"proxy": {
"meta" : {
"enable" : true,
"keyword": "proxy"
}
}
},
"contents": {
"hyperdims": {
"meta" : {
"enable" : true,
"keyword": "hdims"
}
},
"transcoder": {
"meta" : {
"enable" : true,
"keyword": "xcdr"
}
}
}
}
}
]
}
메인 도메인으로 트래픽 통합 demo¶
데모를 통해 분리된 이미지 트래픽의 최적화 효과를 가늠하기 위한 구성이다.
{
"hosting": [
{
"name": "www.example.com",
"origin": {
"protocol": "https",
"address": [ "10.10.10.10" ]
},
"urlRewrites" : [
{
"pattern": "!URLMATCH[(.*)/pagespeed/(.*)] & $URL[www.example.com/(.*)]",
"replace": "www.example.com/#1/pagespeed/optscript/default/optimg/default",
"accessLogUrl": "replace"
}
],
"functions": {
"contents": {
"pagespeed": {
"meta" : {
"enable" : true,
"keyword": "pagespeed"
},
"optimg": {
"matchingList": [
{
"src": "www.example.com",
"dest": "www.example.com",
},
{
"src": "image.example.com",
"dest": "www.example.com",
},
{
"src": "static.cdn.com",
"dest": "www.example.com",
}
]
}
},
"hyperdims": {
"meta" : {
"enable" : true,
"keyword": "hdims"
}
}
},
"network": {
"proxy": {
"meta" : {
"enable" : true,
"keyword": "proxy"
}
}
}
}
}
]
}
메인 트래픽 최적화 를 기반으로 추가된 설정은 다음과 같다.
functions.contents.pagespeed.optimg.matchingList- 분리된 이미지 서비스 도메인인image.example.com과static.cdn.com을www.example.com으로 프록싱한다.functions.network.proxy- proxy 함수를 활성화한다.
서브 도메인의 Bot Protection¶
메인 트래픽(예 www.example.com )에서 처리한 로봇 제어기능을 서브 도메인 (예 api.example.com ) 에서도 처리하기 위해 구성한다.
{
"hosting": [
{
"functions": {
"contents": {
"pagespeed": {
"meta": {
"enable": true
},
"protectbot": {
"meta": {
"enable": true
},
"flows": {
"matchingList": [
...
]
}
}
}
}
},
"urlRewrites" : [
{
"pattern": "$HEADER[Cookie: *_m2spd_*] & $URL[api.example.com/(.*)]",
"replace": "api.example.com/#1/pagespeed/protectbot/flow/default",
"accessLogUrl": "replace"
}
]
}
]
}
Bot Protection 사용을 위해
pagespeed함수와protectbot기능을 활성화 한다.서비스의 일관성을 위해 메인 도메인의
flows설정을 적절히 반영한다.
트러블슈팅¶
이미지 트래픽 분리로 인한 CORS 문제 해결¶
프리로드 등을 목적으로 Ajax를 통한 이미지 요청시, 도메인 변경으로 인한 CORS 에러를 마주할 수 있다. 이때 HTTP 응답헤더 변조 기능 을 통해 문제를 해결할 수 있다.
아래는 www.example.com 도메인의 이미지를 image.example.com 도메인으로 분리시의 가상호스트 설정 예제이다.
{
"hosting": [
{
"name": "image.example.com",
"functions": {
"network": {
"http": {
"frontEnd": {
"headers": {
"modify": {
"enable": true,
"matchingList": [
{
"pattern": "/proxy/*",
"header": "$RES[Access-Control-Allow-Origin: www.example.com]",
"caseSensitive": false,
"mode": "set"
}
]
}
}
}
}
}
}
}
]
}
hosting[].functions.http.frontEnd.headers.modify.matchingList- 이미지 서비스 도메인image.example.com의 응답헤더에Access-Control-Allow-Origin을 추가한다.
캐싱 후 원본 이미지의 특수 헤더 부재 상황 해결¶
M2 캐시엔진은 원본서버가 보내는 헤더 중 캐싱과 관련된 표준 헤더만을 선별적으로 캐싱한다. 이때 원본헤더 전송이 필요하다면 cacheOriginal 설정을 통해 추가할 수 있다.
{
"hosting": [
{
"name": "image.example.com",
"functions": {
"network": {
"http": {
"backEnd": {
"headers": {
"cacheOriginal": {
"enable": true
}
}
}
}
}
}
}
]
}
functions.http.backEnd.headers.cacheOriginal- 이미지 서비스 도메인image.example.com의 응답헤더에 원본 이미지 헤더를 추가한다.
캐싱 후 Post 요청 에러 해결¶
M2 캐시엔진은 Post 캐시 요청을 에러 처리한다. 이 때 postMethod 설정을 통해 허용할 수 있다.
{
"hosting": [
{
"name": "www.example.com",
"functions": {
"network": {
"cache": {
"cachingKey": {
"postMethod": {
"enable": true,
"bodySensitive": true,
"bodyContentLengthMax": 102400
}
}
}
}
}
}
]
}
functions.network.cache.cachingKey.postMethod- 메인 도메인www.example.com의 Post 캐시 요청을 허용한다.
meta¶
"meta" : {
"enable" : true,
"keyword": "pagespeed",
"feJsLocation": null
}
enable (기본: false)pagespeed 활성화
keyword (기본: pagespeed)pagespeed 키워드
feJsLocation (기본: null)pagespeed 프론트엔드 스크립트 다운로드를 특정 도메인에 위임하기 위한 FQDN 형식의 URL.
디버깅 및 테스트 용도로 사용하며, 프로덕션 환경에서 사용을 권장하지 않는다.
apply¶
이 함수는 전처리 설정에 따라 다양한 종류의 트래픽을 처리한다.
본 설정으로 optimg , optvideo , optscript 최적화 동작 범위를 조절한다.
"apply": {
"method": [ "get", "post" ]
"accept": [ "text/html" ],
"requestDest": ["document", "frame", "iframe"],
"ignoredExtensions": [ "json", "xml", "jpg", "woff2", "woff", "css", "js", "jpeg", "webp", "avif", "tiff", "jpg", "png", "gif", "bmp", "svg", "ico", "webm", "mpeg", "mp4", "ogg", "avi", "ts", "flac", "mp3", "wav", "aac", "docx", "xlsx", "pptx", "pdf", "doc", "xls", "ppt", "csv", "log", "txt", "m3u8", "zip", "tar", "rar", "bin", "jar", "gz", "7z" ]
}
method (기본: [get, post])GET,POST메소드를 처리한다.accept (기본: text/html)현재는 원본의
Content-Type헤더가text/html인 콘텐츠만 처리한다.requestDest요청헤더에
Sec-Fetch-Dest헤더가 존재한다면 지정된 대상만 처리한다.ignoredExtensions이 설정은
pagespeed함수의 모든 동작에 대해 무시한다. (protectbot alpha 포함)
Warning
apply설정은 최적화 동작 범위를 조절한다.ignoredExtensions설정만 protectbot alpha 동작에 영향을 미친다.
throttling¶
안정적인 성능보장을 위해 CPU 사용량에 따라 pagespeed 를 동적으로 비활성화한다.
비활성화된 상태의 요청은 원본서버로 바이패스 된다.
"throttling": {
"enable": true,
"cpu": {
"deactive": 60,
"reactive": 40
}
}
enable (기본: true)throttling을 활성화한다.cpu평균 CPU 사용량에 따라 동적으로 기능을 적용한다.
Note
평균 cpu 사용량 기준은 전역으로 변경이 가능하다.
deactive (기본: 60, 범위: 0 ~ 100)평균 CPU 사용량이 설정 값 이상이라면 부하를 낮추기 위해
pagespeed를 적용하지 않는다.reactive (기본: 40, 범위: 0 ~ 100)(
deactive상태에서) 평균 CPU 사용량이 설정 값 미만이라면 다시pagespeed를 적용한다.Note
reactive값이deactive값을 초과하거나 유효 범위가 아니라면deactive의2/3수치로 적용된다.
이상의 값은 기본 값이며 URL전처리를 통해 개별적으로 적용 가능하다.
# CPU 사용량이 60%(기본) 라면 pagespeed는 적용되지 않는다.
.../pagespeed/optimg/default/optscript/default
# CPU 사용량이 70% 미만일 때만 이 요청은 허용된다.
.../pagespeed/optimg/default/optscript/default/throttling/cpu.deactive=70;
optimg¶
웹 문서 내 이미지를 최적화한다.
"optimg": {
"dims": "hdims",
"proxy": "proxy",
"formats": [
"avif",
"webp"
],
"matchingList": [
{
"src": "www.example.com",
"dest": "www.example.com",
},
{
"src": "image.example.com",
"dest": "example.cdn.com"
}
],
"lazyload": {
"enable": true,
"extendTarget": true,
"data-attrs": null,
"ignores": [],
"cssRules": [
{
"pattern": "/(.*)",
"rule": "img[through='m2ps'][src] {min-height:1px;}"
}
]
},
"lqip": {
"enable": false,
"quality": 25,
"resize": ">400"
"format": "jpeg"
"matchingList": []
}
}
dims (기본: hdims)hyperdims 체인함수 키워드
proxy (기본: proxy)proxy 키워드. 원본과 위임 도메인이 다른 경우 한정 프록시가 동작한다.
formats (기본: ["avif"])출력 이미지 포맷. 브라우저 호환성 여부에 따라 설정 순서대로 선택된다.
# formats: [ "avif", "webp", "jpeg", "png" ] # 브라우저 avif 지원시 <img src="image.png/hdims/format/avif;fallback=webp/optimize"> # 브라우저 avif 지원 및 animated 미지원시 <img src="image.png/hdims/format/avif;stillonly;fallback=webp/optimize"> # 브라우저 avif 미지원, webp 지원시 <img src="image.png/hdims/format/webp/optimize"> # 브라우저 webp 미지원시 <img src="image.png/hdims/format/jpeg/optimize"> # 브라우저 jpeg 미지원시 <img src="image.png/hdims/optimize">
Note
85.54%의 브라우저가avif포맷을 지원한다. (24년 3월 기준 호환성)
matchingList (기본: [])이미지 최적화 대상 도메인 리스트
Note
웹 페이지와 같은 도메인이라도 명시적으로 선언해주어야 이미지 최적화가 동작한다.
# functions.contents.pagespeed.optimg.matchingList[] { "src": "www.example.com", "dest": "www.example.com", }
설정에 따른 예시 (optimg, optvideo 동일 규칙)
# proxy: proxy, matchingList: {src: foo.com, dest: bar.com} https://bar.com/proxy/src/https://foo.com/image.jpg/hdims/format/avif/optimize # proxy: null, matchingList: {src: foo.com, dest: bar.com} https://bar.com/image.jpg/hdims/format/avif/optimize # proxy: null, matchingList: {src: foo.com, dest: bar.com/routes} https://bar.com/routes/image.jpg/hdims/format/avif/optimize # proxy: proxy, matchingList: {src: foo.com, dest: bar.com/routes} https://bar.com/routes/proxy/src/https://foo.com/image.jpg/hdims/format/avif/optimize # proxy: proxy, matchingList: {src: bar.com, dest: bar.com/routes} # 원본과 위임할 도메인이 같다면, proxy 처리하지 않는다. https://bar.com/routes/image.jpg/hdims/format/avif/optimize
lazyload¶
enable (기본: true)이미지를 지연로딩 처리한다.
extendTarget (기본: true)true모든<img>를 지연로딩한다.false이미지 최적화 대상 도메인의<img>를 지연로딩한다.
data-attrs (기본: null)이미지
src가 없는 요소의data-속성을 감지하여 최적화한다.media브라우저 미디어 타입mobile모바일 스크린(max-width: 768px)desktop데스크탑 스크린(min-width: 768px)default모든 미디어 타입
name속성 이름
# 모바일 data-src-m, 데스크탑 data-src-pc, 기본 data-src 순으로 속성을 감지하여 최적화한다. "data-attrs": [ {"media": "mobile", "name": "data-src-m"}, {"media": "desktop", "name": "data-src-pc"}, {"media": "default", "name": "data-src"} ]
ignores (기본: null)pattern지연로딩 배제 경로 조건. 정규식을 사용할 수 있으며, 항목 부재시 모든 페이지에 반응한다.selector지연로딩 배제 영역 CSS Selector를 설정한다. 매칭된 첫 항목을 채택한다.
Note
functions.contents.pagespeed.optimg.lazyload.ignores[]# 모든 페이지의 .preload 영역의 이미지를 지연로딩 배제한다. { "selector": ".preload img" } # /prddesc 하위 페이지의 모든 이미지를 지연로딩 배제한다. { "pattern": "/prddesc/(.*)" "selector": "img" } # /index.html 페이지의 .preload, #banner 영역의 이미지를 지연로딩 배제한다. { "pattern": "/index.html", "selector": ".preload img, #banner img" }
cssRules이미지 지연로딩 대상 요소의 영역확보를 위한 스타일을 삽입한다.
pattern지연로딩 대상 페이지 경로.null이면 모든 페이지에 반응한다.rule지연로딩 대상에 적용할 스타일
Note
lazyload동작은loading=lazy속성을 추가하는 것으로 로딩을 지연시킨다.M2를 통해 처리되었음을 인지할 수 있도록
through=m2ps속성이 함께 추가된다.
# 원본 예)
<img src="image.jpg">
# 지연로딩 적용시
<img src="image.jpg" loading="lazy" through="m2ps">
lqip¶
LQIP(Low Quality Image Placeholder) 기능을 통해 이미지를 점진적으로 로딩한다. 콘텐츠 영역을 시각적으로 더 빠르게 채워 고해상도 이미지 로딩시 사용자 경험이 향상된다.
Important
- LQIP 기능은 다음의 상황에 적용시 효과적이다.
페이지 로딩시 가장 넓은 영역을 차지하는 Hero Element 영역내 이미지의 신속한 로딩
상품상세와 같이 이미지 크기와 용량이 큰 이미지의 신속한 로딩
LQIP 대상 이미지는 지연로딩(Lazyload) 기능이 동작하지 않는다.
enable (기본: false)지정한 영역의 이미지를 LQIP 처리한다.
quality (기본: 25)Placeholder 이미지의 퀄리티
resize (기본: >400)Placeholder 이미지의 최대 크기. 이미지 폭이 설정값보다 크면 리사이즈한다.
format (기본: jpeg)Placeholder 이미지의 포맷
matchingList (기본: null)pattern경로 조건. 정규식을 사용할 수 있다.selector대상 이미지를 포함하는 상위영역 CSS Selector. 매칭된 첫 항목을 채택한다.{attr-name}기본 속성 중 오버라이딩 할 항목을 정의한다.
# 설정 예
"lqip": {
"enable": true,
"matchingList": [{
"pattern": "/product/(.*)",
"selector": "#prddesc",
}]
}
# 원본 예
<img src="https://example.com/image.jpg">
# 최적화 예
<img src="https://example.com/image.jpg/hdims/format/jpeg/interlace/true/quality/25/resize/>400"
m2ps-lqipid="uuid" fetchpriority="high" through="m2ps">
<img src="https://example.com/image.jpg/hdims/format/avif/optimize"
style="display: none;" through="m2ps"
onload="try{var src=this.src; document.querySelector('img[m2ps-lqipid=uuid]').forEach(function(el){el.src=src})}catch(e){}" >
optvideo¶
웹 문서 내 MP4 비디오를 WebM 및 MP4 AV1 포맷으로 최적화한다.
"optvideo": {
"transcoder": "xcdr",
"proxy": "proxy",
"compatibleAV1": {
"device": {
"ios": true
}
},
"matchingList": [
{
"src": "video.com",
"dest": "cdn.com"
}
],
"lazyload": {
"enable": true,
"extendTarget": true,
"data-attrs": null,
"ignoreSelectors": null,
"preload": null
},
"poster": {
"enable": true,
"ts": "0.0"
},
"fallbacks": {
"enable": true,
"action": "error",
"conditions": []
}
}
transcoder (기본: xcdr)transcoder 체인함수 키워드
proxy (기본: proxy)proxy 키워드. 원본과 위임 도메인이 다른 경우 한정 프록시가 동작한다.
compatibleAV1¶
WebM AV1포맷 미지원 브라우저에 대해MP4 AV1포맷을 이용한 후속 최적화를 지원한다.
device (기본: {ios: true})후속 최적화 여부는 디바이스 코덱을 지원하는지 판단한다.
Important
최적화 포맷이 채택되는 환경과 시점는 다음과 같다.
포맷
프리셋
지원 환경
판단 시점
비고
WebM (AV1)
_mp42webm
AOS, DESKTOP
백엔드
Chrome 70, Edge 121, Firefox 67, Safari 16 부터 지원
MP4 (AV1)
_mp42av1
iOS
브라우저
iPhone 15 & iOS 16.4 이상 브라우저 API 재생 보장시 지원
MP4 (AV1)포맷 채택시, 브라우저의 판단 이후부터 최적화하며, 이전까지의 요청은 원본이 노출된다.이때 브라우저는 Cookie로 관련 정보를 암호화하여 전송한다.
m2ps.optvideo={"preset":"_mp42av1"}
matchingList¶
비디오 최적화 대상 도메인 리스트
# 원본 예 <video src="https://video.com/sample.mp4"></video> <video> <source src="https://video.com/sample.mp4" type="video/mp4"> </video> # Chrome 최적화 예 <video src="https://cdn.com/proxy/src/https://video.com/sample.mp4/xcdr/preset/_mp42webm" through="m2ps"> <source src="https://video.example.com/sample.mp4" type="video/mp4" through="m2ps"> # fallback을 위해 추가 </video> <video through="m2ps"> <source src="https://cdn.com/proxy/src/https://video.com/sample.mp4/xcdr/preset/_mp42webm" type="video/webm; codecs=av01.0.05M.08" through="m2ps"> <source src="https://video.example.com/sample.mp4" type="video/mp4" through="m2ps"> </video> # Safari 최적화 예 <video src="https://cdn.com/proxy/src/https://video.com/sample.mp4/xcdr/preset/_mp42av1" through="m2ps"> <source src="https://video.example.com/sample.mp4" type="video/mp4" through="m2ps"> </video> <video through="m2ps"> <source src="https://cdn.com/proxy/src/https://video.com/sample.mp4/xcdr/preset/_mp42av1" type="video/mp4" through="m2ps"> <source src="https://video.example.com/sample.mp4" type="video/mp4" through="m2ps"> </video>Note
88.51%의 브라우저가webm포맷을 지원한다. (24년 11월 기준 호환성)
lazyload¶
enable (기본: true)비디오를 지연로딩한다.
autoplay속성 존재시 삭제한다.extendTarget (기본: true)true모든
<video>를 지연로딩한다.false비디오 최적화 대상 도메인의
<video>를 지연로딩한다.
data-attrs (기본: null)비디오
src가 없는 요소의data-속성을 감지하여 최적화한다.media브라우저 미디어 타입mobile모바일 스크린(max-width: 768px)desktop데스크탑 스크린(min-width: 768px)default모든 미디어 타입
name속성 이름
# 모바일 data-src-m, 데스크탑 data-src-pc, 기본 data-src 순으로 속성을 감지하여 최적화한다. "data-attrs": [ {"media": "mobile", "name": "data-src-m"}, {"media": "desktop", "name": "data-src-pc"}, {"media": "default", "name": "data-src"} ]
ignoreSelectors (기본: null)지연로딩 배제 대상 영역의 CSS Selector를 설정한다.
preload (기본: auto)지연로딩 레벨을 정의한다.
none비디오 메타정보와 영상 데이터를 미리 로딩하지 않는다.
# <video src="/sample.mp4"> <video src="/sample.mp4/xcdr/preset/_720p" preload="metadata" through="m2ps"></video>
metadata비디오 메타정보만 미리 로딩한다.
# <video src="/sample.mp4"> <video src="/sample.mp4/xcdr/preset/_720p" preload="none" through="m2ps"></video>
auto비디오 속성 및 재생 시점에 따라
none,metadata를 선택적으로 사용한다.# <video src="/sample.mp4" style="width:100%; height:100%;"> <video src="/sample.mp4/xcdr/preset/_720p" preload="none" through="m2ps"></video> # <video src="/sample.mp4" autoplay controls> <video src="/sample.mp4/xcdr/preset/_720p" preload="metadata" through="m2ps"></video> # <video src="/sample.mp4" onloadeddata="console.log(this)"> <video src="/sample.mp4/xcdr/preset/_720p" through="m2ps"></video>
poster¶
transcoder 함수의 capture 기능으로 <video> 의 포스터를 생성한다.
enable (기본: true)<video>의poster속성 추가. 만약 원본 속성이 있다면 처리하지 않는다.ts (기본: 0.0)추출할 비디오 위치
Note
추출시 이미지 포맷은 optimg 기능의 최적화 포맷을 사용한다. 단,
avif포맷은 지원하지 않는다.기능 비활성시 capture 기능의
format설정에 따른다.비디오에 시작 위치를 명시했다면 설정보다 우선한다.
# 원본
<video src=".../sample.mp4" poster=".../image.jpg">
# 원본 poster 부재 시 예)
<video src=".../sample.mp4/xcdr/preset/_720p" poster=".../sample.mp4/xcdr/capture/ts=0.0;format=webp" through="m2ps"></video>
# 원본 poster 존재 시, optimg 활성시 예)
<video src=".../sample.mp4/xcdr/preset/_720p" poster=".../image.jpg/hdims/format/avif/optimize" through="m2ps"></video>
# 원본에 시작 위치 명시 예) <video src="sample.mp4#t=1">
<video src=".../sample.mp4/xcdr/preset/_720p#t=1" poster=".../sample.mp4/xcdr/capture/ts=1;format=webp" through="m2ps"></video>
fallbacks¶
enable (기본: true)비디오 변환 예외시 fallback 동작을 정의한다.
action (기본: error)비디오 변환 중 transcoder 예외처리 동작을 정의하며,
/exception/redirect와 같은 suffix가 추가된다.redirect원본 비디오 리디렉션error510 상태코드와 관련 정보 JSON 응답. 원본 fallback을 위해<video onerror>속성이 자동 추가된다.origin원본 Bypass 응답Warning
HLS 포맷 기반의 비디오인 경우
origin동작은 권장되지 않는다. 상대경로ts요청시 잘못된 URL이 요청될 수 있다.
conditions (기본: [])비디오 변환 시 사전정의된 throw 동작을 정의한다.
oversourcesize비디오 변환 결과가 원본보다 크다면fallback동작을 따른다.missframe동영상 원본이 비정상 프레임을 가진 경우fallback동작을 따른다.
optscript alpha¶
웹 문서의 초기 로딩속도 향상을 위해 스크립트 로딩을 최적화한다.
"optscript": {
"load": {
...
},
"proxy": {
...
}
}
load¶
스크립트 로딩 순서를 최적화하여 초기로딩 속도를 향상한다.
"load": {
"level" : 3,
"matchingList": [
{
"pattern": "external.com/(.*)",
"level": 2
}
]
}
level (기본: 3)최적화 레벨을 지정한다.
최적화 레벨 |
설명 |
|---|---|
0 |
최적화 하지 않는다. |
1 |
비동기(async) 선언된 자바스크립트를 문서 로딩 이후(defer) 처리한다. |
2 |
외부 자바스크립트를 문서 로딩 이후(defer) 처리한다. |
3 |
외부 자바스크립트를 페이지 로딩 이후 처리한다. |
4 |
모든 자바스크립트를 페이지 로딩 이후 처리한다. |
matchingList¶
최적화 제어 목록
pattern매칭 패턴
level최적화 레벨
proxy¶
외부 호스트의 스크립트를 프록시 처리한다.
"proxy": {
"enable": true,
"domain": null,
"ttl": "10m",
"matchingList": [
{
"pattern": "external.com/(.*)",
"action": "deny"
}
]
}
enable (기본: true)프록시 기능을 사용한다.
domain (기본: null)트래픽 위임할 도메인을 지정한다.
미지정시 메인 트래픽을 사용한다.
ttl (기본: 10m)프록싱 대상 스크립트를 TTL 시간동안 캐싱한다.
matchingList¶
최적화 제어 목록
pattern매칭 패턴
action (기본: deny)deny또는allowttl캐싱 시간.
allow시 값이 없다면 상위설정인proxy.ttl을 사용한다.
originshield alpha¶
클라이언트 요청량 제어를 통해 원본 서버 부하를 낮춘다.
"originshield": [
{
"enable": true,
"name": "waitqueue-100",
"threshold" {
"concurrent": 100,
"waitQueue" : 10000,
"timeout": 30
},
"timeout" : {
"action" : "deny",
"url" : null
}
}
]
enable (기본: false)origin shield 동작 활성화
name실드 이름. 운영중인 이름을 변경시 대기큐가 초기화된다.
threshold¶
concurrent (기본: 100)원본 서버로 동시 요청량 제한
waitQueue (기본: 10000)동시 요청량이
concurrent초과시 최대 대기 큐timeout (기본: 30)최대 대기 시간(초)
timeout¶
대기큐를 초과하거나 타임아웃으로 처리할 수 없는 요청 흐름을 제어한다.
action (기본: deny)
deny상태코드510응답한다.
redirecturl경로의302리디렉션 또는200정적파일 응답한다.url (기본: null)
https://클라이언트의 리디렉션 대상 URL
file://정적 파일 경로 (접근 불가시deny응답)"timeout": { "action": "redirect", "url": "file:///path/to/file.html" }
protectbot alpha¶
웹 크롤러 등 로봇을 통한 HTTP 요청을 제어한다.
"protectbot": {
"meta": {
"enable": true,
"OverridingCmd": false
},
"detect": {
"userAgent": {
"enable": true
},
"cookie": {
"enable": true
},
"js": {
"enable": true
}
},
"flows": {
"matchingList": []
}
}
meta¶
"meta" : {
"enable" : false,
"OverridingCmd" : false
}
enable (기본: false)Protect Bot 동작 활성화
OverridingCmd (기본: false)명령어에 의한 설정 오버라이딩 활성화
프로덕션 환경에서는 사용하지 않는다.
detect¶
"detect": {
"userAgent": {
"enable": true
},
"cookie": {
"enable": true,
"name": "_m2spd_",
"ttl": 300,
"chipsDomains": [
"foo.com",
"bar.com"
]
},
"js": {
"enable": true,
"category": {
"api": true,
"headless": true,
"graphics": true,
"audio": true,
"locale": true,
"cookie": true,
"input": true,
"system": true,
"playwright": true,
"pow": {
"enable": true,
"difficulty": "medium",
"ttl": {
"unknown": 0,
"suspicious": 0
}
}
},
"score": {
"human": 0,
"unknown": 40,
"suspicious": 99,
"bot": "*"
}
}
}
userAgent클라이언트의
User-Agent를 활용해 bot을 탐지한다.enable (기본: true)User-Agent를 활용한 bot 탐지 기능 활성화
Important
쿠키 활성시 브라우저의 AJAX 요청 처리를 위해 아래와 같은 설정이
urlRewrites에 추가되어야 한다."urlRewrites": [{ "pattern": "$HEADER[Cookie: *_m2spd_*] & $URL[www.example.com/(.*)]", "replace": "www.example.com/#1/pagespeed/protectbot/flow/default" }]
js클라이언트 브라우저 환경을 통해 bot을 탐지한다.
enable (기본: true)브라우저 정보를 활용한 bot 탐지 기능 활성화
categoryapi (기본: true)브라우저의 API를 활용한 Bot 탐지
headless (기본: true)puppeteer와 같은 headless 브라우저 탐지
graphics (기본: true)브라우저의 렌더링 정보를 활용한 Bot 탐지
audio (기본: true)오디오 정보를 활용한 Bot 탐지
locale (기본: true)시간대 및 언어 정보를 활용한 Bot 탐지
cookie (기본: true)cookie 기능 동작 여부를 활용한 Bot 탐지
input (기본: true)키보드, 마우스, 터치패널 등의 각종 입력디바이스를 활용한 Bot 탐지
system (기본: true)시스템 정보(OS, 메모리, 파일시스템 등)를 활용한 Bot 탐지
playwright (기본: true)Playwright를 사용한 자동화된 클라이언트 감지
powPoW(Proof-of-work)를 통해 불분명한 클라이언트 브라우저의 자원소비량을 인위적으로 늘려 이탈 또는 요청량 감소를 유도한다.
enable (기본: true)PoW 동작 활성화
difficulty (기본: medium)low저난이도 연산을 통해 PoW 수행이 가능한 JS 엔진 지원 여부를 확인한다.medium중난이도 연산을 통해 대량 요청 시 자원 부담을 유도한다.hard고난이도 연산을 통해 소량 요청에도 자원 부담이 발생하도록 유도한다.
ttl타입별 PoW TTL. 0일 경우 매 요청마다 수행한다.
unknown (기본: 0)unknown 유저의 PoW TTLsuspicious (기본: 0)suspicious 유저의 PoW TTL
score누적 점수를 분류하기 위한 구간을 설정한다.
human (기본: 0)해당 점수 이하를 human으로 분류한다.unknown (기본: 40)해당 점수 이하를 unknown으로 분류한다.suspicious (기본: 99)해당 점수 이하를 suspicious로 분류한다.bot (기본: *)해당 점수 이하를 bot으로 분류한다.*설정시 나머지 모든 점수를 bot으로 간주한다.
Important
봇 활동 감지시, 건당 누적되는 점수는 아래와 같다.
점수 |
설명 |
예시 |
|---|---|---|
1 - 40 |
비정상적인 브라우저 정보 |
입출력장치 부재, CPU 및 메모리 감지 불가 |
41 - 99 |
간접적인 봇 활동 |
API 부재, 비정상적인 창크기 |
100 이상 |
직접적인 봇 활동 |
Headless 감지, Webdriver 감지, CDP 감지, Playwright 스크립트 감지, 매크로 감지 |
flows¶
로봇 요청에 대한 트래픽을 제어한다.
"flows": {
"matchingList": [
{
"pattern": "$URL[/*]",
"type" : "human",
"action": "bypass"
},
{
"pattern": "$URL[/*]",
"type" : "unknown",
"action": "bypass"
},
{
"pattern": "$URL[/*]",
"type" : "suspicious",
"action": "bypass"
},
{
"pattern": "$URL[/*]",
"type" : "bot",
"action": "cache",
"cache" : {
"ttl" : 600,
"modify": {
"requestHeader": [
{
"key": "Authorization",
"value": "-"
}
],
"postBody": [
{
"key": "authorization[0].token.value",
"value": "-"
}
]
},
"timestamp": {
"enable": false,
"queryString": [ "*" ],
"postBody": {
"maxLength": 102400,
"list": [ "*" ]
},
"delta": "5s"
}
}
}
]
}
matchingList (기본: [])매칭리스트
pattern매칭시킬 패턴. urlRewrites 참조.
$URL[]HTTP 요청 URL을 정규표현식으로 검사/치환한다.$URLMATCH[]HTTP 요청 URL을 정규표현식으로 검사한다.$IP[]IP, IP Range, Bitmask, Subnet 네 가지 형식을 지원한다.$HEADER[]HTTP 요청헤더 값을 검사한다.$PROTOCOL[]HTTP 요청 프로토콜을 검사한다.$FUNCTION[]HTTP 요청 URL에 함수호출이 존재하는지 검사한다.
typehuman사람 유형unknown로봇, 사람을 특정할 수 없는 유형suspicious로봇으로 의심되는 유형bot로봇 유형
actioncache캐시 엔진을 통해 응답한다.bypass원본을 응답한다.deny응답 거부한다.403 Forbidden상태코드 응답.
cachettl (기본: 0)TTL 시간(초).
0이면 캐싱하지 않는다.modifyrequestHeader (기본: [])원본 요청 시 헤더를 overwrite한다.
key헤더명value값
postBody (기본: [])원본 요청 시 Post body를 overwrite한다.
key필드명. 도트 표기법 지원.value값
timestamp원본 요청 시 캐싱키 내 타임스탬프 값을 보정한다.
enable (기본: false)보정을 활성화한다.
queryString (기본: [*])쿼리스트링에 존재하는 타임스탬프 값을 보정한다.
*포함시 전체 보정한다.postBodyPost body에 존재하는 타임스탬프 값을 보정한다. JSON, Form-data, Urlencoded를 지원한다.
maxLength (기본:102400, 단위: bytes)보정 허용할 최대 크기
list (기본: [*])보정 대상 필드.
*포함시 전체 보정한다.
delta (기본: "5s")보정 허용할 서버 시간 기준 오차 범위.
s, m, h, d단위 지원.
Note
Unix 포맷과 ISO 8601 포맷을 지원하며, 세컨드와 밀리세컨드 단위를 지원한다.
# 보정 예시 - cache.ttl을 30으로 설정했을 때 # 쿼리스트링 ?ts=1740000000 -> ?ts=1740000000 ?ts=1740000010 -> ?ts=1740000000 ?ts=1740000019 -> ?ts=1740000000 ?ts=1740000040 -> ?ts=1740000030 ?ts=1740000057 -> ?ts=1740000030 ?ts=1740000117 -> ?ts=1740000090 # 요청 바디 { "ts1": "2025-04-25T05:00:07.777Z", -> "2025-04-25T05:00:00.000Z" "ts2": "2025-04-25T05:00:31.777Z", -> "2025-04-25T05:00:30.000Z" "ts3": "2025-04-25T05:01:06.777Z", -> "2025-04-25T05:01:00.000Z" "ts4": "2025-04-25T05:01:55.777Z", -> "2025-04-25T05:01:30.000Z" "ts5": 1740000098, -> 1740000090 "ts6": 1740000117, -> 1740000090 "ts7": 1740000127, -> 1740000120 }
브라우저 호환성¶
글로벌 96.13% 의 브라우저에서 pagespeed가 동작한다. (23년 9월 기준 호환성)
환경 |
브라우저 |
버전 |
|---|---|---|
DESKTOP |
Chrome Edge Safari Firefox AppleWebKit Whale |
55 이후 14 이후 15.4 이후 (또는 macOS 12.3 이후) 52 이후 613.1 이후 3.12 이후 (또는 Chrome 96 이후) |
MOBILE |
Chrome for Android Safari on iOS Samsung Internet Firefox for Android AppleWebKit Whale |
55 이후 15.4 이후 (또는 iOS / iPadOS 15.4 이후) 6.2 이후 52 이후 613.1 이후 3.12 이후 (또는 Chrome 96 이후) |
Note
기타 브라우저인 경우
Accept헤더에image/avif포함시 pagespeed 동작한다.image/webp만 포함된 경우는 동작하지 않는다.그 외 미지원 브라우저는 원본을 전송한다.