비어 있는 App.js와 깜빡이는 커서는 순수한 잠재력처럼 느껴집니다. 제약도 없고, 무엇을 해야 할지 지시하는 보일러플레이트도 없습니다. 하지만 그 빈 캔버스는 자유가 아닙니다. 그것은 우주를 처음부터 다시 구축하라는 공개적인 초대장입니다.
빈 화면의 세금
컴파일러와 텍스트 에디터만 가지고 프로젝트를 시작해 보세요. 첫날은 전율이 느껴집니다. 폴더 구조, 명명 규칙, 비활성화된 버튼의 정확한 회색 음영까지 직접 선택합니다. 하지만 3일째가 되면 그 설렘은 사라지고 진짜 작업이 시작됩니다.
단순한 리스트를 만드는 것이 단순히 map 함수를 작성하는 문제가 아니라는 것을 깨닫게 됩니다. 데이터가 로드되는 동안 스켈레톤(skeleton)이 어떤 모습일지, 맥동(pulse)할지 슬라이드할지, 그리고 나타나기 전까지의 지연 시간을 얼마나 길게 할지 결정해야 합니다. 스크롤 도중 네트워크가 끊기면 어떻게 해야 할지도 결정해야 합니다. 자동으로 재시도해야 할까요? 버튼을 보여줘야 할까요? 이전 페이지를 영원히 캐싱해야 할까요? 두 개의 활성 필터가 어떻게 상호작용할지, 그리고 그 조합의 결과가 없을 때의 빈 상태(empty state)는 어떤 모습일지도 결정해야 합니다. 심지어 사용자에게 '결과 없음'이 무엇을 의미하는지까지 결정해야 합니다.
이것들은 정형화(formalization)의 문제입니다. 모호한 개념을 구체적이고 일관되며 반복 가능한 동작으로 바꾸는 것이 소프트웨어 구축에서 가장 어려운 부분입니다. 코드는 그저 그러한 선택들을 기록한 것에 불과합니다. 무한한 커스터마이징이 기능이 아닌 이유가 바로 이것입니다. 그것은 세금이며, 그 청구서는 예상보다 빠르게 누적되는 미세한 결정(micro-decisions)의 형태로 도착합니다.
계속해서 비용을 치르게 하는 결정들
모든 아키텍처 선택을 구독 서비스처럼 대하십시오. 초기 구현을 작성할 때 첫 번째 할부금을 지불합니다. 그 후에는 매달 계속해서 지불하게 됩니다.
새로운 엔지니어가 합류하여 왜 표준 라이브러리 대신 커스텀 재시도 로직을 선택했는지 물었을 때, 아무도 기억하지 못한다면 비용을 치르는 것입니다. 브라우저 업데이트로 인해 직접 만든 터치 핸들러가 작동하지 않는데, 왜 임계값을 48픽셀로 설정했는지 문서화해 둔 사람이 없다면 비용을 치르는 것입니다. 보안 패치로 인해 맞춤형 인증 흐름을 리팩토링해야 하는데, 정작 리프레시 토큰 로테이션(refresh token rotation)을 고려하지 않았다면 비용을 치르는 것입니다.
아무것도 결정되어 있지 않다면, 모든 것이 당신의 문제가 됩니다. 원하는 것을 정확히 만들 수 있는 자유는 그것을 영원히 책임져야 한다는 부담과 떼려야 뗄 수 없습니다. 당신은 업계가 수년 전에 이미 해결한 패턴들에 대해 유일한 권위자가 되어야 합니다. 집을 짓는 대신 기초를 유지보수하는 데 시간을 허비하게 됩니다.
AI, 속도의 함정
인공지능은 이러한 역학 관계를 완화하기는커녕 더 위험하게 만듭니다. 거대 언어 모델(LLM)은 30초 만에 완전한 인증 모듈을 생성할 수 있습니다. 커피가 식기도 전에 상태 계층(state layer)을 구성하고, 캐싱 전략을 초안하며, 네비게이션 가드(navigation guards)를 작성할 수 있습니다.
하지만 함정이 있습니다. AI는 결정을 내리는 비용은 낮추지만, 그 결정을 책임지는 비용은 예전과 다름없이 높게 유지합니다. 이제 역사상 그 어떤 팀보다 빠르게 기술 부채를 쌓을 수 있습니다. 데모 날에는 코드가 잘 작동합니다. 스모크 테스트(smoke test)도 통과합니다. 하지만 6개월 후, OAuth 제공업체가 엔드포인트를 폐기하거나 느린 연결 중에 캐시 무효화(cache invalidation) 로직에서 레이스 컨디션(race condition)이 발생하면, 당신은 기계에 외주를 줬던 결정들을 디버깅하고 있어야 합니다.
숨겨진 청구서는 반드시 돌아옵니다. 그것은 엔지니어링 시간, 컨텍스트 스위칭, 그리고 서서히 저하되는 개발 속도로 지불됩니다.
지루한 것을 10년 단위로 구매하라
좋은 프레임워크나 플랫폼은 감옥이 아닙니다. 그것은 시간을 구매하는 것입니다.
거의 모든 현대적인 애플리케이션에서 표준인 것들을 생각해 보십시오. 사용자는 로그인해야 합니다. 데이터는 화면 사이를 이동해야 합니다. 인터페이스가 멈추지 않도록 원격 정보는 로컬에 저장되어야 합니다. 사람들은 맥락을 잃지 않고 탐색해야 합니다. 이것들은 차별화 요소가 아니라 범용적인 기능(commodities)입니다.
성숙한 프레임워크는 이러한 패턴을 한 번에 정형화합니다. 프레임워크는 다음을 결정합니다:
- 로딩 상태가 어떤 모습일지, 그리고 언제 나타날지
- 네트워크 오류가 인터페이스로 어떻게 전달될지
- 두 개의 네비게이션 파라미터나 활성 필터가 충돌할 때 어떻게 해결될지
- 기반 서비스가 업데이트될 때 로컬 데이터에 어떤 일이 일어날지
그런 다음 프레임워크는 당신이 잠든 사이에 동작을 문서화하고, 엣지 케이스를 테스트하며, 패치를 배포합니다. 당신은 진정으로 당신의 것인 마지막 10%에 에너지를 쏟을 수 있습니다. 참신한 상호작용. 구체적인 비즈니스
