Skip to content

가속합성으로 인한 화면 깜빡임 해결

하이브리드 앱의 웹뷰 컨텐츠를 개발하던 중 발생한 이슈의 해결과정을 설명합니다.

배경

이 프로젝트에서는 페이지 전환을 앱처럼 보이도록 하기 위해 화면을 겹친 상태로 유지하고 있고,

PAGE1
PAGE2
PAGE3

페이지 전환 트랜지션을 위해 translate3d를 사용합니다.

각 화면에서의 탭 변경 트랜지션을 위해서도 translate3d를 사용합니다.

또한 여러 페이지에서 이미지 슬라이드를 표현하기 위해 vue-awesome-swiper를 사용하고 있는데,

vue-awesome-swiper에서도 스와이프 전환 트랜지션을 위해 translate3d를 사용합니다.

현상

다음과 같이 탭을 변경하면 트랜지션 완료 후 화면 깜빡임이 간헐적으로 발생합니다.

원인

처음에는 탭이 변경된 이후에 이미지 슬라이더 이외의 영역이 다시 그려지는 것이 아닌지 의심했습니다.

하지만 트랜지션이 시작되기 전 컴포넌트의 렌더링이 완료되고,

이후에도 렌더링을 유발하는 변경은 없었습니다.

결정적으로 아래 GIF에서 확인할 수 있듯이 일부 영역만 가려지는 듯한 현상을 확인할 수 있었습니다.

배경에서 언급했듯이 여러 페이지가 겹쳐져 있는 상태에서

가려진 영역의 요소가 잠깐 최상단으로 끌어올려져 보여지는 것이 아닐까 했습니다.


각 페이지에서는 vue-awesome-swiper로 이미지 슬라이드를 표현하고 있는데,

다른 페이지에 가려진 이후에도 슬라이드를 중지하지 않고 있었습니다.


스와이퍼를 삭제해 보니 현상이 사라지는 것을 확인할 수 있었습니다.

트랜지션 직후에만 어떤 요소가 화면을 잠시 가린다는 점,

이미지 슬라이더 컴포넌트를 삭제했을 때 해결되는 점을 근거로

vue-awesome-swiper와 탭 전환 트랜지션를 원인으로 추측했습니다.

비슷한 현상을 찾아보던 중 하드웨어 가속과 가속 합성에 대한 내용을 찾을 수 있었습니다.

가속 합성에 대한 설명은 글 하단의 링크로 대체하겠습니다.


탭의 전환 애니메이션은 vueTransition 컴포넌트를 통해 이루어지므로

translate3d 속성은 전환이 시작될 때 추가되었다가 완료된 후 삭제됩니다.

가속 합성과 관련지어 생각해보면,

탭 영역이 Graphics Layer에서 Render Layer로 변경되며

화면의 합성이 다시 진행되는 것이 원인이지 않을까 추측해 볼 수 있습니다.

해결

선행되었어야 할 해결책은 화면이 전면에 노출되지 않는 경우에는 슬라이드를 중지하는 것입니다.

하지만 프로젝트 구조와 업무 프로세스의 문제로

모든 페이지에서 슬라이드를 중지하는 것은 빠른 기간 안에 진행하기 힘든 일이었습니다.

따라서 빠른 해결을 위해 아래의 방식을 채택했습니다.


원인 파악을 위해 아래의 css를 추가했을 때 현상이 사라지는 것을 확인할 수 있었습니다.

css
.swiper-slide {
  backface-visibility: hidden;
  transform: translate3d(0, 0, 0);
}
.swiper-wrapper {
  transform-style: preserve-3d;
}

하지만 글로벌 css를 변경하게 되면, 스와이퍼가 존재하는 모든 화면에 적용됩니다.

성능과 Side Effect를 고려해서 다른 방향으로 해결해야 합니다.

탭의 translate가 나타났다가 사라지는 영역 내부를 한번 더 감싸서

하위 요소들이 Container의 합성 영역 안에서 합성되도록 했습니다.

vue
<template>
  <div class="tab-contents">
    <div style="transform: translateZ(0)">
      <!--...-->
    </div>
  </div>
</template>

Reference List

GPU Accelerated Compositing in Chrome

Front-End Performance Optimization with Accelerated Compositing Part 1

하드웨어 가속에 대한 이해와 적용

[CSS] 브라우저의 Layer Model과 하드웨어 가속을 이용한 렌더링 최적화에 대해 알아보자!

(번역) CSS GPU 애니메이션 제대로 하기

rotate3d와 z-index 충돌 해결

Swiper-API : maxBackfaceHiddenSlides

will-change - CSS: Cascading Style Sheets | MDN

backface-visibility - CSS: Cascading Style Sheets | MDN

transform-style - CSS: Cascading Style Sheets | MDN

Last updated: