본문 바로가기

ETC

High performance web user interfaces 요약

Google I/O 2016에서 웹쪽 주제로는 첫 번째 세션이었던 High performance web user interfaces 를 요악합니다.


- Progressive Web Apps

    - 여러 기능을 사용하기 위해서는 HTTPS가 필요

        - push messaging, offline 혹은 좋지 않은 접속 상태 (by service worker)

- 사용자는 native app처럼 생긴 앱은 native app 처럼 동작하기를 기대한다.

    - 동작(behaves)은 두 가지로 나뉜다. - performance, interaction

- Performance

    - RAIL

        - 퍼포먼스를 고려할 때 사용자를 중심에 두고 생각하는 모델

        - Response (0.1 sec), Animation (16ms), Idle (50ms), Load (1 sec)

        - 현실에서 중요도는 L > A > R > I 로 생각된다.

        - Add to homescreen에서 실행되거나 PWA에서는 중요도가 R = A > I > L 라고 생각.

            - add to homescreen에서 실행되는 경우에는 service worker가 기본으로 설정되어 있어야 하기 때문

            - SW에서 오프라인이거나 연결상태가 좋지 않을 경우 로딩을 컨트롤 할 수 있다.

            - 매일 실행하는 앱에서는 스크롤이 잘 되거나, 반응성이 좋거나 하는 것이 더 중요하다.

            - App이 아니라 site의 경우에도 user interface의 반응성이 좋은 것은 중요


- Three components의 성능을 높이는 사례를 볼 것임

    - sidenav, dismissable card, expanding and collapsing view

- sidenav

    - pointer-events: none;

        - 미리 준비되어 있어야 하고 언제든 동작 가능해야 하는데 사용자가 클릭하자마자 동작해야 하므로 렌더트리 내에 포함되어 있어야 한다. 그렇지 않다면 렌더트리에 포함될 때 layout, styles, painting 이 트리거 된 후에야 움직일 수 있다. 따라서 hidden 되어 있지 않고 렌더트리에 포함되어 있으려면 모든 엘리먼트의 최상단에 있어야 하는데 그렇게 되면 다른 엘리먼트를 클릭할 수 없다. 따라서 pointer-events를 none으로 설정하면 클릭이 아래에 깔린 엘리먼트로 넘어가게 된다. 화면에 노출될 때는 auto로 변경

    - sidenav가 자체의 composite layer를 갖도록 한다.

        - composite layer: 페이지의 특정한 부분을 페이지의 다른 부분과 분리하는 것

        - will-change: transform; 사용 (예전에는 translateZ(0) 사용)

        - 필요한 곳에만 쓸 것. 메모리 과다 사용 문제, compositing에 걸리는 시간 최소화.

    - 터치로 sidenav를 움직일 경우 document에 이벤트 처리를 위임한다.

        - requestAnimationFrame 사용

        - touchmove 이벤트 핸들러에서 event.preventDefault()를 사용한다.

            - 기본적으로 크롬에서는 touchmove 이벤트를 발생시키는 회수를 줄인다. 손가락으로 가리키는 모든 이벤트를 받고자 한다면 preventDefault()를 사용해야 함.

    - Supercharged 동영상 http://bit.ly/side-nav

- swipeable cards

    - this.onStart = this.onStart.bind(this);

        - prototype을 instance로 복사하면서 현재 instance와 바인딩한다.

        - 호출하면 항상 현재 instance를 참조하고 addEventLister에서 this.onStart으로 등록/제거가 가능

    - onStart에서 style.willChange를 지정해서 별도 레이어로 분리 (필요할 때만 분리한다는 점이 중요)

    - 손쉬운 easing 패턴

        - value += (target - value) / strength

    - Supercharged 동영상 http://bit.ly/swipeable-cards

- Expand and Collapse

    - 이건 좀 어려운데 width, height, top, left를 변경하면 매 프레임마다 layout 트리거 되고 paint도 트리거됨

        - layout은 dom size에 비례하여 시간이 증가

    - transform을 쓰면 layout만 트리거 할 수 있다. (그래서 발표자가 좋아함) (참고: 크롬에서만..)

    - FLIP 방법을 적용

        - First, Last, Invert, Play

        - First: 초기 상태의 position을 얻는다. (getBoundingClientRect)

        - Last: 애니메이션을 마지막 프레임으로 옮겨간다. 그리고 마지막 상태의 position을 얻는다. (getBoundingClientRect)

        - Last로 갈 때 layout, style이 강제로 트리거 된다. Layout은 나쁜데 이렇게 해도 괜찮은가?

            - 단 한 번만 layout함. RAIL의 도움을 얻을 수 있다. 

        - Invert: Last에서 First로 되돌리는 값을 얻어 transform 시킨다. 그리고 transform에 transition을 설정.

        - Play: transform = 'none' 으로 설정하면 카드가 늘어나게 된다.

        - FLIP 주의점

            - scales은 자식 엘리먼트를 변경시킨다. 형제 엘리먼트를 고려해야 할지도

            - first 에서 last로 가는 과정은 layout과 style을 발생시키므로 조심해야 함

        - 성능에 덜 민감하고 Responsive Web Design에도 유용

- 렌더링 퍼포먼스에 대해 알고 싶다면

    - http://bit.ly/render-perf

- 데모에 나온 UI를 더 자세히 살펴보고 싶다면

    - http://bit.ly/supercharged-ui



이 동영상에는 코드에 대한 설명이 많아 모든 내용을 요약하지는 않았습니다. 보다 상세한 내용이 궁금한 분은 동영상을 확인하기 바랍니다.

반응형