pagespeed alpha

/usr/local/m2/setting.json 다음 영역에 대해 기술한다.

{
  "functions": {
    "contents": {
      "pagespeed": {
        ...
      }
    }
  }
}

How to use

Important

  • 이 함수는 proxy 함수에 의존성을 가지기 때문에 반드시 proxy 함수를 같이 활성화 시킨다.

  • 이 함수의 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.ignoreSelectors=.banner,%23top-section

명령어

파라미터

동작

optimg

(하위설정)

optimg 실행

optscript

(하위설정)

optscript 실행

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[*] & !HEADER[Sec-Fetch-Dest: empty] & $URL[www.example.com/(.*)]",
    "replace": "www.example.com/#1/pagespeed/optimg/default",
    "accessLogUrl": "replace"
  }
]

urlRewrites 를 이용해 해당 도메인의 모든 트래픽에 대해 이미지 최적화와 레이지 로딩을 적용한다. urlRewrites 는 설정된 순서대로 동작하기에 같은 도메인에서 서비스하는 다른 리소스(이미지, css, js)에 대한 처리는 더 상위에 정의한다.

Note

pagespeed 는 웹 페이지만을 최적화하며, 처리할 수 없는 콘텐츠는 바이패스 시킨다. 따라서 Sec-Fetch-Dest 헤더 조건과 확장자 제외 필터링을 통해 적용 범위를 최적화한다.

설정 예제

www.example.com 서비스를 최적화하는 설정 예제와 주요 설정이다.

메인 트래픽 최적화

기존 서비스 URL 변경없이 www.example.com 메인 트래픽의 모든 이미지, 스크립트를 최적화한다.

{
  "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/optscript/default/optimg/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.optimg
    • matchingList 도메인 분리가 안된(=메인 도메인으로 서비스되는) 이미지를 최적화하기 위해 대상으로 지정한다.

    • 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/optscript/default/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.comstatic.cdn.comwww.example.com 으로 프록싱한다.

  • functions.network.proxy - proxy 함수를 활성화한다.

트러블슈팅

이미지 트래픽 분리로 인한 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 의 응답헤더에 원본 이미지 헤더를 추가한다.

meta

"meta" : {
  "enable" : true,
  "keyword": "pagespeed",
  "feJsLocation": null
}
enable (기본: false)

pagespeed 활성화

keyword (기본: pagespeed)

pagespeed 키워드

feJsLocation (기본: null)
  • pagespeed 프론트엔드 스크립트 다운로드를 특정 도메인에 위임하기 위한 FQDN 형식의 URL.

  • 디버깅 및 테스트 용도로 사용하며, 프로덕션 환경에서 사용을 권장하지 않는다.

apply

함수가 적용될 요청을 설정한다.

"apply": {
  "method": [ "get" ]
  "accept": [ "text/html" ]
  "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" ],
  "requestDest": ["document", "frame", "iframe"]
}
method (기본: get)

현재는 GET 메소드만 처리한다.

accept (기본: text/html)

현재는 원본의 Content-Type 헤더가 text/html 인 콘텐츠만 처리한다.

ignoredExtensions

지정된 확장자는 처리하지 않는다.

requestDest

요청헤더에 Sec-Fetch-Dest 헤더가 존재한다면 지정된 대상만 처리한다.

Note

pagespeedGET 요청의 text/html 콘텐츠에만 적용되어야 한다.

throttling

안정적인 성능보장을 위해 CPU 사용량에 따라 pagespeed 를 동적으로 비활성화한다. 비활성화된 상태의 요청은 원본서버로 바이패스 된다.

"throttling": {
  "enable": false,
  "cpu": {
    "deactive": 60
    "reactive": 40,

  }
}
enable (기본: false)

throttling 을 활성화한다.

cpu

평균 CPU 사용량에 따라 동적으로 기능을 적용한다.

Note

평균 cpu 사용량 기준은 전역으로 변경이 가능하다.

deactive (기본: 60, 범위: 0 ~ 100)

평균 CPU 사용량이 설정 값 이상이라면 부하를 낮추기 위해 pagespeed 를 적용하지 않는다.

reactive (기본: 40, 범위: 0 ~ 100)

( deactive 상태에서) 평균 CPU 사용량이 설정 값 미만이라면 다시 pagespeed 를 적용한다.

Note

reactive 값이 deactive 값을 초과하거나 유효 범위가 아니라면 deactive2/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": [
    "webp",
    "avif"
  ],
  "matchingList": [
    {
      "src": "www.example.com",
      "dest": "www.example.com",
    },
    {
      "src": "image.example.com",
      "dest": "example.cdn.com"
    }
  ],
  "lazyload": {
    "enable": true,
    "extendTarget": true,
    "ignoreSelectors": [],
    "cssRules": [
      {
        "pattern": "*",
        "rule": "img[loading='lazy'][through='m2ps'][src] {min-height:1px;}"
      }
    ]
  }
}
dims (기본: hdims)
proxy (기본: proxy)

proxy 체인함수 키워드

formats (기본: ["webp"])

출력 이미지 포맷. 브라우저 호환성 여부에 따라 설정 순서대로 선택된다.

# 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

matchingList (기본: [])

이미지 최적화 대상 도메인 리스트

Note

웹 페이지와 같은 도메인이라도 명시적으로 선언해주어야 이미지 최적화가 동작한다.

# functions.contents.pagespeed.optimg.matchingList[]
{
  "src": "www.example.com",
  "dest": "www.example.com",
}

lazyload

enable (기본: true)

이미지를 지연로딩 처리한다.

extendTarget (기본: true)
  • true 모든 <img> 를 지연로딩한다.

  • false 이미지 최적화 대상 도메인의 <img> 를 지연로딩한다.

ignoreSelectors (기본: null)

지연로딩 배제 대상 영역의 CSS Selector를 설정한다.

cssRules

이미지 지연로딩 대상 요소의 영역확보를 위한 스타일을 삽입한다.

Note

  • lazyload 동작은 loading=lazy 속성을 추가하는 것으로 로딩을 지연시킨다.

  • M2를 통해 처리되었음을 인지할 수 있도록 through=m2ps 속성이 함께 추가된다.

# 원본 예)
<img src="image.jpg">

# 지연로딩 적용시
<img src="image.jpg" loading="lazy" through="m2ps">

optscript

웹 문서의 초기 로딩속도 향상을 위해 스크립트 로딩을 최적화한다.

"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 또는 allow

ttl

캐싱 시간. allow 시 값이 없다면 상위설정인 proxy.ttl 을 사용한다.

브라우저 호환성

글로벌 96.13% 의 브라우저에서 pagespeed가 동작한다. (23년 9월 기준 호환성)

../../../../_images/pagespeed_browser_support.png

환경

브라우저

버전

DESKTOP

Chrome

Edge

Safari

Firefox

55 이후

14 이후

15.4 이후

52 이후

MOBILE

Chrome for Android

Safari on iOS

Samsung Internet

Firefox for Android

55 이후

15.4 이후

6.2 이후

52 이후

위 목록 외 미지원 브라우저는 원본을 전송한다.