will-change속성으로 하드웨어 가속 적용하기

will-change 속성으로 하드웨어 가속을 적용해보자

하드웨어 가속

하드웨어가속은 gpu를 이용하여 cpu의 작업량을 줄이고 렌더링을 최적화하는 것을 말한다.

하드웨어 가속을 지시하게 되면 대상이 되는 요소만 존재하는 별도의 레이어를 만들어 작업하고 이 레이어를 페이지에 합친다.

즉 하드웨어 가속을 이용하면 보다 빠르게 렌더링 할 수 있다.

하지만 이 방법은 3D transforms에만 적용되고 2D transforms에는 적용되지 않는다.

2d 애니메이션의 경우 자동으로 하드웨어 가속이 활성화되지 않는다.

때문에 아래와 같이 강제로 3d로 변형시켜서 하드웨어 가속을 지시하곤 했다.

1
2
3
.accelerate {
-webkit-transform: translate3d(0, 0, 0);
}

현재는 2d 애니메이션의 will-change 속성을 이용하여 3d로 변형하지 않고도 브라우저에게 하드웨어 가속을 지시할 수 있다.

will-change

will-change 속성을 사용하여 브라우저에게 미리 변경사항을 알릴 수 있다.

이를 통해 애니메이션이 실제로 시작되기 전에 애니메이션을 준비하는데에 비용이 많이 드는 작업을 수행할 수 있다.

즉 3d로 변환하지 않고 브라우저에 변경사항을 전달하여 메모리를 최적화하고 할당하도록 할 수 있다.

사용방법

will-change속성은 이미 애니메이션이 적용되는 요소에 적용하는 것은 의미가 없다.

즉 브라우저가 사전에 최적화를 수행할 수 있도록 빠른 미래에 예상되는 변경 사항을 브라우저에 미리 알려야 한다.

최적화가 되지 않는 예시는 다음과 같다.

1
2
3
4
5
6
.will-change:active {
will-change: transform;
transition: transform 0.3s;
transform: scale(1.5);
}
/* 변경이 발생되는 시점에 속성을 지정한 경우 동작하지 않는다. */

요소가 active상태가 되기 위해선 먼저 요소를 hover 해야한다.
이를 이용하여 will-change를 적용한 예시는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
.will-change {
transition: transform 0.3s;
}

.will-change:hover {
will-change: transform;
}

.will-change:active {
transform: scale(1.5);
}

will-change 속성을 사용하게 되면 해당 변경사항이 항상 곧 일어난다고 브라우저에게 전달하게 된다.
이는 브라우저의 메모리 소비를 증가하게 만든다.
때문에 will-change는 적절한 시기에 추가하고 제거되어야 한다.

아래의 코드는 hover시의 애니메이션에 will-change를 적용한 코드이다.
다음과 같이 작성할 경우 브라우저의 메모리 소비는 증가하게 된다.
항상 will-change 속성이 적용되기 때문에 메모리 소비가 증가한다.

1
2
3
4
5
6
7
8
.will-change {
will-change: transform;
transition: transform 0.3s;
}

.will-change:hover {
transform: scale(1.5);
}

이는 다음과 같이 수정할 수 있다.
대상의 부모 요소가 hover되었을 때 will-change를 추가하여 브라우저에게 미리 최적화를 지시할 수 있다.

1
2
3
4
5
6
7
8
9
10
.will-change {
transition: opacity 0.3s linear;
}
.will-change-parent:hover .will-change {
will-change: opacity;
}

.will-change:hover {
opacity: 0.5;
}

허나 슬라이드와 같이 항상 변경되는 컴포넌트의 경우 다음과 같이 항상 변경에 대비하도록 작성하는게 더 낫다.

즉 사용자가 동일한 액션을 반복해서 수행할 것으로 예상되거나 계속 사용되는 인터액션의 경우 계속 유지하는 것이 더 낫다.

1
2
3
.slide {
will-change: transform;
}

주의사항

위에서 언급한 것 처럼 will-change속성은 브라우저가 최적화를 위한 작업을 유지하도록 하기 때문에
오래 유지되지 않도록 작업이 끝난 이후에 속성을 제거해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
var el = document.getElementById("element");
el.addEventListener("mouseenter", hintBrowser);

el.addEventListener("animationEnd", removeHint);

function hintBrowser(event) {
event.target.style.willChange = "transform, opacity";
}

function removeHint(event) {
event.target.style.willChange = "";
}

ref

하드웨어 가속에 대한 이해와 적용
An Introduction to the CSS will-change Property
CSS will-change 프로퍼티에 관해 알아둬야 할 것