폴리필의 개념
브라우저마다 지원하는 기능이 다릅니다. 특히 구형 브라우저일수록 최신 기능을 지원하지 않습니다.
설상가상으로 한국에서는 인터넷 익스플로러라는 구형 브라우저를 고려해야 합니다.
세계점유율이 1%대에 마이크로소프트에서도 버린 브라우저이지만 아직도 국내에선 ACTIVE X를 사용하는 관공서 사이트들 때문에 점유율이 10%라는 무시할 수 없는 수치이기 때문입니다.
조금이라도 웹개발에 몸을 담근 분이라면 이 IE가 얼마나 말썽을 일으키고 안되는 것들이 많은지 공감하실 겁니다.
자바스크립트를 예로 들면 인피니티 스크롤과 Lazy Load등에 쓰이는 Intersection Observer부터 시작해서 유용한 ES6 문법까지 IE는 싹 다 먹통으로 만들어버립니다.
그럴 때 사용하는 게 폴리필(Polyfill)입니다. 이 파일은 IE에서 통하는 기존에 있는 문법으로 어떻게든 새로운 기능과 비슷하게 작동하도록 해줍니다.
물론 그 과정에서 복잡한 함수를 쓰고 이리 꼬고 저리 꼬다보니 용량이 크지만 그래도 작동하게 해준다는 데에 의의가 있습니다.
크로스브라우징의 핵심이지요.
폴리필 사용법
사용할 폴리필 정하기
어떤 폴리필을 사용할지 구분해내는 것이 첫번째 단계입니다.
이럴 때 유용한 사이트는 Can I use라는 사이트입니다. 어떤 문법이나 명령어가 어떤 브라우저에서 미작동 하는지를 알아볼 수 있게 해주는 사이트입니다.
무료인데다, 업데이트도 꾸준히 해줘서 매우 유용합니다.
폴리필 파일 다운받거나 코드 받아오기.
어떤 폴리필을 사용할지 정했다면 다음 단계로 나아가야합니다.
예를 들어 Intersection Observer의 폴리필을 구하고 싶다면 Intersection Observer polyfill 같은 키워드를 구글에서 검색하신 후에 Github라던가 모질라재단의 홈페이지에 공개된 폴리필 파일을 다운받으면 됩니다.
이런 과정이 귀찮으시다면, 폴리필io라는 사이트에서 직접 구성해서 다운받으시면 됩니다.
폴리필이 항상 복잡하고 파일 형태로 써야하는 건 아닙니다. 대표적으로 forEach문은 IE에서 작동하지 않는데, 간단한 마크업을 추가해주는 폴리필이 있습니다.
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = function (callback, thisArg) {
thisArg = thisArg || window;
for (var i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this);
}
};
}
폴리필 사용하기
폴리필은 본체보다 먼저 작동해야 합니다.
forEach문을 예로 들어볼까요?
if (window.NodeList && !NodeList.prototype.forEach) {//브라우저에 forEach문이 정의되지 않았다면
NodeList.prototype.forEach = function (callback, thisArg) {
thisArg = thisArg || window;
for (var i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this);
}
};
} // 폴리필 삽입
const a = document.querySelectorAll('.help');
a.forEach(function(ele){
ele.classList.add('hello')
}) //폴리필 다음으로 코드 넣기
위에 코드를 보면 이해하시겠지만 forEach문 위에 폴리필이 있어야 에러 없이 forEach가 작동합니다.
파일로 넣는다면 이렇게 하시면 됩니다.
<script src="경로/forEachpolyfill.js"></script>
<script>
const a = document.querySelectorAll('.help');
a.forEach(function(ele){
ele.classList.add('hello')
})
</script>
다만 여기서 한 가지 추가할 게 있습니다.
어차피 특정 구형 브라우저에서만 폴리필이 필요한데, 굳이 매번 불러올 필요가 있을까요?
그래서 위의 예시문 코드에서 썼듯이 if 문을 이용해 브라우저에 정의되지 않았을때에만 불러오게 하시면 됩니다.
[참고*자바스크립트의 화살표 함수는 폴리필이 되지 않습니다. 아예 새로운 형태의 구문이기 때문입니다.*]
이건 제가 Intersection Observer의 폴리필을 사용할 때 썼던 마크업입니다.
if (!('IntersectionObserver' in window) ||
!('IntersectionObserverEntry' in window) ||
!('intersectionRatio' in window.IntersectionObserverEntry.prototype)) {//만약 정의되지 않았다면
document.write('<script src="./images/IntersectionObserver.js"><\/script>');//폴리필 파일을 발동한다
}
document.write를 피하기 위해서 script를 만들고 appendChild를 쓰는게 성능면에서 좋겠지만 괴상한 IE답게 그럴 땐 폴리필이 작동을 하지 않을때가 있습니다.
또한 비동기 코드(async)를 쓸때도 주의해야합니다. 폴리필이 먼저 발동해야 하기 때문입니다.
브라우저별로 작동하게 하는 조건문
제가 사용법에서 언급한대로 특정 기능이 없을 때 폴리필을 작동시키면 편합니다.
하지만 경우에 따라선 브라우저에 따라서 다른 결과가 나오도록 조건문이 필요할 때가 있습니다.
대표적으로 IE로 접속했을시에 '곧 지원 종료되는 구형 브라우저이니 크롬이나 파이어폭스, 웨일, 엣지 등으로 갈아타세요.' 라고 표시하고 싶을 때가 해당됩니다.
아래의 조건문이 100% 작동하는 것은 아니지만 대략적으로 잡아내줄 겁니다.
// Opera 8.0+
var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
// Firefox 1.0+
var isFirefox = typeof InstallTrigger !== 'undefined';
// Safari 3.0+ "[object HTMLElementConstructor]"
var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification));
// Internet Explorer 6-11
var isIE = /*@cc_on!@*/false || !!document.documentMode;
// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;
// Chrome 1 - 79
var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
// Edge (based on chromium) detection
var isEdgeChromium = isChrome && (navigator.userAgent.indexOf("Edg") != -1);
// Blink engine detection
var isBlink = (isChrome || isOpera) && !!window.CSS;
CSS의 경우엔?
CSS의 경우엔 브라우저마다 표준성이 덜합니다. 똑같은 코드를 써도 미묘하게 결과물이 다릅니다.
크롬과 파이어폭스가 다른 경우가 비일비재하고 말썽쟁이 IE는 말할 것도 없습니다.
그래서 브라우저별로 다르게 해야할 때가 잦습니다.
@supports (-moz-appearance:none) {
h1 { color:red; }
}/*파이어폭스에서만 작동*/
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
h1 { color:red; }
}/*IE에서만 작동*/
그럴 땐 위처럼 쓰시면 됩니다. 사파리의 경우엔 버전이 다양해서 범용적인 조건문을 찾기 힘듭니다.
버전별로 어떤걸 써야할지 참고하시려면 스택오버플로우의 이 글을 읽어보시면 될 겁니다.
'그외 > 유용한 정보' 카테고리의 다른 글
웹페이지의 로딩 속도 최적화를 해 줄 크리티컬 CSS 개념을 알아봅시다. (4) | 2020.10.06 |
---|---|
PageSpeed Insights의 렌더링 차단 리소스를 제거해보자. (15) | 2020.10.02 |
무료 게임을 뿌리는 에픽게임즈에 가입하는 방법 (0) | 2020.09.28 |
티스토리 블로그에 사용할 레이지로드 주입기 (17) | 2020.09.23 |
티스토리에서 레이지 로드(Lazy Load)를 사용하는 방법 (2) | 2013.01.11 |