올리브영 테크블로그 포스팅 올리브영 메인페이지 성능 개선기
Frontend

올리브영 메인페이지 성능 개선기

모바일 메인페이지를 개선하기전 고민과 개선 후 결과를 알아봅시다

2022.12.07

여는글

안녕하세요~ 올영생활 2년 차가 다 되어가는 웹 프론트엔드 개발자 개발새발자 (a.k.a 고인물...) 입니다~만반잘부??!

올리브영 온라인몰(이하 온라인몰)은 근 6개월간 많은 변화를 이뤄냈습니다.

하지만, 온라인몰의 성장세가 엄청나게 증가함에 따라 많은 사용자가 온라인몰의 고질적인 문제인 성능으로 불편함을 이야기하고 있습니다.

이러한 이슈는 사용자 경험의 큰 영향을 받기에 각 파트는 성능 이슈를 가장 먼저 해결해야 할 중점 이슈로 받아들이고 있으며, 사용자가 불편함을 겪지 않도록 성능을 개선하기 위해 많은 노력을 하고 있습니다.

그 중 온라인몰 성능개선 파트는 성능을 중점으로 고민하고 해결해 나가는 파트이며, 이번에 공유 드릴 내용은 성능개선 파트에서 온라인몰 메인페이지를 개선했던 경험을 프론트엔드 관점에서 작성해 보려고 합니다.

(백엔드는 아마 백엔드 개발자분이신 달고나윤님이 작성하시리라 믿습니다 ㅎㅎㅎ ☞( ͡o ͜ʖ ͡o)☞넝담~)

그럼 온라인몰의 메인페이지는 어떤 문제가 존재했고 그 문제를 어떻게 해결했는지에 대해서 자세히 알아보도록 하시죠~ Let's GO

가즈아아아

올리브영 너무 느려요...

올리브영 앱 리뷰

저희도 알고 있습니다... 네.. 참 잘 알고 있지요...(자기객관화가 확실한 편...??)

현재의 온라인몰은 꽤 성능이 빨라졌지만, 불과 6개월 전만 해도 온라인몰을 사용하시는 고객분들이 항상 말씀하시는 이슈는

"너무 느려서 사용성이 떨어진다!"

였습니다. 그럼 온라인몰 그중에서도 메인페이지는 왜 느렸을까요?

느린 이유 파악하기

먼저 개선 전 올리브영의 모바일 메인페이지를 한번 보도록 하겠습니다.

올리브영 온라인몰 앱 로딩 애니메이션

페이지를 서버에 요청하면 헤더를 서버에서 반환하고 긴 지연시간을 가지고 컨텐츠를 불러옵니다. 왜 이렇게 동작을 할까요?

올리브영 온라인몰 메인페이지 렌더링 로직

개선 전 온라인몰 메인페이지의 동작 로직을 한번 보도록 하겠습니다.

  1. 메인페이지 진입
  2. 헤더 렌더링
  3. 0.5초 뒤 활성화 할 탭 체크
  4. 활성화 탭에 대한 컨텐츠 서버 요청

여기서 조금 이상한 부분이 보입니다.

바로 3번의 활성화 할 탭을 체크하기 위해 0.5초라는 불필요한 로직이 있습니다.

이 부분은 개선이 필요해 보입니다.

데이터 독 APM

컨텐츠 요청에는 문제가 없는지 확인하기 위해 올리브영에서 현재 활용하고 있는 모니터링 시스템인 Datadog을 한번 확인해보겠습니다.

사진을 보시면 메인페이지의 홈 컨텐츠를 불러오는데 1.91s의 시간이 소요됩니다.

하지만 실질적인 JSP render는 77.9ms이고 나머지는 서버 내 쿼리 실행으로 시간이 소요되고 있습니다.

올리브영 온라인몰 앱 성능

내친김에 크롬 브라우저에서 간단하게 돌려볼 수 있는 퍼포먼스 기능을 활용하여 확인해 보도록 하겠습니다.

FCP를 받고 나서 한참이 지나고 나서야 LCP 시간이 측정됩니다. 엄청나게 많은 리소스들이 네트워크 요청을 하고 있는 것 같습니다.

어느정도 원인은 파악되었습니다.

  • 렌더링에 불필요한 로직 존재
  • 너무 느린 LCP
  • 쿼리 요청에 따른 문서 생성 시간 지연

자! 그럼 위 이슈를 해결해 보도록 하겠습니다.

렌더링에 불필요한 로직 삭제

올리브영 온라인몰 메인페이지 렌더링 로직

위 로직은 메인페이지 렌더링 로직입니다. 여기서 중점적으로 볼 것은 0.5초에 타이머가 과연 필요한가입니다.

이전 히스토리의 대한 정보가 없어서 정확히는 알 수 없지만, 예상하기에는 메인페이지 탭 컨트롤을 위해 URL의 해시 값을 받아와서 작업해야 하는데, url 값이 제때 바뀌지 않으니 이러한 지연 로직을 넣어 해결한 것 같습니다.

해당 코드 때문에 메인페이지의 컨텐츠를 요청하는 시간이 코드 상 대략 0.5초 정도 지연되고 있었으며, 자바스크립트의 이벤트 루프 특성상 0.5초 그 이상의 지연도 발생할 수 있습니다.

사실 이곳 말고도 많은 부분에서 지연 로직을 남발하고 있습니다만 기존 레거시 코드들 사이에서 빠르게 해결할 수 있는 지연 로직은 위 0.5초 로직을 제거하는 것으로 판단했기에 해당 로직을 삭제하였습니다.

따라서 해당 로직 때문에 발생하는 불필요한 0.5초의 지연을 제거하면, 성능을 향상할 수 있을 것으로 보입니다.

바뀐 로직은 아래와 같습니다.

올리브영 온라인몰 메인페이지 개선 렌더링 로직

실질적으로 0.5초 로직을 제거했을 때 LCP 시간을 확인해 보겠습니다.

올리브영 온라인몰 앱 성능

로컬 개발 환경 기준으로 setTimeout을 삭제하기 전에는 LCP가 3.9초 정도 걸리던 게 삭제한 후에는 3.4초로 준 것을 확인할 수 있습니다.

하지만 메인페이지에 setTimeout을 제거하여도 0.5초에 차이는 사용자로서는 큰 차이를 느끼기 어렵습니다.

그렇다면 좀 더 속도를 줄일 방법을 더 찾아보도록 하겠습니다.

너무 느린 LCP

올리브영 온라인몰 앱 성능

LCP를 줄이기 위해서 최대한 사이즈가 큰 리소스를 최대한 빨리 제공해 주어야 합니다.

사이즈가 큰 리소스를 연속적으로 호출하게 되면, LCP는 점점 더 늘어나게 됩니다.

따라서 리소스 로드 시점을 지연시켜야 합니다.

올리브영 온라인몰 앱 성능

온라인몰 메인페이지는 5개의 탭이 존재하고 탭 진입 시, 자연스러운 스와이프를 제공하기 위해 좌·우측 탭도 같이 렌더링합니다.

이러한 방식은 나쁘지 않은 방식입니다.

왜냐하면 사용자가 스와이프를 할 때 서버 요청을 보내고 받는 시간, 렌더링 시간을 감소시킬 수 있기 때문입니다.

하지만, 동시에 네트워크를 요청하고 렌더링하기에 사용자가 보고 있는 사이즈가 큰 리소스의 렌더링 시간이 우선순위에서 부분적으로 밀리게 되고, 사용자는 탭이 느리게 느껴집니다.

올리브영 온라인몰 앱 성능

해당 사진에서 우리가 중요하게 봐야 할 부분은 우측 하단에 DOMContentLoaded 시간과 로드 시간입니다.

이 두 시간의 의미는 아래와 같습니다.

DOMContentLoaded

브라우저가 HTML을 전부 읽고 DOM 트리를 완성하는 즉시 발생합니다. 이미지 파일이나 스타일시트 등의 기타 자원은 기다리지 않습니다.

Load

HTML로 DOM 트리를 만드는 게 완성되었을 뿐만 아니라 이미지, 스타일시트 같은 외부 자원도 모두 불러오는 것이 끝났을 때 발생합니다.

그렇다면 Dom 자체를 완성하는데 1초가량 소요됐지만, 나머지 리소스를 요청하는데 2~3초가량 소모되었단 이야기입니다.

이것을 해결하려면 다양한 방법이 있지만, 사용자가 바로 보지 않아도 되는 탭을 DOMContentLoaded 타임에 같이 렌더링하고 같이 이미지를 로드하는 방식 때문에 이미지가 빨리 그려지지 않는 이슈를 의심해 볼 수 있습니다.

그렇다면 먼저 어떻게 최적화할지 순서도를 한번 생각해 봅시다.

기존 및 최적화 시 Swiper 동작 순서도 정리

최적화 전 순서도를 보면 0.5초 딜레이 후 탭을 요청 및 렌더링합니다.

그리고 좌우 탭은 지금 당장 필요 없는데 활성화 탭을 렌더링하는 시간에 같이 렌더링을 진행합니다.

따라서 이미지나 스크립트 로딩 시간의 우선순위가 모호해집니다.

그리고 사용자가 탭을 스와이프 할 때 브라우저가 렌더링을 다시 하도록 설계 돼 있습니다. 이러한 방식은 클라이언트에 부하를 줍니다.

하지만 최적화 후 순서도를 보면 처음 렌더링 시 불필요한 0.5초 딜레이를 제거하였고, 좌 우 탭은 지금 당장 필요 없으니, 활성화 탭 먼저 로드 한 후, 활성화 탭 먼저 로드가 완료되면 로드 타임 때 좌 우 탭을 그려줍니다.

따라서 우선순위가 좌측 우측 탭보다는 홈 탭이 빠르게 로드됩니다.

그리고 사용자가 스와이프 시 먼저 그려져 있는 탭이라면 따로 돔 변경 없이 진행할 수 있도록 Hash 방식을 최적화하여 설계하였으며, 오로지 비어져 있는 탭만 먼저 로드할 수 있도록 설계하여 클라이언트에 부하를 줄였습니다.

올리브영 온라인몰 앱 성능

쿼리 요청에 따른 문서 생성 시간 지연 개선

아무리 프론트엔드 성능을 개선하더라도 근본적으로 서버의 응답속도가 느리다면, 사용자는 느린 속도를 체감하게 됩니다.

따라서 서버 응답시간도 같이 개선되어야 합니다.

올리브영 온라인몰 앱 성능

데이터독을 한 번 더 보자면, 프론트엔드 개선으로 어느 정도 속도는 개선되었지만, 그럼에도 LCP P75 2.28초, LCP P90 3.37초대로 코어 웹 바이탈 기준 그렇게 좋은 축에 속하지 못합니다.

올리브영 온라인몰 앱 성능

또한, APM의 주요 지표를 참고하면

  • 총 request 시간 : 1.91s
  • spring.handler 시간 : 1.82s
  • render jsp 시간 : 0.077s

으로, 쿼리가 지연이 된 만큼 사용자는 빈 컨텐츠 화면을 보게 됩니다.

그렇기 때문에 아래와 같은 방식으로 수정하여 사용자가 빈 화면을 보는 시간을 최대한 줄이고 쿼리 요청을 분리하는 것이 좋아 보입니다.

그럼 어떻게 개선을 해야 할지 플로우를 작성해 보도록 하겠습니다.

올리브영 메인페이지 플로우

올리브영 온라인몰 앱 성능

위 플로우는 현 메인페이지의 플로우 입니다.

이 플로우 차트에서 개선이 필요한 부분은 유저가 빈 화면을 보는 시간을 단축시켜 유저가 빠르다고 느낄 수 있도록 해주는 게 좋아 보입니다.

올리브영 온라인몰 앱 성능

개선하게 되면 이렇게 변경을 할 수 있을 것 같습니다.

간단히 설명해 드리자면 기존에 홈 탭의 모든 데이터를 가져와 뿌리는 API를 분리하여, 사용자가 뷰포트 내 빈 화면을 보는 시간을 최대한으로 단축 시키고, 사용자가 스크롤 시 나중에 보게 될 뷰포트 외 페이지를 브라우저에 그리는 것을 플로우 차트로 그렸습니다.

모던 프레임워크에서 제공하는 CSR과 SSR 로직하고 같다고 보면 됩니다.

그럼 이 작업을 함으로 어떻게 개선이 되었을까요?

배포 이후 결과 값

배포 전

올리브영 온라인몰 앱 성능

배포 후

올리브영 온라인몰 앱 성능

비교 타임라인

올리브영 온라인몰 앱 성능

배포 전과 후 데이터독 대시보드를 보면 확연히 개선된 것을 볼 수 있습니다.

특히 LCP가 꽤 많이 감소한 게, 눈에 보입니다.

정리해보면 불필요한 로직과 성능 개선 전과 개선 후의 FID 값은 약 34%가 개선되었고, LCP는 81%가 개선되었습니다.

그리고 로딩 타임은 무려 122%라는 어마어마한 수치로 개선되었습니다.

끝으로

현재 올리브영의 온라인몰은 많은 개선이 이루어졌지만, 아직은 부족한 모습들이 많이 보이기에 계속해서 연구하고 계속해서 노력하고 있습니다.

특히 프론트엔드 파트는 레거시로 개발된 프로젝트를 모던 프레임워크로 전환하는 작업을 진행하고 있으며, 이번에 개선한 메인페이지 또한 레거시를 탈피하는 작업을 진행하고 있습니다.

(특정 페이지는 모던 프레임워크로 전환이 완료되었는데 관련해서 저희 프론트개발팀 인원이 개선기를 작성해주지 않을까 하는 조그마한 기대감~❤️)

만약 올리브영 온라인몰의 개선 및 모던 프레임워크 전환의 발을 맞추고 싶으신 분🫵 있으신가요?

그렇다면 지금이 바로 올리브영으로 오실 기회입니다.~ 츄라이츄라이~

다음에는 더 좋은 주제로 돌아오겠습니다~

그럼, 20000

참고

FrontEnd성능개선메인페이지
올리브영 테크 블로그 작성 올리브영 메인페이지 성능 개선기
🐶
개발새발자 |
Front-end Engineer
개발새발 코딩하며 성장하려고 하는 프론트엔드 개발자입니다. 만반잘부~👋