모바일 메뉴에 기름칠 하기 ! (feat. animation 최적화)

운동하는 개발자·2022년 7월 20일
0

html/css

목록 보기
3/12
post-custom-banner

Overview

'아니.. 왜 내가 만든 메뉴는 이렇게 끊기는거지?'에서 시작되었다.
animation, transform 을 최적화를 해봐야겠군..

브라우저의 Timeline

애니메이션을 최적화 하기 위해선 우선적으로 브라우저가 어떻게 랜더링이 되는지 선행학습이 되어야 된다.

브라우저의 Timeline은 아래의 이미지와 같다.

1. Style

브라우저는 요소에 적용할 스타일을 계산합니다.(CSS를 모두 읽어온다고 생각하면 좋다)

2.Layout

가져온 CSS에서 layout에 영향을 주는 것들은 우선적으로 설정합니다.

layout 대표 속성 값
margin, padding, width, height

3.Paint

CSS에서 layout 즉, 뼈대를 꾸며주는 일을 합니다. 그리고 레이어들을 GPU로 업로드 한다:)

Paint 대표 속성 값
box-shadow, border-radius, color, background-color 등

4. Composite

레이어를 합성하여 화면에 그려내는 일을 한다.(프레임을 그린다.)

Composite 대표 속성
transform, tranlate, rotate, opacity 등

아래의 이미지는 위의 4단계를 요약한 이미지이다.

그럼 애니메이션은 동작하는 원리는?

CSS 기반 애니메이션은 이란적으로 브라우저의 메인 쓰레드가 아닌, 컴포지터 쓰레드에서 처리된다.

메인 쓰레드 : styling, layout, painting, javascript 를 처리한다.

"컴포지터 쓰레드메인 쓰레드에서 정보를 받아와 독립적으로 프레임을 그린다."

컴포지터 쓰레드에서 프레임을 그린다 = drawing

Javascript의 경우 메인 쓰레드에서 우선순위가 밀리게되면 느리게 표현되지만, CSS 애니메이션의 경우에는 독립적인 컴포지터 쓰레드를 이용하기 때문에 큰 문제가 없다.

자, 그럼 실전으로 알아보자 !

display:none/block 으로 메뉴 표현

이렇게 한번에 팍 튀어나오는 것을 좋아하는 사람도 있지만, 왠지 모바일에서는 스무스가 대세인거 같다.

코드를 보면,

.global__menuList{
    display: none;
    position: fixed;
    top: 0;
    bottom: 0;
    width: 60%;
    background: #fff;
    padding: 40px 0;
    box-sizing: border-box;
    border-left: 1px solid #e1e1e1;
}
&.open{
    .global__menuList{
        display: block;
    }
}

이와 같이 단순히 display:none/block; 으로 처리를 하였다. 이 결과는

동영상 업로드가 안되 gif 파일로 하니.. 이해해주길 바란다..

이제는 스무스하게! left/right를 이용

첫 번째로 스무스하게 움직이기 위해선 transition 속성을 이용하여 right값을 제어를 해준다.

.global__menuList{
    display: block;
    position: fixed;
    top: 0;
    right: -60%;
    transition: right 300ms linear;
    width: 60%;
    background: #fff;
    padding: 40px 0;
    box-sizing: border-box;
    border-left: 1px solid #e1e1e1;
}
&.open{
    .global__menuList{
        display: block;
        right: 0;
        transition: right 300ms linear;
    }
}

적용한 영상은 아래와 같다.


녹색 영역은 애니메이션을 랜더링하는데 소요된 시간을 나타낸다.
FPS가 불규칙과 성능이 느린것을 알 수 있다.

transform을 이용 애니메이션 효과

박스를 옮기는 방법은 여러가지가 있지만, 앞서 말한 것처럼 compostie에서 부터 그려지는 속성인 transform을 이용한 것이다.

코드는 아래와 같다.

.global__menuList{
    display: block;
    position: fixed;
    top: 0;
    transform: translateX(15%);
    transition: transform 300ms linear;
    width: 60%;
    background: #fff;
    padding: 40px 0;
    box-sizing: border-box;
    border-left: 1px solid #e1e1e1;
}
&.open{
    .global__menuList{
        transform: translateX(-85%);
        transition: transform 300ms linear;
    }
}

결과는?

역시나.. gif... 동영상을 볼때는 차이가 나는데 말이다.. 그래서.. !

오.. 몬가 다르다... 왠지 더 규칙적으로 보여진다 !

그래서 두개를 비교를 해보았다. 두번째 아래의 동영상에서 두번째 노출되는 것을 보고 있으면, 좌(right) / 우(trasnform) 우측이 아주 미세하게 부드러운 것을 느낄 수 있다.
(아..동영상으로는 확 티가 나는데 말이다.... 아쉽..)

부가 설명

애니메이션 최적화를 찾다보면 반드시 나오는 단어가 reflow, will-change 이 두개 일 것이다.

쉽게 설명해

reflow : TimeLine의 Layout부터 다시 그려지는 것 !
repaint : TimeLine의 paint부터 다시 그려지는 것 !
will-change : 변화가 예상되는 요소를 브라우저에게 미리 알리는 것.

will-change에 대하여

will-change 속성은 4가지다.

will-change: auto;
will-change: scroll-position;
will-change: contents;
will-change: transform;
will-change: top, left;

  1. auto
    기본값으로 브라우저는 별다른 최적화를 실시하지 않습니다.
  2. scroll-position
    스크롤 할 때 엘리먼트의 위치가 변경될 것을 알려줍니다. 이 값을 설정하면 브라우저는 스크롤 가능한 엘리먼트를 미리 최적화 하여 랜더링 합니다. 한 번에 많은 양을 스크롤하거나 빠른 스크롤이 필요한 경우에 사용합니다.
  3. contents
    엘리먼트의 컨텐츠가 변경될 것을 알려줍니다. 브라우저는 보통 엘리먼트의 랜더링 결과를 캐싱합니다. 대부분의 엘리먼트가 변경되지 않고 변경되어도 위치가 바뀌는 정도의 미미한 변경만 발생하기 때문입니다. 하지만 엘리먼트가 계속해서 변경되는 경우 브라우저 캐시는 무의미하게 됩니다. 이 속성을 사용하게 되면 캐시를 하지 않고 변경될 때마다 처음부터 랜더링하게 됩니다.
  4. 변경하고 싶은 속성을 사용할 수 있습니다. 쉼표(,)를 이용하여 두 개 이상의 속성을 사용할 수 있습니다. 크롬에서는 현재 6가지 속성(opacity, transform, top, left, right, bottom)만 적용됩니다.

will-change 참고

will-change 사용 예시는 다음과 같다.

*,
*:before,
*:after {
  will-change: width, margin, height, top, left, bottom, right, transform, opacity;
}

위의 코드처럼 속성을 모두 넣는다고 최적화에 도움이 된다고 확신을 할 수가 없기 때문에 이 방법을 추천하진 않는다.

결론

좀 더 자극적인 페이지를 위해선 애니메이션 효과가 들어간다. JavaScript를 이용하여 더 세밀하게 조작을 할 수도 있지만, CSS를 이용하여 적절한 애니메이션을 사용하면 브라우저 최적화에 큰 도움이 될거 같다.

참고 URL

  1. https://medium.com/outsystems-experts/how-to-achieve-60-fps-animations-with-css3-db7b98610108 (
    호세 로사리오 블로그)
  2. https://wit.nts-corp.com/2017/06/05/4571 (WIT 블로그)
  3. https://brunch.co.kr/@99-life/2 (브런치)
profile
강인한 체력이 최고의 무기다.
post-custom-banner

0개의 댓글