FE 성능분석에 대한 고찰

콜라제로·2020년 7월 8일
1

프론트엔드

목록 보기
1/1

주니어 개발자들에게는 가깝지만 항상 멀게만 느껴졌던 문제는 performance이다. 항상 performance를 생각해서 웹을 빌드한다고 하지만, 막상 서비스를 만드는데에만 급급해지고, 시간여유상 performance는 시니어들이 개선한다. 많은 주니어 개발자들이 시니어 개발자로 탈바꿈하고싶어하고 그때 꼭 알아야 될 혹은 경험해야 될 부분이 성능분석이다. 우선 큰 그림에서 시작해보자!

Backend Performance?

TPS(Transition per Seconds)라는 것은 서버가 얼마나 많은 요청을 처리 할 수 있는지에 대한 지표다. 들어오는 traffic에 대해서 어떠한 서버에 어떠한 MQ처리를 하여서 풀어나가는지가 중요하다.

Frontend Performance?

그렇다면 FE에서의 성능분석은 어떨까? 사용자가 입력한것을 얼마나 빠르게 반응하는지에 대한 지표가 필요하다. LAI(Loading and Interaction)에 의해 나눠진다.
1. Loading

  • 얼마나 빨리 페이지를 볼수있는가?
  1. Interaction
  • 얼마나 매끄럽게 애니메이션이 동작하는가?
  • 스크롤이 버벅거리거나 키보드 버벅기림이 있는가?

이러한 것들에 대한 고찰 혹은 해결이 결국 성능과 직관적으로 연결되어있을것이다.

이번 글에서 loading과 interaction을 최적화 하는 방법에 대해서 얕지만 깊게 알아보도록 하겠다.

Loading

우선 웹의 동작과정을 정말 간단하게 설명하자면, 우리가 가고 싶은 url주소(서버)에서 클라이언트로 여러가지 파일을 주게된다. 이 파일들은 html,css 그리고 javascript파일들이다. 이러한 파일들이 받아지는 속도를 브라우저에서 보면 이러한 이미지일것이다.

여기서 핵심적인 파트는 waterFall 차트이다. 여기서 이 로딩시간을 줄일수있는 여러가지 방법이 있겠지만, 효과적이고 서비스에서 필요한것들에 대해서 설명해본다.

우선 이를 위해서 방법론에 대해서 알아보자.

  • 높이를 줄이고,
  • 폭을 줄이고,
  • 간격을 땡긴다

마지막으로 총체적점검이 필요하다.

  1. 높이를줄인다
    Request를 줄인다고 생각하면 된다. 보다싶이 여러가지 js파일과 css파일등이 있다. 이 파일들을 하나로 merge하면 된다. 또한 이미지파일들을 줄이는것도 굉장히 중요하다. 필요한 이미지 파일들을 하나로 모아서 보내는 방법을 CSS SPRITE라고 한다. 더 나아가서 효과적인 방법으로 몇가지가 있을 수 있다. 실수로 요청한 자원들을 제거하고, 초기로딩시 필요없는 js파일들 제거, 그리고 viewport 바깥에있는 이미지를 뒤로 미루거나(lazy loading) 삭제 할 수 있다. 브라우저는 호스트당 동시에 연결 하는 개수가 정해져있다.

    그렇기 때문에, 넓게 보자면, 이렇게 높이를(리퀘스트의 수)를 줄이는것이 성능개선에 엄청난 영향을 줄 수 있다. 왜냐하면 요청수가 많아질수록 대기하기 때문에 더 오래 걸릴것이다.
  2. 폭을 줄인다
    폭을 줄일때에는, 리퀘스트의 정보를 알아봐야 한다. 그러기 위해서, network탭에서 폭이 넓은 리퀘스트에 대해서 좀더 알아보도록 해보자.

    Initial Connection은 http 프로토콜 마다 다르다. 기존의 http1은 컨넥션수를 하나밖에 가지지 못하지만 http2는 2개를 가질 수 있다. 두번째로 TTFB는 Time to First Byte이다. 리퀘스트를 첫번째 받은 시간이라고 생각하면 된다. 이말은, 서버에서 이만큼의 시간이 (예제에서는 33.00ms)걸려서 도착했다고 생각하면된다. 그럼으로 이거는 서버에서 튜닝이 필요하다는 것을 뜻한다. Content Download는 두가지로 추론가능한데: 네트워크 속도가 낮거나 컨텐츠의 크기가 큰 경우이다. 보통 컨텐츠가 큰 경우에는, minify나 gzip을 이용해서 압축을 시켜주는 작업이 필요하다. 이럴경우 최소 30%에서 최대 50%까지 크기가 줄어든다. (특히 이미지! 줄여주는게 중요하다.)
  3. 간격을 땡긴다
    여기서 일단 이 브라우저로딩과정에 대해서 간단한 그림을 봐보자.

    우선 서버로부터 HTML문자열을 STREAM 으로 받게된다. 그러고 태그에 포함된 자원을 병렬로 다운로드 한다. 어떻게 보면 속도가 향상된다 생각할 수 있지만, 이작업을 할동안 페이지에는 아무것도 로드 되지않기때문에, 보통 여기다가 js를 포함시키지 않는다. (이유는 js파일들이 보통 크기때문에 또한 나중에 dom을 바꿀수있는 문법이 있을수있어서) 고로 head태그에는 css와 필수 js만 넣어야 되고, js는 바디태그 마지막에 넣는게 통상적으로 가장 효율적인 방법이다. defer(돔제어 관련있는 스크립트)혹은 async(의존성이 없는 스크립트)를 이용해서 javascript를 다운로드 받을 수 있다. preload를 통해서 폰트나 이미지를 같이 받는 방법이 있을 수 있다.

이제 이정도 까지 하면, 로딩관련된 왠만한 이슈는 해결할 수 있다. 이렇게 3 가지를 완료했다면, 튜닝에 대한 왠만한 이슈가 해소 되었다고 할 수 있다. 이 3가지를 반복적으로 하다보면 로딩시간이 훨씬 주는것을 체감 할 수 있을것이다. 하지만 이렇게 속도만 올리다보면 UX(사용자경험)을 무시하는 경우가 나올 수 있다. 어떻게 사용자경험을 조금더 좋게하면서 속도를 높일 수 있을까?

UX의 향상?

유저들이 서비스를 접할때, 정확히 어느 시점에서 ux가 좋다 나쁘다를 판단할 수 있을까를 생각해본다면, First Paint시점일 것이다. FP는 head태그 종료 후에 이뤄지는 액션이다. 그렇다면, 우리는 이 FP가 이뤄지는 시점에서 선택을 해야된다: 스트럭쳐를 먼저 그릴지? 아니면 꽤 의미있는 엘리먼트들을 먼저 보여줄지. 그 다음은 First Meaningful Paint라는 개념이다. FMP같은 경우에 Hero 엘리먼트가 보이는 시기라고 생각 하면된다. 다른 말로하면, 가장의미있고 사용자에게 전달해주고자 하는 영역을 뜻한다. 예를 들면 유투브에서는 보고 싶었던 비디오를 보여주는게 히어로 엘리먼트 일 것이다. 이러한 것들이 결국 로딩속도를 줄이고 사용자로 하여금, 훨씬더 좋은 ux를 경험하고 있다고 느끼게 해줄 지표들이 될것이다.

Interaction

Interaction을 높일려면 어떤식으로 해야될까? Javascript가 동적으로 바뀌기 때문에, DOM을 건들면 기본적으로 Main Thread에 의해 rendering pipeline이 동작한다. 그러고 이 Main Thread를 free하는게 가장 중요한 핵심 포인트이다.
Rendering Pipeline에 대해서 간단하게 이해해보자.

보통 JS로 돔을 변경한다. 그 후에, 돔의 스타일을 계산해서 (Style Recalculate) 돔의 배치와 크기를 계산한다.(Layout) 이부분에서 돔의 스타일을 계산하는 부분이 굉장히 비싼 부분이라고 할 수 있는게, 우리가 browser의 html을 파보면 나오는 여러가지 css 수치들이 이때 계산되기 때문에, 무거운 작업이라 할 수 있다. 사실 여기서 훨씬더 깊게 들어가서 어떤 styling이 어떻게 무거운지도 생각해볼 수 있다. (아주 짧게) 예로 top과 transform에 대한 고찰을 해보자.

위 그림에서 보다싶이, top은 ['style, layout', paint, composite] 모든것을 건드린다. 한마디로 rendering pipeline의 모든 과정을 다시 해야되는데 반해서,

transform은 순전히 composite스텝만 건들게 된다. 이렇기 때문에 어떠한 css를 쓸지도 인터렉션 개선에 큰 도움을 줄 수 있다.
하지만, 이럼에도 불구하고, main thread에서 해줄 수 있는 양은 한계가 있고, 그렇기 때문에 우리는 GPU에서 도움을 받을 수 있다. (CPU가 아닌 GPU에서의 도움!)
그렇다면 GPU와 composite은 무엇일까? composite이란 웹페이지는 하나의 거대한 레이어라는 것이다. GPU는 각각의 레이어를 합치는 작업을 한다. 그렇다면 여기서 레이어라는 것은 한마디로 층이 되겠다. 예를들어 웹페이지를 아파트라고 했을때 우리가 3층과 4층사이에 3.5층을 넣고싶다면, 레이어를 생성해 주면 될것이다. 그럼 이 레이어를 넣는것은 그렇게 비싼 비용이 들지 않는다. 이유는 이미 3.5층 외에 모든 층들이 만들어져있고, 그것을 중간에 넣고 위에서 바라보는 모습을 고객들은 보기 때문이다. 그래서 GPU의 도움을 받기위해 레이어를 만든다. 하지만, GPU도 side effect가 존재한다. 레이어를 구성하는 작업은 CPU(Main Thread)가 진행 하고 레이어에 원래 비트맵정보를 복사하기 때문에, 메모리가 2배로 필요하다. 고로 꼭 필요한 부분만 만드는것이 중요하다.

Conclusion

성능 분석은 항상 멀게만 느껴지지만, 꽤 기본적인 flow를 가지고 있다. 큰 접근법을 가지고 방법론을 얘기하다보면 결국 많은 방법들이 쌓일것이고 이 경험을 토대로 인사이트가 생긴 성장하는 개발자가 되지 않을까 한다.

profile
frnontend

0개의 댓글