성능 예산은 불만이 들어온 뒤가 아니라 설계 전에 정하세요
성능을 최적화 단계로 다루면 언제나 기능에 집니다. 설계가 시작되기 전에 합의된 제약으로 다루면, 조용히 그리고 공짜로 더 나은 결정을 만들어 냅니다.
거의 모든 팀이 성능은 중요하다고 말합니다. 그리고 거의 모든 팀이 그것을 막바지 단계에 배치합니다. 거기서 성능은 출시와 경쟁하고, 집니다.
결국 빠른 제품을 갖게 되는 팀은 다른 일을 합니다. 영웅적인 최적화가 아닙니다. 누군가 디자인 도구를 열기 전에 "충분히 빠르다"의 의미를 정하고, 그 숫자를 브라우저 지원 목록처럼 다룹니다. 목표가 아니라 제약으로.
"나중에 최적화하자"가 실패하는 이유
이유는 셋이고, 여러분을 쓰러뜨리는 건 세 번째입니다.
- 절충을 강제하는 것이 없다. 개별 기능은 따로 보면 값을 합니다. 예산이 없으면 "아니오"라고 말하는 것이 없고, 합치면 느려집니다.
- 싼 해법은 바닥난다. 압축, 캐싱, 이미지 포맷이 사 주는 건 정해진, 그리 크지 않은 양뿐입니다. 그다음은 구조의 영역입니다.
- 비싼 원인은 구조에 있다. 과하게 가져오는 데이터 계층, 네트워크에서 막히는 렌더링 경로, 임계 경로에 놓인 서드파티 스크립트. 이것들은 초기에 결정되고 나중에 걷어내는 데 막대한 비용이 듭니다.
측정할 수 있게 될 무렵이면 결과를 결정한 판단은 이미 몇 달 전 것입니다.
예산은 어떤 모습인가
예산이란 빌드가 통과하거나 실패할 수 있는 소수의 구체적인 한계입니다. KoiSpeak 검색에 대한 예를 들면:
| 지표 | 예산 | 이유 |
|---|---|---|
| 첫 결과까지 걸리는 시간 | 150ms 미만 | 사람들은 말하다 말고 사전을 엽니다. 이걸 넘으면 기다린 느낌이 듭니다. |
| Largest Contentful Paint | 중급 휴대폰에서 2.5초 미만 | "좋음"으로 통하는 일반적 기준. |
| Interaction to Next Paint | 200ms 미만 | 입력이 끊기는 느낌을 주면 안 됩니다. |
| 전송하는 자바스크립트 양 | 경로별 상한 | 나머지 전부를 예측하는 유일한 숫자. |
예산을 장식이 아니라 진짜로 만드는 성질이 둘 있습니다.
- 형용사가 아니라 숫자일 것. "빠르다"로는 빌드를 실패시킬 수 없습니다. 150ms로는 가능합니다.
- 사용자가 실제로 가진 기기에서 측정할 것. 개발자 노트북에서 사무실 와이파이로 잰 예산은 아무것도 재지 않은 것입니다.
실제로 존재하는 하드웨어에서 시험하세요
여기가 대부분의 성능 작업이 시작도 전에 어긋나는 지점입니다.
개발은 빠른 기계, 빠른 회선에서 이뤄집니다. 사용자는 몇 년 된 중급 안드로이드 폰에서, 모바일 데이터로, 백그라운드에 앱 열댓 개를 띄운 채입니다. 두 경험의 차이는 20%가 아닙니다. CPU를 쓰는 작업에서는 흔히 5배에서 10배입니다.
실무상의 최소한:
- 진짜 중급 기기를 한 대 책상에 두고 매주 씁니다.
- 개발자 도구의 CPU 제한을 특별 훈련이 아니라 기본값으로 켭니다.
- 실제 세션의 현장 데이터를 모읍니다. 실험실은 무엇이 바뀌었는지, 현장은 사용자가 실제로 무엇을 받았는지 알려 줍니다.
예산이 결정을 바꾸는 방식
가치는 측정에 있지 않고, 아무것도 만들기 전에 논쟁을 일찍 싸게 끝내는 데 있습니다.
- 서체가 비용이 된다. 두 서체 네 굵기는 모바일 예산에서 실질적인 몫입니다. 설계 단계에서 두 굵기로 줄이는 판단이 잡음 없이 내려집니다.
- 애니메이션 라이브러리가 스스로를 정당화해야 한다. 직접 쓸 CSS와 비교해서.
- 분석 도구와 채팅 위젯이 계산에 들어간다. 서드파티 스크립트가 종종 가장 큰 항목인데, 팀의 누구도 쓰지 않았기에 아무도 눈치채지 못합니다.
- 데이터 모양이 예산을 따른다. 첫 결과가 150ms 안에 와야 한다면 큰 덩어리를 받아 클라이언트에서 거를 수 없습니다. 그러면 접두사 색인으로 밀려가고, 그게 원래 정답입니다.
마지막 항목이 바로 그 패턴입니다. 예산은 여러분을 늦추지 않습니다. 올바른 구조를 더 일찍 드러냅니다.
출시 후에 하는 성능 작업은 구조 작전입니다. 처음부터 제약으로 다뤄진 성능은 그냥 설계입니다.
의식 없이 강제하기
아무도 확인하지 않는 예산은 소망입니다. 강제 장치는 싸게 유지하세요.
- 번들 크기 초과 시 빌드를 실패시키기. CI 설정 한 줄로 회귀의 대부분을 잡고, 유지비는 0입니다.
- 풀 리퀘스트마다 합성 측정을 돌리기. 가장 중요한 두세 경로만으로 충분합니다.
- 현장 지표는 주 단위로 알림. 커밋 단위가 아니라. 실사용자 데이터는 잡음이 많으니 추세를 보세요.
- 제품이 바뀌면 예산을 재검토하기. 예산은 신성하지 않습니다. 이유를 갖고 의식적으로 올리는 건 괜찮습니다. 소리 없이 넘어가는 건 안 됩니다.
예산을 어디에 쓸까
예산은 최소화가 아니라 배분의 문제입니다. 무게값을 하는 것들이 있습니다.
- 임계 경로. 사용자가 찾아온 이유가 가장 먼저고 나머지는 기다려도 됩니다. 사전이면 검색창과 결과. 상점이면 상품 이미지와 가격.
- 측정 속도보다 체감 속도. 결과 뼈대를 즉시 보여 주는 편이 응답을 40ms 앞당기는 것보다 나은 경우가 많습니다.
- 입력에 대한 즉각 반응. 키 입력에 약 100ms 안에 반응하면 즉시로 느껴집니다. 대략 300ms를 넘으면 사람들이 알아챕니다.
불편한 부분
진짜 예산은 개별적으로는 좋은 것들에 아니라고 말해야 함을 뜻합니다. 바로 그래서 작동하고, 또 그래서 팀들이 조용히 예산을 버립니다. 누군가 원하는 기능을 예산이 처음 막는 순간, 가장 쉬운 수는 예산을 올리는 것이니까요.
규율은 숫자를 정하는 자리에 있지 않습니다. 그 숫자를 지켜 내는 회의에 있습니다.