September 11th 2019
Contents
현재 회사에서 페이지 일부를 개편하는 작업을 맡고 있는데, 필요한 기능을 구현하며 플랫폼별 성능 이슈를 효율적으로 해결해야 하는 과제가 생겼습니다. 그래서 이 기회에 웹 성능 관련 학습한 내용을 정리하고자 합니다. (아자! 빨라져라!!)
어떻게 해야 우리가 만든 웹 앱의 성능을 좋게 또 오래 지속될 수 있도록 할 수 있을까요? 프로그래밍에서 모든것이 그렇든 performance 또한 trade-off가 존재합니다. 이 포스팅을 통해 성능과 이에 대한 trade-off는 어떠한 것이 있는지 알아보도록 하겠습니다.
또한, 인터넷 상에 언급된 성능에 관한 방식을 사용할때 주의를 기울여야합니다. 오래된 방식이거나 잘못된 방법을 사용하면 도움이 되지 않을수 있고 오히려 성능에 악영향을 줄 수도 있기 때문입니다.
성능과 관련된 구체적이 내용을 살펴보기전 왜 이것이 중요한지에 대해 먼저 알아보아요. 왜 성능이 중요할까요? 이와 관련해서 Jacob Nielson의 웹 사용성과 관련된 연구 중 일부를 살펴보면 아래와 같습니다.
0.1 second is about the limit for having the user feel that the system is reacting instantaneously, meaning that that no special feedback is necessary except to display the result.
위의 내용에 따르면, 0.1초안에 시스템으로부터 응답을 받으면 유저는 즉각적인 응답을 받는다고 느낀다고 합니다. 그래서 애플리케이션을 만들며 이상적인 응답 시간으로 100ms을 목표로 할 수 있습니다.
1.0 second is about the limit for the user's flow of thought to stay uninterrupted, even though the user will notice the delay. Normally, no spacial feedback is necessary during delays of more than 0.1 but leff than 1.0 second, but the user does lose the feeling of operating directly on the data.
그리고 약 1초가 흐른후 유저는 이를 감지한다고 합니다. 유저는 애플리케이션이 요청한 작업을 처리하고 있음을 인지하고, 앱에 대한 집중력이 저하될 수 있습니다.
10 seconds is about the limit for keeping the user's attention focused on the dialogue. For longer delays, users will want to perform other tasks while waiting for the computer to finish, so they should be given feedback indicating when the computer expects to be done. Feedback during the delay is especially important if the response time is likely to be highly variable, since user will then
대부분의 유저가 기다릴수 있는 한계치는 10초라고 합니다. 10초가 지나면 유저는 컴퓨터가 작업을 마치는 것을 기다리는 것보다 다른 작업을 시도할 가능성이 크다고 합니다. 이 시간은 유저가 처음 page에 방문해 page가 로드되는 시간까지 포함합니다. 만약 page 로드가 더디다면 이또한 사용자 경험에 좋지 않은 영향을 줄 수 있습니다.
성능과 관련된 추가 통계 자료가 궁금하다면, 아래의 자료를 참고해주세요.
Aberdeen Group found that a 1 second slow down resulted 11% fewer page views, 7% less conversion.
Akamai found that two-second delay in web page laod time increase bounce rates by 103 percent.
A 400 millisecond improvement in performance resulted in a 9% increase in traffic at Yahoo.
Google found that a 2% slower page resulted in 2% fewer searches, which means 2% fewer ads shown.
100 millisecond improvement in performance results in 1% increase in overall revenuw at Amazon.
53% of users will leave a mobile site if it takes more than 3 secs to load.
According to research, if you want user to feel like your site is faster than your competitors, you need to be 20% faster.
속도는 웹 애플리케이션에서 매우 중요하기때문에 이를 개선하기 위해 여러 작업을 하지만, 앱의 규모 또한 점점 더 키지고 있어 이것이 쉽지만은 않습니다. 7년전 데스크탑 웹앱의 평균 사이즈와 비교를 해보면 지금의 앱은 거의 2~3배 규모로 커져있습니다. 모바일은 더 가파른 비율로 그 크기가 커지고 있습니다. 그만큼 모바일폰의 스펙이 좋아지고 있지만, 브라우저는 우리가 코드의 양을 늘리는 비율만큼 빨라지고있지 않습니다. 참고로, LTE 속도 또한 무제한 플랜으로 인해 느려지고 있다고합니다.
성능을 고려할때 우리가 만들고 있는 애플리케이션이 유저에게 제공해야 하는것이 무엇인지 생각해보면 좋습니다. 예를 들면, newyork times는 유저에게 콘텐츠를 가능한 즉각적으로 보여주는것이 아마도 가장 큰 우선순위가 될 것입니다. 로딩바를 보여주는 것 또한 사치가 될 수 있습니다. gmail의 경우는 다르게 접근해 볼 수 있습니다. gmail에서는 로드바를 볼 수 있는데, 이와 같은 앱의 경우 유저가 앱을 장시간 켜놓고 사용하는 상황이 많습니다. 따라서, memory leak이 발생하지 않고 앱이 계속 켜져있어도 느려지지 않도록 하는것이 중요합니다.
성능을 고려할 때에도 앱의 기능을 고려해 어떠한 관점으로 접근을 할지 고민을 해봐야 합니다. 성능과 관련해 구분을 하자면 크게 세 가지 network load performance, javascript performance, rendering performance로 분류해 볼 수 있습니다.
client side application은 유저가 요청을 하면 source code를 전달해야 합니다. page를 유저에게 빠르게 전달하는일은 중요합니다. 일반적으로 웹앱의 성능에 대해 이야기할때 load performance에 대해 이야기하는 경우가 많습니다.
page가 load되면 이제 유저가 우리가 만든 애플리케이션을 이용할 수 있습니다. source code를 전달하면 client 측에서 코드를 parse하고 애플리케이션을 build하는 작업을 합니다. 그래서, Javascript의 parsing, compiliation performance를 고려해야 합니다. 이를 위해서 코드의 어느 부분이 취약한지 분석할 수 있어야 하고, 이를 리팩토링 할 수 있는 능력이 있어야 합니다.
Javascript 애플리케이션은 단순히 브라우저에서 작동하는 프로그램이 아닙니다. 브라우저의 Page와 DOM을 조작하고 여러 상호작용을 합니다. 따라서, 전체적인 시스템이 어떻게 흐르느지를 파악하고 loadblock이 발생하지 않도록 하는 작업이 필요합니다.
앞서 우리의 애플리케이션이 즉각적으로 반응하는 것과 같은 사용자 경험을 위해서는 100ms 내에 결과를 보여줘야 한다는 조사를 언급했습니다. 모든 유저의 interaction에 이와 같이 빠르게 반응을 하면 좋지만, 실제 환경에서 모든 상호작용을 이렇게 처리하기는 매우 어려울 것입니다. 하지만, 성능과 관련된 목표로하는 수치를 바탕으로 프로그래밍을 하면, 좀 더 좋은 애플리케이션을 개발할 수 있다고 생각합니다.
이와 관련된 기준점으로 구글에서 제시하는 Rail(Response Animation Idle and Load)가 있습니다.
애니메이션 프레임 속도가 다르면 유저가 눈치챕니다. 초당 60 프레임을 생성하는것이 사용자가 애니메이션을 부드럽다고 여긴다고 합니다. 초당 60프레임을 생성하려면 프레임당 16ms이 걸려야 합니다. 하지만 브라우저가 화면을 그리는 시간 또한 필요하기때문에 우리의 코드는 10ms 이내에 완료가 되어야 합니다.
앞서 언급한 것처럼 위의 수치는 목표로하는 기준이지, 실제 상황에서 완벽히 지키기는 어려울 것입니다. 대신 현재 애플리케이션의 성능을 10%씩 점진적으로 개선하겠다고 계획을 세우는 것은 좋다고 생각합니다. 우리는 앱이 느리다는 생각이 들면, 어느 부분이 느린것인지 분석하고 가설을 세우고 어떻게 대처할지를 고민해 볼 수 있습니다.
어떠한 개선 사항이 효과가 있는지 없는지 알기 위해서는 성능 측정을 해야합니다. Rob Pike의 말을 인용하면 측정하기 전까지 성능 개선을 위한 작업을 안하는 것이 좋다고 합니다. 자신이 어떠한 작업을 진행하려는지 정확히 알기 전에는 최적화 작업을 하지 않는것이 좋습니다. 모든 추상화된 작업은 trade-off가 존재하기 때문에 잘못된 최적화는 다른 문제를 발생시킬수 있습니다.
Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest. - Rob Pike
성능 테스트를 할 때에는 또한 고려해야할 사항이 있습니다. 맥북 프로와 같은 고급 장비에서 실행할지 아니면 일반적인 사양의 디바이스에서 실행할지, 또는 완벽하지 않은 컨디션의 네트워크 환경 등을 고려해 볼 수 있습니다.
한가지 더 생각해볼만한 사항은, 미세한 최적화 작업을 여러번 하는것보다 때로는 더 나은 architecture나 자료구조를 생각해 보는것이 성능에 더 좋은 영향을 미칠수 있습니다. 매우 간단한 예를 들어, DOM에 매우 많은 리스트가 있어 앱이 느려진다면 pagination을 추가해 해결해 보려 할 수 있습니다.
어떠한 상황에서건 최적화를 위한 최적의 방법이 존재하지는 않기 때문에, 개발자로서 여러 상황을 고려해가며 최적화를 진행해야 할 것입니다.