성능 문제를 처음 마주한 개발자가 가장 먼저 하는 실수는 '원인을 안다고 가정하는 것'이다. 네트워크가 느릴 것이라 생각하거나, 데이터베이스 쿼리를 의심하거나, 번들 사이즈를 탓한다. 그런데 실제로 병목을 추적해보면, 문제는 대부분 전혀 다른 곳에 숨어 있다. 최근 세 가지 실제 사례를 엮어보면, 성능 설계에 대한 하나의 철학이 선명하게 떠오른다.
의존성 자체가 병목일 때
dev.to에 공개된 CalculatorKaro의 경량 임베드 위젯 구축 사례는 단순해 보이지만, 핵심을 정확히 찌른다. 계산기 하나를 만들기 위해 React나 jQuery를 끌어오는 순간, 그 도구가 해결하는 문제보다 만들어내는 문제가 더 많아진다. 추가 네트워크 요청, 글로벌 변수 충돌, WordPress 같은 CMS 환경에서의 번들러 호환성 이슈, 그리고 LCP·CLS 직격탄.
이 프로젝트가 선택한 해법은 단호하다. Vanilla JS + IIFE 패턴으로 스코프를 완전히 격리하고, 클래스 네임에 고유 프리픽스를 붙여 CSS 충돌을 원천 차단했다. 결과는 JS 실행 시간 100ms 미만, 렌더 블로킹 요청 제로. 빌드 스텝도 없다. <script> 태그 하나로 끝난다. Core Web Vitals 관점에서 보면 이보다 깔끔한 구조를 짜기 어렵다.
여기서 진짜 통찰은 기술 선택 이전에 있다. "이 문제에 프레임워크가 정말 필요한가?"라는 질문을 먼저 던졌다는 것. 단일 목적 위젯에서 의존성은 기능이 아니라 리스크다. 프레임워크가 주는 DX의 90%는 Vanilla JS의 규율 있는 구조로도 충분히 대체된다.
코드가 느린 게 아니라, 일을 너무 많이 할 때
같은 dev.to에 올라온 Gem Price Estimator 성능 디버깅 기록은 또 다른 유형의 병목을 보여준다. 앱은 정확히 동작했다. UI도 깔끔했다. 그런데 뭔가 '느리게 느껴졌다'. 개발자는 먼저 데이터베이스를 의심했고, 네트워크를 뒤졌고, 브라우저 렌더링 파이프라인을 살폈다. 모두 무죄였다.
진짜 범인은 알고리즘 내부에 있었다. 사용자가 입력값 하나를 바꿀 때마다 전체 가격 계산 로직이 처음부터 재실행되고 있었다. 변경된 부분은 일부인데, 엔진은 매번 전체를 다시 계산했다. 규칙이 추가될수록 중복 연산이 기하급수적으로 쌓였고, 체감 성능은 서서히 무너졌다.
해결책은 코드를 '더 빠르게' 만드는 게 아니었다. '불필요한 일을 하지 않도록' 설계를 바꾸는 것이었다. 계산 순서를 재구성하고, 이미 처리된 결과를 재활용하는 방식으로 알고리즘 자체를 리팩토링했다. 결과값은 동일하게 유지된 채 효율만 올랐다. 이 사례가 던지는 메시지는 명확하다. 성능 최적화의 첫 번째 목표는 '더 빠른 코드'가 아니라 '덜 하는 코드'다.
API 문서와 실제 API 사이의 간극
dev.to의 또 다른 글은 조금 다른 각도에서 같은 진실을 건드린다. 실제 API 통합 경험담이다. 저자는 OAuth 인증을 뚫고 첫 번째 요청이 성공하는 순간 "이제 연결만 하면 된다"고 생각했다. 그 믿음은 오래가지 못했다.
어떤 API는 타임스탬프를 UTC로 반환하고, 어떤 건 계정의 로컬 타임존으로 내려온다. 데이터가 없을 때 빈 배열을 주는 곳이 있고, null을 주는 곳이 있고, 아예 필드 자체를 생략하는 곳도 있다. '어제 가입한 고객 수'라는 단순한 질문에도 플랫폼마다 '가입'의 정의가 다르다. 계정 생성인지, 이메일 인증인지, 첫 결제 완료인지.
이건 API 설계의 문제라기보다 통합을 대하는 태도의 문제다. 문서는 해피 패스만 보여준다. 실제 운영 환경은 엣지 케이스의 집합체다. 저자가 내린 결론은 단순하지만 묵직하다. 외부 API는 내가 통제할 수 없는 시스템이다. 첫 번째 성공 응답은 시작일 뿐, 진짜 통합 작업은 그 이후부터다.
세 사례가 가리키는 하나의 원칙
이 세 가지 이야기는 표면적으로 달라 보이지만 같은 곳을 향한다. 의존성 제거든, 알고리즘 재설계든, API 통합 현실이든—병목은 항상 '당신이 처음 의심한 곳'이 아닌 곳에 있다. 그래서 성능 설계의 첫 번째 원칙은 여전히 고전적이다. 측정 먼저, 최적화는 그 다음.
프론트엔드 개발자로서 이 원칙을 적용하는 방식은 구체적이어야 한다. 프레임워크를 선택하기 전에 그 위젯이 정말 프레임워크를 필요로 하는지 묻는 것, 최적화 전에 DevTools 프로파일러를 먼저 여는 것, API 통합을 시작할 때 문서가 아니라 실제 응답 구조를 먼저 탐색하는 것. 이 순서를 지키는 습관이 쌓이면, 병목이 예상 밖에 있어도 당황하지 않게 된다.
빠른 프로토타이핑과 검증이 중요한 시대일수록 이 감각은 더 중요해진다. AI 도구가 코드 생성 속도를 올려주더라도, 어디를 측정하고 무엇을 없애야 하는지를 판단하는 것은 여전히 사람의 몫이다. 성능은 코드의 속도가 아니라 설계의 질에서 결정된다.