성능을 나중에 수습하는 일이 아니라 개발의 모든 단계에 내장해 팀이 성장해도 빠름을 유지하는 방법을 설명합니다.
25년 동안 글로벌 브랜드를 위한 사이트를 구축하면서, 저는 같은 패턴이 반복해서 나타나는 것을 보았습니다. 팀이 새 기능을 출시하면 사용자는 조용히 불편을 겪기 시작하고, 한참 뒤에야 버그 리포트가 조금씩 들어오기 시작합니다. 누군가 마침내 지표를 확인하면 공포가 퍼지고, 이미 수천 명에게 영향을 주고 있는 문제를 메우기 위해 기능 개발은 중단됩니다. 수정은 한동안 도움이 되지만, 한 달쯤 지나면 또 다른 속도 저하가 나타나고 사이클은 다시 시작됩니다. 팀은 무언가를 만드는 일보다 불 끄기에 훨씬 더 많은 시간을 쓰게 됩니다.
저는 이 반복되는 _출시, 불만, 공황, 땜질_의 순서를 성능 붕괴 사이클이라고 부릅니다. 안타깝게도 이것은 많은 팀의 기본 상태이며, 사기를 빠르게 갉아먹습니다.
분명 더 나은 방법이 있어야 합니다.
제가 tech-lead 역할을 맡기 시작했을 때, 실험을 시작했습니다. 성능을 나중에 정리하는 대상이 아니라 처음부터 보호해야 하는 것으로 다루면 어떨까? 성능에 민감한 한 명의 엔지니어가 날아와 문제를 해결해 주기를 기대하는 대신, 팀 전체가 책임을 나누면 어떨까? 그리고 문제가 프로덕션에 도달하기 훨씬 전에 시스템 자체가 성능을 일찍 드러내 준다면 어떨까?
여러 팀과 수많은 반복을 거치면서, 다른 패턴이 나타나기 시작했습니다. 저는 이제 이것을 _기본적으로 빠르게_라고 부릅니다.
기본적으로 빠르게는 개발의 모든 단계에 성능을 심어 넣어, 속도가 늦은 구조를 나중에 구출하는 일이 아니라 자연스러운 결과가 되게 하는 실천입니다. 여기에는 엔지니어만이 아니라 팀의 모든 사람이 참여합니다.
대부분의 조직은 성능을 아플 때 다뤄야 하는 문제로 취급하거나, 몇 달마다 버그 수정 스프린트를 잡습니다. 두 접근 모두 비용이 크고, 신뢰할 수 없으며, 거의 항상 너무 늦습니다.
속도 저하가 눈에 띄기 시작할 무렵이면, 원인은 이미 렌더링 전략, 데이터 페칭 순서, 컴포넌트 경계 속에 굳어져 있습니다. 이런 결정들이 시스템이 낼 수 있는 최대 속도의 상한을 정합니다. 그 상한 안에서는 튜닝할 수 있지만, 다시 짓지 않는 한 그 한계를 뚫을 수는 없습니다.
한편 기준선은 서서히 밀려갑니다. 느린 빌드와 굼뜬 상호작용이 당연한 것으로 받아들여집니다. 1주 차에는 받아들일 수 없었던 것이 6개월 차에는 정상처럼 느껴집니다.
그리고 일단 기능이 출시되면 관심은 다른 곳으로 이동합니다. 성능 작업은 새로운 아이디어와 로드맵 압박과 경쟁해야 합니다. 대부분의 팀은 정리를 위해 다시 돌아오지 못합니다.
성능 회귀는 드라마틱한 단일 실패 하나로 자신을 드러내는 일이 거의 없습니다. 그것은 수십 개의 그럴듯한 결정들을 통해 조용히 축적됩니다.
어떤 기능은 JavaScript를 조금 더 추가하고, 새 의존성은 숨겨진 전이 로드를 가져오며, 디자인 수정은 레이아웃 이동을 도입합니다. 단일 페이지 로드는 여전히 괜찮게 느껴지지만, 상호작용은 점점 더 무거워지기 시작합니다. 더 많은 기능이 추가되고, 더 많은 코드가 배포되며, 느린 경로가 천천히 정상 경로가 됩니다.
이것은 의존성 수준에서 가장 분명하게 드러납니다:
// 겉보기에는 충분히 무해해 보인다...
import { format } from 'date-fns'; // 약 67KB
import { debounce } from 'lodash'; // 약 71KB
import { Chart } from 'chart.js'; // 약 188KB
// ...하지만 6개월 뒤 번들은 2MB가 되었고 왜 그런지 아무도 기억하지 못한다
각 import는 따로 보면 타당했고 코드 리뷰도 통과했습니다. 경험을 망가뜨린 것은 단 하나의 결정이 아니라, 그 조합이었습니다.
이것이 예방이 언제나 치료보다 나은 이유입니다.
두더지 잡기식 수정 문화로 되돌아가지 않으려면, 빠른 결과가 자연스럽게 나오도록 유인을 바꿔야 합니다.
핵심 아이디어는 단순합니다: 느린 경로보다 빠른 경로를 더 쉽게 만들어라.
이렇게 하면 성능은 더 이상 경계심이나 영웅적 활약에 의존하지 않게 됩니다. 마찰 없이 팀을 빠른 결정 쪽으로 조용히 끌어당기는 시스템과 워크플로를 만들게 됩니다.
이것이 일상에서 어떻게 보이는지 살펴보면 다음과 같습니다:
출발점이 클라이언트 렌더링 SPA라면, 이미 오르막길을 걷고 있는 셈입니다. 선택적 hydration을 갖춘 서버 우선 렌더링(흔히 Islands Architecture라고 부릅니다)은 이를 유지하기 위해 끊임없는 미세 최적화가 필요하지 않은 성능 여유를 제공합니다. 또한 SPA 중 실제로 어느 정도가 진짜로 SPA일 필요가 있는지도 더 분명하게 해 줍니다.
의존성 크기가 IDE에 바로 표시되고, 번들 크기와 예산 검사가 CI에서 자동으로 실행되며, hydration 경고가 로컬 개발에서 드러난다면, 개발자는 변경의 비용을 즉시 보게 되고 맥락이 아직 생생할 때 문제를 수정할 수 있습니다.
유틸리티 우선 라이브러리에 손이 가게 하고, 더 작은 의존성을 선택하며, 첫 질문이 “왜 안 되지?”가 아니라 “이게 정말 필요한가?”가 되도록 하는 문화를 기르면 복잡성이 눈덩이처럼 불어나는 것을 막을 수 있습니다.
리뷰어가 변경이 렌더 시간이나 메모리 압박에 어떤 영향을 주는지 꾸준히 묻는다면, 팀 전체의 수준이 올라갑니다. 그 질문은 뒤늦은 부가 요소가 아니라 작업 기술의 일부가 되고, 결국 모든 pull request에 등장하게 됩니다.
빠름을 유지하는 팀이 성공하는 이유는 성능 전문가가 더 많아서가 아닙니다. 그들은 소유권을 분산하기 때문에 성공합니다.
디자이너는 레이아웃 안정성을 생각하고, 프로덕트 매니저는 속도를 염두에 두고 작업 범위를 정하며, 엔지니어는 성능 예산을 별도의 관심사가 아니라 정합성의 일부로 다룹니다. 모두가 빠른 코드를 배포하는 일이 올바른 코드를 배포하는 것만큼 중요하다는 점을 이해합니다.
이것이 작동하려면 회귀가 일찍 드러나야 합니다. 그러려면 지속적인 측정, 명확한 소유권, 그리고 사용자가 문제를 알아차리기 전에 문제를 부각하는 도구가 필요합니다. 시스템이 최소한의 저항으로 올바른 방향으로 끌어당기기 시작하면, 성능은 스스로 유지되는 성질이 됩니다.
빠른 기본값을 가진 팀은 1개월 차에 빠른 소프트웨어를 출시하고, 12개월 차와 36개월 차에도 여전히 빠른 소프트웨어를 출시하고 있습니다. 작은 이점들이 자신들에게 유리하게 누적되기 때문입니다.
성능 붕괴 사이클 속에서 사는 팀은 처음에는 받아들일 만한 성능으로 시작할 수 있지만, 12개월 차에는 전용 성능 스프린트를 계획하고 있고, 36개월 차에는 재작성을 논의하고 있음을 발견하게 됩니다.
차이는 전문성이나 노력에 있는 것이 아니라, 그들이 어떤 접근에서 출발했는가에 있습니다.
속도는 신뢰를 쌓고, 디자인을 날카롭게 하며, 개발을 가속하기 때문에 지렛대입니다. 그것을 잃으면 단지 몇 초만 잃는 것이 아닙니다. 사용자, 수익, 그리고 자기 시스템에 대한 자신감까지 잃게 됩니다.
기본적으로 빠르게는 팀이 이 사이클을 끊고, 성장하면서도 계속 빠른 시스템을 구축하는 방식입니다.
이 모델에 관해 더 알고 싶다면 https://fastbydefault.com을 참고하세요.
이 글은 2025년 12월 4일 https://calendar.perfplanet.com/2025/fast-by-default/에 처음 게시되었습니다.