성능 튜닝 전에 성능 예산부터 구하자

Shef·2023년 2월 20일
22

Infra

목록 보기
2/5
post-thumbnail

이번 글부터 웹 서비스의 성능을 개선해나가는 글을 작성하고자 합니다.

예상되는 글의 순서는 다음과 같습니다.

  1. 성능 목표 잡기
  2. 성능 테스트 진행하기
  3. 문제 원인 파악하기
  4. 성능 개선하기

먼저 서비스의 '웹 성능 예산'을 구하는 것부터 시작하겠습니다.

웹 성능 예산이란 무엇인가요?

'웹 성능'이 좋다는 것은 사용자들이 웹사이트에 접속했을 때 이들이 원하는 콘텐츠가 로딩될 때까지의 시간이 짧다는 것을 의미합니다. '웹 성능이 좋다'라고 하면 '콘텐츠가 빨리 로딩된다'라고 할 수 있죠. 그렇다면 '웹 성능 예산'은 무슨 말일까요?

국가 예산을 예로 들어보겠습니다. 국가 예산을 보면 먼저 총 얼마를 사용할 수 있는지 정하고, 다시 각각의 분야에 쓸 수 있는 최대 돈을 정합니다. 총 예산 600조, R&D에는 4조, 저출산 대응 7조 이런 식이죠.

웹 성능 예산도 비슷합니다. 먼저 목표 웹 로딩 시간을 정하고, 웹 로딩 과정에서 일어나는 여러가지 과정에 대해서 최대 허용 가능한 시간을 배분합니다. 총 예산 3초, DB조회는 1초, API 요청 처리는 0.5초 이런 식입니다.

실제로 웹 성능 예산을 짤 때는 시간 뿐만이 아니라 시간에 영향을 주는 세부적인 요소들에 목표 허용량을 정하기도 합니다만, 서버 개발자 입장에서는 시간으로 예산을 세우는게 직관적이고 이해하기 편하다고 생각합니다.

성능 개선은 비용이 드는 작업입니다. 서비스에 모든 페이지를 무조건 빠르게 만드는 것은 ROI가 좋지 않죠. 따라서 가장 중요한 페이지에 대해서만 웹 성능 예산을 짜고 성능 개선을 진행하는 것이 권장됩니다.

위 내용을 바탕으로 다음과 같이 웹 성능 예산을 짜볼 수 있습니다.

목표 : 사용자가 '홈 화면' 에 접속했을 때 '최대 3초' 안에 콘텐츠를 받아 볼 수 있어야 한다.

이를 위해서,
1. 정적 리소스는 최대 50ms 안에 리턴되어야 한다.(Web 서버 예산)
1. API 요청 처리는 DB 조회 시간을 제외하고 최대 100ms을 넘어서는 안된다. (WAS 예산)
2. DB에서는 최대 500ms 안에 조회가 이루어져야 한다. (DB 예산)

로딩 속도가 3초 이상이 될 때 53%의 사용자는 떠나간다

국가에서는 왜 예산을 정할까요? 그야 돈이 그 정도 밖에 없고 예산을 초과하면 문제가 생기기 때문이겠죠.

웹 성능 예산을 초과하면?

저희가 목표로 잡고 있는 로딩 시간을 초과하게 되고, 사용자들은 점점 불만이 쌓이다가 서비스를 떠나가게 됩니다. 추후 기업이 이 문제를 해결하더라도 한 번 신뢰를 잃은 서비스를 사용자들은 다시 찾지 않습니다.

따라서 저희는 목표한 로딩 시간을 지키기 위해 예산을 잘 짜고 예산을 초과하는 부분에 대해서 개선을 진행해야 합니다.

하지만 예산을 짜는 것은 쉽지 않다

예를 들어 우리가 아래와 같이 예산을 짰다고 해봅시다.

"우리는 속도로 승부본다. 목표는 0.3초야"
"계산하기 쉽게 브라우저 렌더링은 0.1초 안에 API도 0.1초 DB도 0.1초 안에 조회해야 돼"

그런데 아무리 성능 개선을 진행해도 현실적으로 DB조회가 0.1초 안에 이루어지는게 불가능하다면 이 예산은 잘못 짠게 되겠죠.

따라서 적절한 예산을 짜기 위해서는 전략이 필요합니다. 비슷한 다른 서비스들의 중요 페이지들은 각각의 요소에 대해 얼마만큼에 시간이 걸리는지 확인해보기도 하고, '이 부분은 이 정도 목표는 달성할 수 있을거야'와 같은 가설을 세우고 테스트한 후 예산을 수정하는 과정도 필요합니다.

지하철 노선도 서비스의 예산 짜보자

웹 성능 예산에 대해 어느 정도 이해가 됐다면, 이제 저와 함께 지하철 노선도 서비스 예제로 예산에 대해서 짜보도록 하겠습니다.

저희가 다루는 지하철 노선도 서비스는 다음과 같은 사용자 시나리오를 가진 아주 간단한 서비스입니다.

  1. 사용자는 경로 검색 페이지에 들어온다.
  2. 출발역과 도착역을 정하고 검색 버튼을 클릭한다.
  3. 최단 거리와 경로를 확인한다.

서버 구조

서버는 웹 서버 - WAS - DB로 이루어진 3 tier 형태의 간단한 구조를 갖고 있습니다.

가장 중요한 페이지 고르기

사용자 시나리오에 따르면, 가장 중요한 페이지는 '경로 검색 페이지''경로 검색 결과 페이지' 입니다. 단 두 개의 페이지만으로 사용자는 원하는 모든 것을 얻을 수 있습니다. 이미 운영하고 있는 서비스라면, 웹 로그(Web Log or Access Log) 분석 등을 통해 중요한 페이지를 더 정확하게 파악할 수 있습니다.

목표 지표 고르기

앞에서 '웹 성능'은 사용자들이 웹사이트에 접속해서 원하는 콘텐츠가 로딩될 때까지의 시간을 의미한다고 말했는데요. 여기서 원하는 콘텐츠는 페이지마다 다를 수 있습니다.

저희 서비스의 경로 검색 페이지에서는 단순히 출발역 도착역 등의 텍스트가 뜨는 것보다, 출발역을 클릭해서 역 선택이 가능해지는 상태를 가장 기다릴 것입니다. 따라서 저희는 웹사이트가 사용자와 상호작용이 가능해지기까지 걸리는 시간을 의미하는 TTI(Time To Interactive)지표를 목표 지표로 고르겠습니다.

반면 경로 검색 결과 페이지 같은 경우 사용자들은 당연히 거리나 경로와 같은 텍스트 또는 이미지가 뜨기를 가장 기다릴 것입니다. 따라서 저희는 가장 큰 비주얼 콘텐츠가 표시되는 시간을 의미하는 LCP(Largest Contentful Paint)를 목표 지표로 고르겠습니다. 여기서 비주얼 콘텐츠는 텍스트, 이미지, 비디오 등 눈에 보이는 모든 것을 의미합니다.

이런 지표는 TTI, LCP 외에도 첫번째 비주얼 콘텐츠가 표시되는 시간을 의미하는 FCP(First Contentful Paint) 등 다양합니다.

목표 시간 잡기

목표 시간을 잡기 위해서 다음과 같은 연구 결과를 참고하면 좋습니다.
1. 3초의 법칙 - 3초 안에 로딩되지 않으면 53%의 사용자는 떠난다. [1]
2. 사용자는 20% 이하의 성능 차이는 인지하지 못한다. [2]

저는 3초의 법칙을 지키면서 목표 지표에 대한 시간이 주요 경쟁사 중 가장 빠른 서비스 대비 최소 20% 이상 뛰어난 수준으로 목표 시간을 잡아보도록 하겠습니다. 위 목표에 대한 저의 논리는 이렇습니다.

'지하철 노선도 서비스는 서비스 자체로 다른 서비스와 차별화를 꾀하기 힘들다'
'이러한 상황에서 후발 주자로써 돋보이려면 속도가 빨라야 한다.'
'더군다나 우리 서비스는 주요 경쟁사보다 간단한 정보를 제공한다. '
'따라서 주요 경쟁사 중 가장 빠른 서비스 대비 최소 20% 이상 뛰어난 수준을 목표로 설정한다.'

정해진 답은 없고 각자만의 논리로 목표를 잡으시면 됩니다.

아마 주요 경쟁사로 저희가 매일 쓰는 '지하철종결자'나 '카카오지하철'이 떠오르리라 생각됩니다만, 저희 예제는 웹 서비스이기 때문에 웹으로 이용 가능한 '네이버지도'와 '카카오맵'을 주요 경쟁사로 잡겠습니다.

경로 검색 페이지 목표 시간 잡기

먼저 PageSpeed에서 저희 서비스와 네이버지도, 카카오맵의 경로 검색 페이지의 TTI 지표를 확인해보겠습니다.

네이버지도 : https://map.naver.com/v5/subway/1000/-/-/-?c=15,0,0,0,dh

카카오맵 : https://map.kakao.com/

네이버보다 빠른 카카오의 TTI인 2.6초에 비해 20% 빠른 2초를 목표로 잡도록 하겠습니다.

경로 검색 페이지의 목표 : 최대 TTI 2s (사용자가 최대 2초 안에 상호작용 가능해야 한다. )

경로 검색 결과 페이지 목표 시간 잡기

이번엔 PageSpeed에서 네이버지도의 경로 검색 결과 페이지의 LCP 지표를 확인해보겠습니다.

네이버 지도 : https://map.naver.com/v5/subway/1000/417/239,4003,1609/-?c=15,0,0,0,dh

6.3보다 20% 빠른 5초를 목표로 잡을 수도 있지만, 저희는 3초의 법칙을 지키기 위해 LCP 3초를 목표로 잡도록 하겠습니다.

경로 검색 결과 페이지의 목표 : 최대 LCP 3s(사용자가 최대 3초 안에 주요 결과를 볼 수 있어야 한다.)

카카오맵의 경우 출발역과 도착역을 각각 선택할 때마다 결과가 바로 바로 업데이트되어 동작 방식이 저희 서비스와 사뭇 다르다 생각해 제외하였습니다.

시간 배분하기

우선 브라우저의 레더링하는 부분을 제외하고 구간을 크게,

'정적 웹서버 브라우저로 데이터를 보내는 시간'
'WAS가 요청에 따라 로직을 처리하는 시간'
'DB가 데이터를 조회하는 시간'

으로 나누고 시작하겠습니다.

경로 검색 페이지 시간 배분하기

경로 검색 페이지 목표 : 최대 TTI 2s

  • '정적 웹서버 브라우저로 데이터를 보내는 시간'

퍼포먼스 탭을 통해 분석해본 카카오 맵의 정적 파일 중 TTI 전까지 전송하는데 가장 오래 걸린 시간이 165ms가 걸렸습니다. 따라서 저희는 165ms보다 20% 빠른 132ms를 목표로 잡겠습니다.

  • 'WAS 및 DB'

경로 검색 페이지는 WAS의 요청할 일이 없으므로 목표는 따로 없습니다.

경로 검색 결과 페이지 시간 배분하기

경로 검색 결과 페이지 목표 : 최대 LCP 3s

  • '정적 웹서버 브라우저로 데이터를 보내는 시간'

퍼포먼스 탭을 통해 분석해본 네이버 지도의 정적 파일 중 LCP 전까지 전송하는데 가장 오래 걸린 시간이 57ms가 걸렸습니다. 따라서 저희는 57ms보다 20% 빠른 45ms를 목표로 잡겠습니다.

  • 'WAS의 로직 처리 및 DB 조회'

사실 퍼포먼스 탭을 통해 분석해본 결과, 저희 경로 검색 결과 페이지는 이미 LCP 3초 목표를 지키고 있었습니다. 따라서 굳이 성능 개선을 진행할 필요가 없습니다만 트래픽이 많은 상황에서도 이 목표를 지킬 수 있을까요?

현재 WAS 및 DB가 처리한 파일이 311ms가 걸리고 있습니다. 퍼포먼스 탭을 통해 분석해 본 네이버 지도의 WAS 처리 시간 중 가장 오래 걸린 시간은 116ms로, 이 수치에 비하면 매우 느리다고 할 수 있습니다.

따라서 저는 116ms 보다 20% 빠른 92.8ms를 웹 서버 뒷단에서의 목표로 잡아보도록 하겠습니다. 저는 일반적으로 DB가 레이턴시의 70% 정도를 차지한다는 점을 들어 3:7의 비율로 WAS의 로직 처리에 27.8ms를 분배하고 DB 조회에는 65ms의 시간을 분배하도록 하겠습니다.

즉 WAS는 로직 처리시 최대 27.8ms를 넘어서는 안되고 DB 조회시에는 65ms를 넘겨서는 안됩니다.

마무리

최종적으로 저희가 짠 웹 성능 예산을 보도록 하겠습니다.

경로 검색 페이지경로 검색 결과 페이지
최종 목표최대 TTI 2s최대 LCP 3s
웹서버의 정적 리소스 반환최대 132ms최대 45ms
WAS 로직 처리최대 27.8ms
DB 조회최대 65ms

다음 글에서는 이 성능 예산을 바탕으로 목표를 잡고 성능 테스트를 진행하는 과정을 알아보도록 하겠습니다 :)

부록

퍼포먼스 탭 보는 법

크롬에서 F12를 누른 후 Network 또는 Performance 탭에서 HTTP 요청에 대한 처리 시간을 알 수 있습니다. 최근에는 Performance 탭보다 더 직관적이고 이해하기 쉬운 Performance Insights 탭이 나왔습니다. 저는 저희 서비스의 경로 검색 결과 페이지를 Performance Insights 탭을 이용해서 분석해보겠습니다.

Performance Insights 탭은 아직 베타 버전으로 오른쪽 위에 점 3개 -> more tools로 들어가면 찾을 수 있습니다.*

Performance Insights 탭에 netwok 판넬을 펼쳐보면 위와 같이 캔들차트를 90도로 뒤집은 듯한 모양의 그림들이 나옵니다. 네모를 클릭해보면 오른쪽 아래에 서버가 요청을 처리하는 동안 기다린 시간 (Waiting), 응답 결과를 다운 받는 시간 (Download), 응답 결과를 브라우저가 처리하는 시간 (Processing)을 볼 수 있습니다.

참고로 그림으로 보면 왼쪽 꼬리는 TCP 연결을 맺고 HTTP 요청 메시지를 보내는 구간, 네모난 박스 중 밝은 부분은 HTTP 요청이 서버에 의해 처리되는 시간, 음영된 부분은 브라우저가 응답 메시지를 다운로드 받는 시간, 오른쪽 꼬리는 브라우저가 처리하는 시간을 의미합니다.

위 이미지는 네이버지도의 Performance Insights 탭으로 WAS 및 DB가 처리하는데 116ms, 웹 서버로부터 브라우저로 다운되는데 45ms, 웹서버가 처리하는데 931ms가 걸리고 있습니다.

Reference

넥스트스텝 - 인프라 공방
Working With Web Performance Budgets | DebugBear
[1] Google Research, Webpagetest.org, Global, sample of more than 900,000 mWeb sites across Fortune 1000 and Small Medium Businesses. Testing was performed using Chrome and emulating a Nexus 5 device on a globally representative 3G connection. 1.6Mbps download speed, 300ms Round-Trip Time (RTT). Tested on EC2 on m3.medium instances, similar in performance to high-end smartphones, Jan. 2017.
2

2개의 댓글

comment-user-thumbnail
2023년 7월 14일

좋은 글 감사합니다 잘 보고 갑니다!

1개의 답글