도구는 능력이 아니라 마찰로 경쟁한다. AWS가 무료로 제공하던 데이터베이스 마이그레이션 평가 도구 DMS Fleet Advisor가 2026년 5월 조용히 퇴역했다. AWS의 공식 입장은 단 한 줄, "신중한 검토 끝에 지원을 종료하기로 결정했다"가 전부다. 하지만 이유는 문서 안에 이미 적혀 있었다. 이 도구를 쓰려면 로컬 에이전트 설치, S3 버킷 생성, IAM 역할 설정, CloudFormation 스택 보안 심의까지 통과해야 했다. dev.to의 AutoShiftOps가 지적했듯, 은행의 솔루션 아키텍트가 마이그레이션 타당성을 검토하려면 그 검토를 시작하기 위한 승인을 먼저 받아야 하는 6주짜리 조달 대화가 앞에 놓여 있었다.
결국 Fleet Advisor를 이긴 경쟁자는 다른 상용 도구가 아니었다. SSMS를 열고 저장 프로시저를 Ctrl+F로 직접 읽는 인간이었다. 수동 작업은 느리고 오류가 많고 확장이 안 된다. 그런데도 이겼다. 설정 시간이 0이었기 때문에. 이 사례는 도구 설계의 핵심 질문을 바꿔버린다. "가장 완전한 분석 결과를 만들 수 있는가"가 아니라, "지금 사용자가 이미 갖고 있는 것만으로 즉시 가치를 줄 수 있는가"가 진짜 질문이다.
같은 원리가 React 훅 설계에도 적용된다. useEffect는 마운트와 업데이트를 구분하지 않는다. 덕분에 페이지가 로드되는 순간 "설정이 저장되었습니다 ✅" 토스트가 뜨고, 아무도 건드리지 않은 폼이 자동 저장 POST를 날리며, 실제로는 컴포넌트가 처음 나타난 것뿐인데 analytics 이벤트에 "변경" 이 기록된다. 개발자들은 오랫동안 useRef로 마운트 여부를 체크하는 가드 코드를 매 이펙트마다 손으로 작성해왔다. 옳은 코드지만, 의도—"마운트는 건너뛰어라"—가 여섯 줄의 보일러플레이트 아래 묻힌다.
@reactuses/core의 useUpdateEffect는 그 의도에 이름을 붙인 것이다. 구현은 네 줄, 시그니처는 useEffect와 동일하다. 새로 배울 것이 없다는 게 핵심이다. 단, dev.to의 ChildrenTime이 검증한 한 가지 중요한 함정이 있다. React 18 StrictMode 개발 환경에서는 렌더 함수를 두 번 호출하기 때문에, 첫 번째 호출에서 이미 isFirstMount ref가 뒤집혀 두 번째 호출부터 가드가 무너진다. 결과적으로 개발 환경에서는 마운트 시점에도 이펙트가 실행된다. 프로덕션에서는 정확히 설계된 대로 동작하지만, 이 차이를 모르면 디버깅에 오후 한 나절을 날린다. 훅 하나의 추상화가 어디까지 책임지고 어디서부터는 사용자가 알아야 하는지를 명확히 문서화하는 것—그게 DX 설계의 마찰 지점이다.
세 번째 사례는 가장 직접적으로 "설계가 품질을 강제한다"는 명제를 구현한다. VS Code 테마 제작자 shadowbox는 한국 전통 단청 팔레트에서 영감을 받아 13개 앱용 컬러 테마를 만들면서, WCAG 명도대비 기준을 통과하지 못하면 빌드 자체가 실패하도록 파이프라인을 설계했다. --force 플래그는 없다. 명도대비가 실패한 테마는 "스타일이 다른 것"이 아니라 누군가에게 깨진 것이기 때문이다.
흥미로운 건 초기 게이트의 실패 스토리다. 첫 버전은 변형당 11개 색상을 하나의 배경색에만 대조 검사했고, "모두 통과"를 반환했다. 하지만 실제 배포된 테마에는 명도대비 1.83:1의 줄 번호와, 선택 영역 위에서 사라지는 1.9:1의 주석색이 있었다. 사이드바도 배경이고, 선택 영역도 배경이고, 입력 필드도 배경이다. 에디터 배경 하나만 아는 게이트는 한 픽셀만 보는 게이트다. AI 리뷰 에이전트를 자신의 프로덕트에 적대적 감사자로 투입해 기존 게이트가 놓친 19개 페어를 발견했고, 최종적으로 222개 페어를 전수 검사하는 구조로 확장했다. 게이트는 페어 목록만큼만 정직하다.
세 사례를 관통하는 설계 원칙은 하나다. 품질 기준을 리뷰 코멘트가 아니라 실행 경로 안에 박아 넣어라. Fleet Advisor는 가치 있는 기능을 갖추고도 설정 마찰 때문에 졌다. useEffect 가드는 옳은 패턴이지만 매번 손으로 써야 한다는 마찰이 변형과 버그를 낳는다. 단청 테마의 WCAG 게이트는 명도대비를 "나중에 검토할 코멘트"에서 "빌드를 막는 조건"으로 격상시켰다. 접근성이 선택지가 아니라 기본값이 되는 순간이다.
이 방향은 더 넓은 트렌드와 맞닿아 있다. React Compiler가 수동 memo 최적화를 컴파일러 레이어로 끌어내리고, ESLint와 TypeScript가 런타임 버그를 에디터 시점으로 앞당기듯, 좋은 도구는 지속적으로 "사용자가 실수를 저지를 수 있는 경로"를 좁히는 방향으로 진화한다. useUpdateEffect가 마운트 스킵을 네 줄로 캡슐화하고, WCAG 게이트가 222개 페어를 자동으로 검증하며, SPXray가 IAM 없이 SQL 파일만으로 즉시 분석을 시작하게 만드는 것—모두 같은 방향을 가리킨다. 마찰을 없애는 것이 아니라, 마찰이 발생하는 위치를 사용자의 워크플로우 밖으로 옮기는 것.
프론트엔드 개발자로서 지금 당장 적용할 수 있는 질문은 세 가지다. 첫째, 접근성 검사가 PR 코멘트로 끝나는가, 아니면 CI에서 빌드를 막는가. 둘째, 반복되는 useEffect 가드 패턴에 이름이 붙어 있는가. 셋째, 내가 만드는 도구에서 사용자가 첫 번째 가치를 경험하기까지 몇 단계가 필요한가. 그 단계를 하나씩 줄일 때마다, 도구는 조금 더 경쟁자를 이긴다.