Developer/CSS

css 애니메이션, position대신 transform으로 하면 좋은 이유(예제 포함)

jaddong 2024. 4. 17. 15:01
320x100

reflow와 repaint가 많을수록 성능저하를 유발한다고 알고있는데, 이론으로 말고 실제로 구현과 측정을 통해서 어떤 차이가 있는지 알아보고 싶어서 테스트를 작성해봤다.

 

1.  DevTool에서 성능(performance)탭에서 알아본다.

2. 레이아웃이 다시 되는지 확인한다. -> reflow를 확인한다.

 

relfow

생성된 DOM 노드의 레이아웃(너비, 높이 등) 변경 시 영향받는 모든 노드(자식, 부모)의 수치를 다시 계산하여 렌더 트리를 재생성하는 작업입니다.

repaint

reflow 과정이 끝난 후, 재생성된 렌더 트리를 다시 그리는 작업으로 수치와 상관없는 background-color, visibility, outline 등의 스타일 변경시에는 reflow 과정이 생략 된 repaint 작업만 수행합니다.

그냥 쉽게 해서 종이에 상자 그림이 있고 그걸 다시 그린다고 가정했을 때 아래와 같지 않을까 싶다.

step1 : 종이에 그릴 상자의 너비, 높이, 위치를 다시 계산한다. -> reflow
step2 : 상자를 빨간색으로 다시 칠한다. -> repaint

 

 

left로 박스의 위치를 이동시켰을 때

HTML 코드 

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Document</title>
		<style>
			@keyframes reposition {
				0% {
				}
				100% {
					left: 200px;
				}
			}
			body {
				margin: 0;
			}
			#box {
				width: 200px;
				height: 200px;
				background-color: black;
				position: absolute;
				left: 0;
			}
			.move {
				animation: reposition 3s ease-in forwards;
			}
		</style>
	</head>
	<body>
		<button id="button">Move!</button> // 버튼
		<div id="box"></div> // 박스
		<script>
			const box = document.getElementById("box");
			button.addEventListener("click", () => {
				box.className = "move";
			});
		</script>
	</body>
</html>

 

 

결과 영상

호출 트리를 보면 레이아웃에 11.0ms 가량 시간이 걸린 것을 확인할 수 있다.

 

 

결과 사진

이벤트 로그에서 "레이아웃"으로 검색하면 이동할 때마다 reflow가 발생함을 확인할 수 있다. 

호출트리를 보면 레이아웃에 11.0밀리초가 걸린 걸 확인할 수 있었다.
이벤트 로그에서도 계속적으로 레이아웃 감지됨을 확인 할 수 있다.

 

 

 

 

 

 

transform으로 박스의 위치를 이동시켰을 때

HTML 코드 

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Document</title>
		<style>
			body {
				margin: 0;
			}
			#box {
				width: 200px;
				height: 200px;
				background-color: black;
				position: absolute;
				left: 0;
			}
			.move {
				transform: translateX(200px);
				transition: transform 3s ease-in;
			}
		</style>
	</head>
	<body>
		<button id="button">Move!</button>
		<div id="box"></div>
		<script>
			const box = document.getElementById("box");
			button.addEventListener("click", () => {
				box.className = "move";
			});
		</script>
	</body>
</html>

 

 

 

결과 영상

 

 

결과 사진

이벤트 로그에서 "레이아웃"으로 검색하면 reflow가 발생하지 않는 걸 확인할 수 있다.

호출트리를 보면 레이아웃이 없는 걸 확인할 수 있다.

 

이벤트 로그에서도 레이아웃는 없다.

 

 

 

 

 

 

작성한 단순한 코드여서 레이아웃에 11.0ms의 차이가 있지만, 상자를 50개라면 어떨까 궁금했다. 🧐

 

 

상자 50개로 다시 테스트해 본 결과

left로 구현했을 때 레이아웃에 19ms가 걸렸다.

left : 레이아웃에 19.0ms가 걸렸다.

 

 

transform으로 구현했을 때는 역시나 레이아웃에 소모되는 시간이 없다.

transform : 레이아웃이 없다.

 

 

 

결론

테스트용이라서 엄청 큰 차이는 없어보일 수 있으나, 코드가 복잡해지고 애니메이션이 많아진다면 영향을 미칠 수 있다는 생각이 들었다.

평소 애니메이션을 구현할 때 width, height, left, top 같은 property들을 지양하는 습관을 들이는 게 좋을 것 같다.

그럼 어떤 property가 reflow를 일으키는지 궁금할 수 있는데, 링크에서 참고할 수 있다.

transform은 composite로 구분되어 있는데, 이것도 나중에 알아봐야겠다.

 

 

 

 

- 참고링크 : https://wit.nts-corp.com/2017/06/05/4571

반응형