뒤로가기
지루한 기술을 선택하는 용기

June 23, 2020

frontendessay

2023년 가을, 새 프로젝트 킥오프 미팅이 있었다. 기존 서비스를 완전히 새로 만드는 거대한 리라이트 프로젝트. 프론트엔드 스택을 처음부터 다시 정할 수 있는, 개발자라면 누구나 설레는 그 순간이었다.

스택 논의 회의에서 한 동료가 말했다. "이번엔 Svelte로 가면 어때요? 번들 사이즈도 작고, DX도 React보다 훨씬 좋고, 벤치마크 보면 성능이 압도적이에요." 다른 동료가 거들었다. "Solid도 괜찮지 않아요? Signal 기반이라 렌더링 최적화가 기본으로 되고, React의 re-render 문제를 근본적으로 해결한 거잖아요." 회의실 분위기가 확 달아올랐다. 새로운 기술을 쓸 수 있다는 가능성에 다들 눈이 반짝였다.

그때 팀 리드가 조용히 물었다. "그럼 Svelte로 복잡한 폼 상태 관리할 때 라이브러리 뭐 쓸 건데? 서버 상태 캐싱은? 모노레포에서 빌드 파이프라인은 어떻게 잡을 건데?" 회의실이 조용해졌다.

이노베이션 토큰이라는 개념#

Dan McKinley라는 엔지니어가 있다. Etsy에서 일했던 사람인데, "Choose Boring Technology"라는 유명한 발표를 했다. 핵심 아이디어는 간단하다. 모든 회사, 모든 팀에는 이노베이션 토큰이라는 게 있고, 그건 대략 3개뿐이다.

이 토큰은 새롭고 검증되지 않은 기술을 도입할 때 쓰는 일종의 예산이다. 새 기술 하나를 도입할 때마다 토큰을 1개 쓴다. 왜 3개뿐이냐면, 새로운 기술은 문서화되지 않은 문제들, 즉 unknown unknowns를 갖고 있기 때문이다. 오래된 기술은 어디서 터질지 대충 알 수 있다. MySQL이 어떤 조건에서 느려지는지, React의 re-render가 언제 문제가 되는지는 Stack Overflow에 답이 있다. 근데 6개월 된 프레임워크의 프로덕션 이슈? 누구도 모른다. 직접 부딪혀야 한다.

그래서 토큰은 정말 비즈니스에 핵심적인 곳에 써야 한다. 기술 스택 선택 같은 인프라 레벨이 아니라, 제품의 차별점이 되는 곳에. McKinley의 표현을 빌리면, "경제를 재편하거나 인터넷 GDP를 올리는" 문제에 써야 한다.

우리 팀의 선택#

결국 우리는 React + Redux(정확히는 Redux Toolkit)를 선택했다. 2023년에 Redux라니, 올드하다고 느낄 수 있다. Zustand, Jotai, Recoil 같은 모던한 상태 관리 라이브러리가 넘쳐나는 시대에. 근데 이유가 있었다.

첫째, 팀원 7명 전원이 React 경험이 있었다. Svelte 경험자는 0명이었고, Solid를 실무에서 써본 사람도 없었다. 팀 전원이 새로운 프레임워크를 배우면서 동시에 복잡한 비즈니스 로직을 구현한다? 그건 도박이다.

둘째, Redux Toolkit은 "지루하지만 예측 가능"했다. 모든 상태 변경이 액션으로 추적되고, DevTools로 타임 트래블 디버깅이 되고, 미들웨어로 사이드 이펙트를 관리하는 패턴이 수년간 검증되어 있었다. 코드가 좀 verbose할 수는 있어도, 새로 합류하는 주니어가 패턴을 파악하는 데 하루면 충분했다.

셋째, 생태계의 크기. React로 X를 어떻게 하나요? 라고 검색하면 답이 나온다. 공식 문서, 블로그, 강의, Stack Overflow 답변, 유료 강의까지. Svelte로 같은 질문을 하면? 답이 있긴 한데, 그 답이 현재 버전에서도 유효한지 확인하는 데 또 시간이 든다.

지루하지 않은 선택이 불러온 재앙#

이 결정을 내리기 1년 전 경험이 크게 작용했다. 2022년에 내부 어드민 툴을 만들 때 한 동료가 Remix를 강력 추천했다. 당시 Remix는 정말 핫했다. React Router를 만든 팀이 만들었고, nested routing과 loader 패턴이 혁명적이라는 평가가 넘쳤고, Kent C. Dodds가 열정적으로 밀고 있었다.

우리는 도입했다. 처음 2주는 정말 좋았다. loader에서 데이터를 가져오고, action에서 뮤테이션을 처리하고, 에러 바운더리가 자연스럽게 잡히는 그 느낌. "이게 웹 개발의 미래다"라고 진심으로 생각했다.

문제는 3주 차부터 시작됐다. 어드민 툴 특성상 복잡한 폼이 많았는데, 여러 단계에 걸친 폼 상태를 Remix의 철학대로 관리하려니 loader/action 패턴만으로는 부족했다. 클라이언트 사이드 상태와 서버 사이드 상태를 어떻게 조합할 것인지에 대해 명확한 가이드가 없었다. 공식 문서를 뒤지고, Discord를 탐색했지만, 비슷한 상황의 레퍼런스가 부족했다. 우리만의 패턴을 만들어야 했다.

그러다 6개월 뒤, Remix가 React Router에 합병된다는 발표가 나왔다. 방향 자체가 바뀐 거다. 우리가 학습하고 구축한 것들의 미래가 불투명해졌다. 결국 그 어드민 툴은 1년도 안 돼서 "레거시"가 됐다. 유지보수하는 사람이 "이건 도대체 왜 이렇게 되어 있는 거야?"라고 묻는 코드가 됐다.

매슬로의 욕구 위계와 기술 선택#

McKinley가 재밌는 비유를 했다. 매슬로의 욕구 위계처럼, 엔지니어링 팀에도 위계가 있다는 거다. 기본 욕구(안정적인 인프라, 예측 가능한 배포)가 충족되지 않으면, 상위 욕구(혁신적인 제품, 차별화된 UX)에 집중할 수 없다. 데이터베이스 선택 때문에 매주 회의하는 팀이 어떻게 제품 전략을 논의할 수 있을까.

이걸 프론트엔드에 대입하면 이렇다. 빌드 시스템이 매일 깨지고, 상태 관리 패턴에 대해 팀원마다 의견이 다르고, 프레임워크 업데이트 때마다 breaking change가 터지는 팀은 — 정작 사용자 경험을 개선할 여유가 없다. 번들 사이즈를 최적화하고, 인터랙션을 개선하고, 접근성을 높이는 진짜 중요한 일을 할 시간이 인프라 소방에 다 빠지는 거다.

우리 팀이 React + Redux를 고른 뒤 실제로 벌어진 일이 이걸 증명한다. 스택에 대한 논쟁이 사라지니까, 에너지가 제품으로 갔다. 검색 UX를 완전히 새로 설계하는 데 2주를 집중할 수 있었다. 만약 Svelte를 학습하느라 그 2주를 썼다면, 검색 UX는 기존 패턴을 복붙하는 선에서 끝났을 거다. 이노베이션 토큰을 스택이 아니라 제품에 쓴 거다.

도구를 마스터하라#

사람들이 기술을 바꾸려는 시점이 있다. McKinley에 따르면, 모든 기술에는 "행복 곡선"이 있다. 처음에는 새롭고 신선해서 좋다. 그 다음 한계에 부딪히면서 불만이 생긴다. "이 프레임워크 왜 이래?"라는 불만이 최고조에 달하는 시점이 온다. 근데 그 골짜기를 지나면, 도구를 진짜로 이해하기 시작한다. 한계를 알고 있으니 우회할 수 있고, 패턴이 손에 익으니 생산성이 확 올라간다. 문제는, 대부분의 개발자가 골짜기에서 새 기술로 갈아탄다는 거다. 그러면 또 새 기술의 골짜기가 시작된다. 영원히 골짜기만 경험하는 셈이다.

React가 정확히 이런 케이스다. useEffect가 짜증나고, re-render 최적화가 귀찮고, 상태 관리가 복잡하다고 느끼는 시점이 온다. "Svelte면 이런 고민 안 해도 되는데..." 하는 생각이 든다. 근데 Svelte로 가면 거기엔 또 다른 골짜기가 있다. Svelte 5의 Runes가 기존 문법을 크게 바꿔서 생태계가 혼란스러운 시기, SvelteKit의 라우팅 관련 edge case, 대형 프로젝트에서의 상태 관리 패턴 부재 같은 것들.

지루함은 자신감이다#

Dan Abramov가 자신의 블로그에서 흥미로운 접근을 보여준다. React의 핵심 개발자였던 그가 강조하는 건 항상 "기본기"다. 새로운 API나 패턴보다, JavaScript 클로저가 어떻게 동작하는지, 컴포넌트의 생명주기를 정확히 이해하고 있는지, 사이드 이펙트를 왜 이렇게 다루는지 — 이런 근본적인 이해를 강조한다. 화려한 새 프레임워크보다, 지금 쓰고 있는 도구를 깊이 이해하는 게 먼저라는 뜻이다.

지루한 기술을 선택한다는 건, 자신감의 표현이다. "우리는 이미 검증된 도구로도 훌륭한 제품을 만들 수 있어"라는 선언이다. 반대로, 항상 새로운 기술을 쫓는 건 어쩌면 "기존 도구로는 한계가 있어"라는 불안의 표현일 수도 있다.

물론, 영원히 지루한 기술만 고수하라는 건 아니다. React도 한때는 "지루하지 않은 선택"이었다. 2015년에 jQuery 대신 React를 도입하는 건 분명히 이노베이션 토큰을 쓰는 결정이었다. 핵심은 의도적인 선택이다. "이게 새롭고 멋있으니까"가 아니라, "이 토큰을 여기에 쓰는 것이 우리 팀과 제품에 가장 큰 가치를 줄 것인가"라는 질문.

3개의 토큰을 어디에 쓸 것인가#

지금 프로젝트를 되돌아보면, 우리는 이노베이션 토큰을 이렇게 썼다.

토큰 1: 서버 상태 관리에 TanStack Query를 도입했다. 당시 팀에서 처음 쓰는 라이브러리였지만, API 캐싱과 동기화 문제를 근본적으로 해결해줬다. 학습 곡선이 있었지만, 쓸 가치가 충분했다.

토큰 2: 모노레포 구조를 Turborepo로 잡았다. 패키지 간 의존성 관리와 빌드 최적화가 필요했고, 이건 직접 스크립트를 짜서 해결하기엔 너무 복잡했다.

토큰 3: 디자인 시스템을 자체 구축하기로 했다. 이건 제품 차별화에 직접 기여하는 결정이었고, 기존 UI 라이브러리로는 요구사항을 맞출 수 없었다.

프레임워크(React)와 상태 관리 패턴(Redux Toolkit)은 토큰을 안 쓴 거다. "지루한" 선택이었지만, 덕분에 토큰을 진짜 필요한 곳에 집중할 수 있었다.

지루함의 역설#

아이러니한 건, 지루한 기술을 선택한 결과가 전혀 지루하지 않다는 거다. 스택 논쟁에 에너지를 안 쓰니까, 실제 제품 경험이 혁신적이 될 수 있었다. 사용자는 우리가 Svelte를 쓰든 React를 쓰든 신경 안 쓴다. 검색이 빠르고, 결제가 매끄럽고, 에러가 적은 걸 원할 뿐이다.

가끔 트위터에서 프레임워크 논쟁이 벌어지면 구경하면서 생각한다. 저 에너지를 제품에 쓰면 더 좋을 텐데. 근데 또 그런 논쟁 속에서 배우는 것도 있으니까 마냥 무의미하진 않다. 다만, 회사의 프로덕션 코드를 가지고 그 실험을 하지 않았으면 좋겠다.

McKinley의 말을 프론트엔드 버전으로 바꾸면 이렇다. "당신의 React 프로젝트가 지루해 보인다면, 그건 아마 제대로 하고 있다는 뜻이다."

지루한 기술을 선택하는 데는 용기가 필요하다. 회의에서 "우리 그냥 React 쓰죠"라고 말하는 건, "Svelte 써봅시다!"보다 훨씬 덜 흥미진진하다. 근데 그 지루한 선택이, 나중에 팀이 야근 안 하고 집에 가는 이유가 된다. 프로덕션에서 새벽 3시에 알림이 울리지 않는 이유가 된다. 그게 진짜 용기다.