React가 사실상 기본값이 된 뒤로 우리가 놓치게 된 플랫폼 기능과 다른 프레임워크들의 진화, 그리고 더 나은 대안들을 살펴본다.

많은 사람들처럼, 한때 내가 듣는 음악의 전부가 내 지역 라디오 방송국에서 틀어주는 것뿐이었던 시절이 있었다. (그래도 대략 30대 이상인 사람들 얘기지만. 아직 이 얘기가 낯설게 느껴진다면, 잠깐만 나와 함께 가보자.) 그때 나는 그걸로 만족했다. 그게 내가 필요한 전부인 것처럼 보였다.
돌이켜보면 나는 이렇게 생각했다: 좋은 것은 필연적으로 인기를 얻고—그러니 알 가치가 있는 것이라면 결국 저절로 내게도 찾아올 거라고, 순진하게 믿었다.
하지만 결국, 내 삶에 다른 음악이 뿌리를 내리기 시작했다. 새 친구들과 인터넷을 통해, 나는 새로운 아티스트들을 알게 되었고, 점점 더 내가 예전에 좋아했던 것들—혹은 적어도 좋아한다고 생각했던 것들—에서 멀어져 갔다.
그 새 음악은 달랐다. 한 주에는 푹 빠졌다가 다음 주에는 질려버리는 식이 아니었다. 끝없는 순환의 일부로 듣는 음악도 아니었다.
오히려 그 반대에 가까웠다. 들으면 들을수록, 더 좋아지고 더 감사하게 되는 음악이었다. 깊이가 있었다. 물론, 그 음악엔 내가 그전까지 즐기던 시끄럽게 찢어진 기타 톤도, 펀치라인처럼 떨어지는 가사도, 설탕 코팅 같은 멜로디도 없었다. 그런데 놀랍게도, 그게 somehow 더 좋게 만들었지, 더 나쁘게 만들지 않았다.
그때 나는 깨닫기 시작했다: 어쩌면 나는 내가 생각했던 만큼 만족하고 있지 않았을지도 모른다.
어쩌면 내 행복감은, 사실 무지 위에 세워져 있었을지도 모른다.
이 이야기가 음악이 아니더라도, 아마 어느 정도 공감할 수 있을 거라고 생각한다.
아마 예전엔 싫어하던 음식이나 음료가 지금은 최애가 되었을 수도 있다. 혹은 별 기대 없이 봤던 영화, 책, 게임, 팟캐스트, 인플루언서, 취미가 의외로 깊게 와닿았던 경험이 있을 수도 있다.
디테일은 중요하지 않다. 내가 말하고 싶은 건 이거다:
당신은 아마 ‘대중적인 기본값’의 주변부 너머에서, 정말 좋은 무언가를 발견해본 적이 있을 것이다.
프론트엔드판 잘난 척 힙스터처럼 들리고 싶진 않다. 그건 내 의도가 아니다. Olive Garden에서 Bud Lite 마시는 게 최고의 즐거움이라면: 좋다, 브레드스틱 좀 돌려줘.
하지만 내가 정말 하려는 말은 이거다: 당신이 알아차리지도 못한 채, 어떤 멋진 것을 스스로 차단하고 있을지도 모른다는 가능성을, 부드럽게 공유하고 싶다.
어쩌면 이런 개념—익숙한 경계 밖에서 더 나은 것을 찾는 일—이 도구와 워크플로우에도, 삶의 다른 영역만큼이나 그대로 적용될지도 모른다.
그리고 어쩌면—정말 어쩌면—지금의 만족감은, 적어도 조금은, 그저 무엇을 놓치고 있는지 모르기 때문에 생기는 것일지도 모른다.
나는 전에 React가 프론트엔드 프레임워크의 새로운 기본값이 되었고, React를 नियमित적으로 사용하는 대부분의 사람들이 React가 얼마나 뒤처졌는지 제대로 인지하지 못한다고 생각한다는 글을 쓴 적이 있다.
그리고 여기서부터 우리의 비유는 한계를 드러낸다.
만약 이게 순전히 개인 취향의 문제라면, 나는 당신이 무엇을 좋아하는지 두고 논쟁하는 글을 쓰거나, 마음을 바꾸려 드는 글을 절대 쓰지 않을 것이다. (적어도 이 나이엔.) 누가 신경 쓰겠나? 즐기면 그만이다.
하지만 음악이나 다른 주관적 즐길거리와 달리, 프론트엔드 도구 선택은 타인에게 경험적으로, 측정 가능한 영향을 준다.
그 결정에는 실제 책임이 따른다. 단지 우리가 무엇을 좋아하느냐의 문제가 아니다. 개발에서—적어도 완전히 나만을 위해 만드는 게 아니라면—우리의 즐거움은 부차적이고, 사용자 경험이 최우선이다.
도구를 사랑한다면 그건 멋진 일이다. 나도 그러길 바란다. 하지만 그건 잘해야 사이드 퀘스트고, 최악의 경우엔 해로운 산만함이 될 수도 있다. 개발자 경험(DX)이 사용자 경험(UX)을 앞서서는 안 된다.
그러니 허술한 은유를 쓴 점은 용서해 달라. 원한다면 평생 같은 음악만 들어도 된다. 나는 그걸 지지한다. 하지만 우리가 쓰는 도구에 대해서는, 기존 선호의 안락함을 넘어설 매우 타당하고 중요한 이유가 있다.
React가 동료들에 비해 뒤처졌다는 말이 당신에겐 새로울 수도 있다. 많은 사람들처럼, 당신은 여전히 React를 프론트엔드의 현대적 표준으로 여길지도 모른다. 그래서 제목의 목록으로 들어가기 전 마지막 섹션에서, 그 거품을 살짝 찔러보자.
Alex Russell, Mastodon에서 가져온 이 글이 내가 이 포스트를 쓰게 된 계기였다:
오늘 누가 나에게 IE 지원이 필요 없는 새 앱에서 React를 써야 할 이유가 있냐고 물었다.
단 하나의 이유도 떠올릴 수 없었다…
React가 얼마나 구식인지 정말 놀랍다.
Alex는 그 스레드에서 React가 웹 컴포넌트를 지원하지 않는 점을 언급한다. 그 기능은 수년 전부터 React에 눈에 띄게 빠져 있었다. 그리고 맞다, “로드맵에 있다.” 하지만 이 글을 쓰는 시점에서, 구현이나 출시 시점에 대한 확실한 약속은 없다.
반면, React의 동시대 거의 모든 것—React 대신 선택할 수 있는 어떤 프레임워크나 기술이든—은 이미 그 이야기를 출하했고, 프로덕션에서 쓰이고 있다.
웹 컴포넌트는 한 가지일 뿐이다. 하지만 “다른 건 다 이미 하고 있고/혹은 더 잘 하는 것들” 목록의 유일한 항목은 아니다. (아래에서 여러 개를 다룰 것이다.)
React는 프레임워크 게임에 일찍 뛰어들어 엄청난 이득을 봤다; 표준을 세웠다. 하지만 그 대가로 민첩성과 적응성에 큰 손해를 봤다. 2013년 즈음 시작된 이후 React가 내린 모든 결정은 기술 부채의 또 하나의 층이 되었고—새로 나온 동시대 경쟁자들은 그 제약을 받지 않는다.
React는 ‘08년의 제약을 위해 설계된 ‘13년 기술이다. 2023년의 React에는 혁신적인 것이 없고, 오히려 현대에 함수형-반응형 프론트엔드 프로그래밍을 얻는 가장 느린 방법이다…
React가 늙었고, 대부분의 사람들이 그 정도와 질을 잘 모른다고 내가 생각하는 이유. 그러니 위 인용을 다른 방식으로 말해보자(그리고 음악 도입부와 연결해보자):
React는 Taylor Swift 앨범 7장 전, John Mayer와 Jennifer Aniston이 아직 사귀던 세상을 위해 설계됐다.
(정확히는 Taylor Swift의 새 앨범 7장 전이다. Taylor’s Version 릴리스는 계산에도 안 넣은 거다.)
그러니 지난 몇 년 동안 세계가 온통 React였던 많은 개발자 중 한 명이라면, React를 너무 오래 써서 잊어버렸거나—아예 처음부터 몰랐던—것들이 있을지도 모른다.
현대 프론트엔드가 얼마나 빠르게 움직이는지에 비해, 우리는 React를 왕으로 만든 세계가 여러 면에서 더 이상 존재하지 않는다는 사실을 깨닫는 데 아주 느리다. (애초에 존재했는지도 의문이지만; 시작부터 Facebook의 문제 세트와 비슷한 것을 가진 조직은 많지 않았다.)
지난 10년 동안 브라우저는 JavaScript와 CSS 모두에서 새로운 기능 채택이 폭발적으로 늘었다. 기술과 사용자 기대는 진화했고, 현 도구 생태계는 당신이 생각하는 것보다 훨씬 더 많이 React를 넘어 반복 개선과 적응을 해왔다—레거시 소프트웨어가 할 수 없는 방식으로.
React를 “레거시 소프트웨어”라고 부르는 건 논란이 있을 수 있지만, 나는 공정하다고 생각한다; 비교적 복잡하고, 상대적으로 오래됐고, 규칙과 함정이 많고, 초보자들이 종종 두려워하며, 그 위에 세운 아키텍처적 결정들이 오래전부터 반복 개선을 가로막는 장애물이 되어 왔다.
여기까지 읽고도 내가 당신을 완전히 소외시키지 않았다면 (준-엘리트주의, 장황한 서문, 괄호 속 끼어들기의 과다 사용의 콤보로), 한동안 머리가 React 세계에만 있었던 당신이 놓쳤을지도 모르는 것들을 몇 가지 공유하고 싶다. 지금 플레이리스트에 있는 것보다 더 좋을지도 모르는 곡들을 소개해보고 싶어서다.
나는 다른 글에서도 이걸 언급했지만, 개발 프로젝트 도구 후보로 “검증되지 않은” 프레임워크 이름이 나올 때마다, 사람들이 가장 먼저 묻는 질문은 늘 이것인 것 같다: 생태계가 얼마나 크냐?
이 포스트의 전제를 읽는 순간, 당신도 그런 생각을 했을지도 모른다. React에서 다른 프레임워크로? 그게 충분히 큰가?
우리는 왜 생태계 크기에 집착할까?
물론 이 프레임워크가 갑자기 사라지거나, 몇 년 안에 유지보수가 멈추지 않을지 확신하고 싶다. 그건 아주 타당하다. 그리고 너무 새롭거나 검증되지 않은 것에 올인하진 않을 거다. 하지만 Vue, Svelte, Preact, Solid, Astro, 그리고 다른 것들 모두는 그 단계를 한참 지나, 지원도 탄탄하고 유지보수도 잘 되고 있다. 그러니 그 이유만은 분명 아니다.
그럼 무엇 이 걸림돌일까? 내 이론은 이거다:
우리는 패키지가 특정 프레임워크를 위해 만들어져야 한다고 학습돼 왔다.
그런 사고방식이 jQuery에서 시작됐다고 주장할 수도 있지만, 나는 React가 그것을 가속했다고 생각한다.
React에서는, 어떤 모듈/위젯/라이브러리가 필요할 때마다(캐러셀, 지도, 아코디언, 등등), React용 이어야 했다; 그냥 웹용이나 바닐라 JavaScript용은 안 됐다. React의 모든 규칙, 상태 처리, 컴포넌트 라이프사이클의 기묘함 때문에, React용으로 명시적으로 작성되지 않은 패키지/라이브러리는 아마 제대로 작동하지 않을 가능성이 컸다.
React는 우리에게 무엇이든 특정 프레임워크에 맞게 만들어져야 한다고 훈련시켰다. 하지만 그건 이제 그리 사실이 아니고, 애초에 그래야 할 이유도 별로 없었다.
특히 “그냥 JavaScript”라고 그렇게 자주 주장하는 프레임워크라면, 그래선 안 된다. _그냥 JavaScript_라면, _진짜 그냥 JavaScript_인 것들과는 _그냥 동작_해야 한다.
물론 다른 프론트엔드 프레임워크들도 상태와 아키텍처에 대한 자체 규칙과 관습이 있다. 그들 마당에서도 비유적으로 갈퀴를 밟을 수 있다. 그리고 Svelte나 Vue 등에서만 돌아가도록 특별히 만들어져야 하는 것들도 항상 있을 것이다.
하지만 결정적으로—이 점을 가능한 한 강하게 강조하고 싶다:
현대 프론트엔드 프레임워크 중, React만큼 플랫폼과 완강하게 비호환적인 것은 없다.
다른 현대 도구와 프레임워크로 개발한다면, 바닐라 JavaScript 패키지들이 문제 없이 잘 동작할 가능성이 훨씬 높다—그런 패키지는 _수천 개_나 된다. 렌더 사이클이나 다른 프레임워크 특유의 문제를 일으킬 가능성도 훨씬 낮다. 게다가 웹 컴포넌트를 쓸 선택지도 있다.
전용으로 맞춤 제작된 특수 패키지/라이브러리가 꼭 필요하지 않은 경우가 많다. 당신의 ‘그것’은 아마 이미 플랫폼과 잘 맞고, 그러면 이미 존재하는 다른 것들과도 자연스럽게 맞기 때문이다.
Preact Signals는 훌륭한 예다. Preact용으로 만들어졌지만, 어떤 프레임워크에서도, 심지어 바닐라 JavaScript에서도 임포트해서 쓸 수 있다. 웹 컴포넌트도 마찬가지로, 현대의 비-React 프레임워크 거의 어디서나 호환된다.
프레임워크가 부족한 부분은, 플랫폼이 이미 필요한 것을 제공하고 있을 가능성이 높다. (예를 들어 폼 제출. React에서 늘 골칫거리였는데, 이제는 양방향 데이터 바인딩과 브라우저가 제공하는 관습을 그대로 쓰면 훨씬 쉬워진다.)
그리고 최악의 경우에도, React에서보다 필요한 것을 직접 만들기가 아마 훨씬 더 쉬울 것이다. (useState를 다른 프레임워크의 버전과 비교해보면 금방 보일 것이다.)
보수적인 개발자들은 ‘새로운 것’을 단점으로 보곤 한다. 모든 면에서 철저히 검증되지 않은 무언가에 발을 담그는 것을 경계하기 때문이다. 하지만 새롭다는 건 _장점_이기도 하다. 기술 부채가 적고, 오래된 브라우저 지원을 걱정할 필요가 적으며—그리고 기존의 좋은 아이디어와 더 현대적인 브라우저 기능 위에서 더 멀리 반복 개선할 자유가 있기 때문이다.
Hooks는 class 컴포넌트를 대체하는 React의 가장 최신 진화다.
공은 공대로 인정하자: hooks는 프론트엔드 세계에서 거대한 전환점이었다. 애플리케이션에서 로직과 상태를 조합하는 방식 자체를 혁신했다. hooks는 분명 훌륭하고, 거의 모든 프레임워크가 상태 관리를 위한 hooks 비슷한 모델로 수렴했다.
하지만 React hooks는 더 이상 새롭지 않다. (사실 hooks가 들어간 안정판 React의 나이는 우리 아이와 거의 비슷하고, 그는 몇 주 뒤에 유치원 예비반을 시작한다.)
Hooks는 더 이상 경쟁 우위도, 눈에 띄는 기능도 아니다; 기준선이다. 이제는 그냥 우리가 하는 방식이다.
다른 모든 프레임워크는 hooks의 자체 구현을 갖고 있을 뿐 아니라, 특히: 그들 모두는 더 빠르거나, 더 똑똑하거나, 더 쓰기 쉽거나, 혹은 셋 다의 조합이다.
여기서 Preact Signals는 언급할 가치가 있고, Svelte의 말도 안 되게 단순한 스토어도 그렇다. Solid도 Signals를 갖고 있다. Vue 3의 composition API도(직접적으로 hooks에서 영감을 받았지만) React 구현 대비 몇 가지 핵심 장점이 있다.
Hooks는 훌륭한 패턴이고, React가 이를 대중화한 공은 인정받아 마땅하다. 하지만 거의 모든 다른 프레임워크가, 더 적은 규칙과 더 적은 보일러플레이트로 hooks를 더 잘 한다.
Signals라는 개념이 낯설다면: 거칠게 단순화해 말해, 반응형 상태의 다음 단계이자 더 나은 진화라고 생각해도 된다. re-render를 무엇이 유발하는지에 대한 기본값이 더 좋고, 전체 컴포넌트가 아니라 필요한 노드만 다시 렌더하게 해준다.
고백 하나: 나는 아직도 useMemo와 useCallback의 차이가 뭔지—그리고 언제 써야 하고 언제 쓰면 안 되는지—정확히 모르겠다. 그런데도 오늘 아침에 그 주제의 글을 여러 개를 문자 그대로 읽었다. (진짜다.)
두 번째 고백: useEffect의 dependency array에 무엇을 넣어야 하고 무엇을 넣지 말아야 하는지, 그리고 왜 그런지 여전히 직관적이지 않다. useEffect를 쓸 때마다, 린터가 좋아하는 형태가 되도록 코드를 15분쯤 리팩터링하는 느낌이다. 내가 99% 확신하기로는 괜찮은데도, 앱을 무한 심연으로 빨아들이는 일이 없을 텐데도 말이다.
React를 쓴다면 이 고백들에 공감할 가능성이 높다. 그리고 그 혼란과 모호함을 그냥 정상이라고 받아들였을지도 모른다. 하지만 그렇다면 이건 알아야 한다:
다른 프레임워크에서는 이런 종류의 렌더링 사이클 미시 관리를 수년 전부터 하지 않아도 된다.
요즘 프레임워크들은 이런 일을, 당신이 일일이 손잡고 설명하지 않아도 처리할 만큼 똑똑하다.
실제 필요가 없을 때 귀중한 리소스를 낭비하며 다시 렌더하지 않는다는 걸 이미 알고 있다. 필요 없는 것들을 계속 재평가하는 대신, 값만 업데이트할 만큼 충분히 지능적이다.
…물론 대부분의 경우에 한해서다. 완벽하진 않다. 하지만 React보다 기본값으로 무엇을 해야 하는지 더 잘 알고, 더 성능 좋게 수행한다.
다른 프레임워크에서도 최적화가 필요할 수는 있다. 완벽하진 않으니까. 하지만 그 시점은 React에서 이미 오래전에 필요했을 지점을 한참, 한참 지난 뒤다.
useEffect 버전을 무서워하지 않는다컴포넌트가 DOM에 들어올 때 뭔가를 하게 하고 싶을 때—그리고/또는 다른 데이터나 변수에 기반해 뭔가를 동적으로 재계산하고 싶을 때—대부분의 다른 프레임워크는 useEffect보다 더 나은 방법을 갖고 있다.
React 커뮤니티 내부에서도 useEffect는 악명 높은 위험 요소로 여겨지고, 아예 피하기도 한다. 그래서 여기서 내가 너무 길게 말할 필요는 없겠지만: 믿어달라. 어떤 비-React 프론트엔드 프레임워크에서도, 이렇게 정상적이고 유용한 기능을 쓰는 걸 사람들이 이토록 두려워하진 않는다. 그리고 그 어디에서도 이렇게 난해한 규칙들이 있진 않다.
컴포넌트가 마운트됐을 때 뭔가 하려다가 발등을 찍지 않으려고, 제3자 패키지를 들여다보는 일도 없다.
새(React보다 새로운) 프레임워크가 나올 때 사람들이 즉시 묻는 또 다른 질문이 있다: 스케일하나? 하지만 나는 그 질문이 조금 구식일 수 있다고 본다.
기억할 가치가 있다: React를 낳은 세계는 문제가 달랐다.
그 세계에서 대부분의 프론트엔드 UI는 바닐라 JavaScript로, 혹은 jQuery(또는 비슷한 대안)로 만들어졌다. 그리고 지금 우리가 알듯, 그런 방식은 일정 수준을 넘어서면 잘 스케일하지 않았다.
왜냐하면 상호작용하고 싶은 각 요소와 DOM 노드마다 셀렉터를 직접 써야 했고, 상태를 추적하고 동기화하는 수동 방식을 스스로 만들어야 했기 때문이다. 보통 DOM에 쓰고 DOM에서 읽는 방식이었는데, 지저분하고 오류가 나기 쉽고, 무엇보다 느렸다. (그때 virtual DOM이 등장했지만, 그것마저도 수년 전부터 꽤 철저히 구식이 됐다.)
그 시절엔 모듈식 코드를 쓰기가 어렵거나 사실상 불가능했고, JS 파일은 수백 줄에서 수천 줄까지 불어났다. 여러 사람이 같은 프로젝트를 작업하면, 서로의 코드를 재발명하거나 반복하거나 심지어 덮어쓰기도 했다(부분적으로는 코드가 공용 글로벌 네임스페이스에 들어가 충돌이 더 자주 났기 때문이다). 앱이 더 크고 복잡할수록(Facebook) 문제는 더 심각했다.
중요한 건 이거다: 프론트엔드에서 “스케일하냐?”의 기준선이 여기에서 나왔다. 앱이 기하급수적으로 커져도 합리적으로 유지보수 가능하냐?
프론트엔드 프레임워크가 스케일하지 못할까 봐 걱정하는 건 jQuery만큼이나 오래된 두려움이고, 현대 웹 개발을 기준으로 보면 그만큼 구식으로 봐야 한다.
React는 이 문제들 중 상당수를 해결했다, 맞다. 하지만 그게 현대 공학의 경이로움이라서라기보다, 상태를 관리하고 공유하는 좋은 방식, 데이터를 반응형으로 만드는 방식, 복잡성을 추상화하는 방식, 그리고 개발자들이 충돌/네임스페이스 충돌/덮어쓰기 없이 같은 프로그래밍 패턴을 공유하게 해주는 방식을 만들었기 때문이다.
React는 프론트엔드 스케일링의 최고의/유일한/심지어 _최초_의 해법이 아니었다; 같은 패러다임의 가능한 버전 중 하나일 뿐이다.
(그리고 그중에서도 가장 오래된 편이다.)
내가 어떻게 아냐고? 공개된 결과가 있는 벤치마크가 수없이 돌았고, React와 다른 모든 프론트엔드 프레임워크의 스케일 성능을 비교했다. (여기선 링크를 걸지 않겠다. 온라인에 쉽게 찾을 수 있다.) 그 결과들은 거의 모두, 프론트엔드 영역의 다른 선택지가 React만큼 잘 하거나 더 잘 한다는 것—그리고 많은 경우 훨씬 더 잘 한다는 것을 확인해준다.
여기서 말하는 스케일은 일반적 의미다; 복잡성이 최소로 유지되고, 앱 크기가 늘어날수록 선형으로 커지지 않도록 하는 것. 물론 Markdown 파일에서 정적 HTML을 만드는 것 같은 특수 작업에서는 어떤 프레임워크가 더 잘/못 스케일할 수도 있다.
몇 년 전만 해도, 서버 렌더링 콘텐츠(주로 Next JS를 통해)에 관해서는 React가 사실상 유일한 선택지였다. 사람들은 React가 클라이언트에서 SPA로 렌더되는 대신, 서버에서 HTML로 렌더될 수 있다는 아이디어에 당연히 흥분했다. 속도와 SEO 이점은 무시할 수 없었고, 초기엔 다른 프레임워크들이 따라잡는 데 시간이 좀 걸렸다.
하지만 이런 것들에서 흔한 주제이자, 이 글의 주제이기도 한데: 최초로 반복 개선을 시작한 것이 최선인 경우는 드물다.
SvelteKit은 아무것도 하지 않아도 기본으로 서버 렌더링되며, 렌더링 패턴에 대한 세밀한 제어를 제공한다. Vue의 메타 프레임워크인 Nuxt는 더 일찍 이 게임에 들어왔다(Next에서 분명히 영감을 받았다).
Deno의 프론트엔드 프레임워크인 Fresh는 당신이 “island”(클라이언트 렌더)로 지정한 부분을 제외하면 전부 서버 렌더링이다; 나머지는 정적 HTML로만 전송된다. Fresh는 Preact도 사용한다(다시 말하지만 React보다 더 빠르고, Signals라는 useState와 반응성 모델의 더 성능 좋고 더 인체공학적인 버전도 있다).
Astro는 서버 렌더링을 지원하고, 원하는 어떤 종류의 컴포넌트든 서버 렌더링하게 해준다. 다른 프레임워크 컴포넌트도 잘 렌더하며, 경우에 따라 Next에서 큰 성능 업그레이드가 된다고 언급되기도 했다.
Solid의 메타 프레임워크인 SolidStart도 서버 렌더링을 갖고 있다. Qwik은 아예 그걸 중심으로 설계됐다. 더 오래된 프레임워크인 Ember나 Angular도 이 영역의 이야기가 있다. 다른 것도 빠뜨렸을 거다.
요점은: 예전엔 React가 서버에서 클라이언트 뷰 프레임워크 컴포넌트를 렌더하는 개념을 가진 소수의 프레임워크 중 하나였다. 하지만 이제 서버 렌더링은 기본 조건이다. 많은 새 프레임워크들은 서버에서 렌더링할 _옵션_만 있는 게 아니라, 기본값이 서버 렌더링이다.
PHP가 돌아왔다, 베이비.
혹은 이 섹션의 더 좋은 제목은 이거일지도 모른다: 폼은 원래 그렇게 어려운 게 아니다.
React가 Facebook이 만든 것이라는 점을 기억하는 건 중요하다. Facebook의 고유한 문제 세트를 해결하기 위해 만들어졌다.
React의 강한 신념 중 하나—데이터는 오직 한 방향(위에서 아래)으로만 흐른다—는 2010년대 초 Facebook의 엔지니어링 난제가 React 아키텍처를 얼마나 지워지지 않게 형성했는지 보여주는 좋은 예다.
한동안 단방향 데이터 흐름은 모범 사례로 여겨졌다. 하지만 요즘은 양방향 데이터 바인딩의 함정을 해결하는 방법들을 대부분 찾아냈고, 많은 경우 그게 오히려 훨씬 더 편리하다는 걸 알게 됐다.
React에서 폼을 다루는 일이 악명 높게 번거로운 이유는, 사용자의 키 입력 하나하나가 두 단계이기 때문이다: input에서 값을 가져오고; 그다음 상태를 그 값과 맞춘다(그 결과 input은, 이미 같은 값을 갖고 있었는데도 React state와 동기화됐다는 이유로 쓸데없이 다시 렌더된다). 보통 너무 빨라서 티가 안 나지만, 일이 많다.
이게 React에 폼 라이브러리가 넘쳐나는 이유다. React에서 폼을 만드는 건 프레임워크로 할 수 있는 일 중 악명 높게 가장 어렵다. 사실 나는, 폼 작업을 이렇게까지 유명하게 불편하게 만드는 다른 도구를 알지 못한다.
폼은 웹 플랫폼의 표준 기능이고, 이후에 나온 많은 프레임워크들은 플랫폼을 완강히 거스르기보다, 플랫폼을 신뢰하고 활용하기로 했다.
서버 쪽을 잠시 잊고 프론트엔드에서만 폼을 다룬다고 해도, Svelte나 Vue 등은 같은 데이터 바인딩/동기화 문제를 갖고 있지 않다. 양쪽에서 자동으로 업데이트되도록 상태를 바인딩하면 된다. 상태가 바뀌면 DOM이 업데이트되고; DOM이 바뀌면 상태가 업데이트된다.
이렇게 하면 여러 단계의 춤을 출 필요가 없다. 예를 들어 텍스트 박스의 값을 캡처하고 싶다면 양방향 데이터 바인딩을 한다. 그러면 사용자가 필드에 타이핑할 때 데이터가 자동으로 업데이트되고, 적절한 시점에 추가 단계 없이 언제든 가져다 쓸 수 있다. 그 사이에 값을 설정하거나 필드를 비우는 것도 간단한 한 줄이다.
양방향 데이터 바인딩은, 한쪽이 다른 쪽을 따라가고 있는지 계속 확인하지 않아도 데이터와 DOM을 동기화된 상태로 유지해준다.
이걸 쓰다가 문제를 겪을 수 있냐고? 물론이다. 하지만 나는, 모범 사례에 대한 교조적 이상이 도움이 되기보다 방해가 되는 경우를 그만큼이나 자주 본다. 단방향 데이터 흐름이 그 대표 예다.
React 위주로 일한다면, 프론트엔드 컴포넌트에서 스타일을 다루는 방식을 두세 번, 혹은 그 이상 바꿔본 경험이 있을 가능성이 높다.
JSX 컴포넌트에 .css 파일을 바로 임포트했을 수도 있고, CSS Modules, Styled Components, 그리고/또는 Tailwind를 썼을 수도 있다(대개 classnames나 tailwind-merge 패키지와 함께—어쩌면 둘 다에 Tailwind 애드온까지). 그리고 이것들은 그저 가장 대중적인 선택지들일 뿐이다.
Tailwind는 그 자체로 토끼굴이다(그리고 내가 그리 좋아하지 않는, 그 자체의 프론트엔드 프레임워크이기도 하다; 나는 그것이 단기 이득을 위해 플랫폼의 결을 거슬러, 결국 장기 손실로 누적된다고 본다). 하지만 어쨌든, 이런 스타일링 솔루션들이 존재하고 꽤 채택되는 이유 중 하나는 React가 존재한 내내 1st-party 스타일링 옵션이 사실상 공백이었기 때문이다.
다른 여러 프레임워크에서는 스타일링이 이미 해결된 문제라는 걸 당신이 모를 수도 있다.
특히 Vue와 Svelte는 둘 다 컴포넌트 스타일링 스토리를 갖고 있다. 둘 다 컴포넌트 레벨 스코핑이 있다(Vue는 opt-in, Svelte는 opt-out). 둘 다 바닐라 CSS와 훌륭하게 동작한다(그게 당신이 원하는 방식이라면). 하지만 그 둘—그리고 다른 모든 프론트엔드 프레임워크—도 여전히 CSS modules, Tailwind, Sass 등 원하는 무엇이든 호환된다.
하지만 가장 중요한 건: CSS의 ‘문제’라고들 하는 것들(당신이 그걸 문제라고 보든 말든)이 내장 스타일 처리로 완전히 다뤄진다는 점이다. 스코프 CSS가 가능한 거의 모든 문제를 해결하니, 다른 곳에서는 패키지와 설정이 그렇게까지 필요 없다.
진지하게 말해, CSS가 왜 나쁘다는 이유 목록을 읽어보라(참고로 CSS는 나쁘지 않지만, 못 하는 사람들이 그렇게 말하곤 한다). CSS에 대해 가질 수 있는 거의 모든 비판은 스코프 스타일링으로 해결된다. 그리고 여러 비-React 프레임워크는 그걸 이미 기본으로 갖고 있다.
나는 React로 주로 훈련된 개발자들이, React를 배우기 얼마나 어려웠는지를 떠올리며 다른 프레임워크의 학습 곡선도 비슷하게 평가한다고 추측한다. 그리고 그게 새로운 것을 시도하지 못하게 하는 요인의 일부일 것이다; 첫 번이 정말 어려웠으니까.
상태 관리, props, 중첩, 컴포넌트 라이프사이클, hooks, 그리고 물론 JSX 작성법…양이 많다. 가장 열렬한 React 팬조차도 초보자가 빠르게 익히기 쉬운 편은 아니라고 인정할 가능성이 높다. (아니라고 말하는 사람은 초보자였던 시절을 잊었을 확률이 크다.)
공감한다면 좋은 소식이 있다:
React만큼 배우기 어려운 도구는 더 이상 없다. 하지만 프레임워크 하나를 알고 나면, 나머지는 모두 엄청난 스타트를 끊은 거나 다름없다.
나는 이걸 두 번째 악기를 배우는 것에 비유한다(또 음악으로 연결하려고). 첫 번째로 연주를 배울 때는, 특정 악기뿐 아니라 _음악 자체의 모든 것_을 배우고, 원하는 소리를 내는 법까지 배운다. 하지만 두 번째 악기를 배울 때는 많은 것을 건너뛸 수 있다. 모든 개념이 익숙하다. 음악을 이해한다. 기존 지식과 근육 기억을 약간 다른 형태로 옮기기만 하면 된다.
프론트엔드도 비슷하다: 모든 프론트엔드 프레임워크에는 컴포넌트가 있고; 모두 TypeScript와 호환되며; props, children, 반응형 상태라는 개념이 있다. 우리는 이런 것들이 좋고 유용하다고 대체로 합의했다. 다만 구현에 대한 각자의 관점이 다를 뿐이다.
그리고 말이 나온 김에: React가 이런 아이디어들을 퍼뜨리는 데 큰 역할을 했다고 해도, React가 그 이상적 구현이라고 생각하는 건 어리석을 것이다.
좋은 것들은 반복 개선을 통해 만들어지고, 대체로 나중에 나온 다른 프론트엔드 선택지들은 React의 핵심 아이디어 위에서 반복 개선할 수 있는 명확한 이점을 갖고 있다.
즉 React는 main에서 한참 뒤처진 git 브랜치 같은 면이 있다. React가 당신 세계의 항성이라면 이를 깨닫기 어려울 수 있지만…프론트엔드는 이미 आगे로 갔다. 생태계는 그 아이디어들을 받아 더 나은 것을 만들었다.
지금 우리에겐 더 성능 좋고, 덜 복잡하고, 덜 배우기 어려운 선택지가 넘친다. 그리고 이미 React를 안다면, 그 중 어떤 것도 배우기 어렵지 않을 것이다.
Note
다음 두 섹션은 이 포스트의 원래 초안에는 없었고, 2023년 8월 15일에 원문 버전에 대한 피드백을 반영하기 위해 추가됐다.
이런 글을 논할 때 내가 자주 듣는 반응은 대략 이렇다:
저 멍청한 JavaScript 개발자들, 맨날 반짝이는 새 장난감만 쫓아다니지! 장기 유지보수는 신경도 안 써. 뜨거운 새 프레임워크는 내일이면 잊힐 거고, 그들의 코드는 아예 안 돌아갈 거야!
그 말엔 약간의 진실이 있다. 사실 JavaScript 개발자(감히 말해 프론트엔드 개발자 전반)는 다른 프로그래밍 분야보다 새것에 끌리는 면이 있어 보인다.
…하지만 정말 그럴까? 전 세계 모든 JS 개발자가 뭔가 새로 나오기만 하면 기술 스택을 통째로 갈아엎으러 뛰쳐나간다고 확신할 수 있을까? 아니면 끝없는 온라인 과대광고 사이클 때문에 그렇게 느껴질 뿐일까?
나는 실제보다 훨씬 더 사실처럼 보인다고 생각한다. 어떤 기술이든 얼리어답터는 주목을 받기 마련이고, 그들이 블로그 글과 영상을 만들며, 그것들이 공유되고 이야기되면서 실제보다 그런 행동이 훨씬 많은 것처럼 보이게 만든다. (만약 그게 절반만 사실이었어도, React의 점유율은 지금보다 훨씬 낮았을 것이다.)
내가 만난 대부분의 프론트엔드 개발자들은 다른 개발자들과 마찬가지로, 아는 것을 고수한다. 다만 우리에겐 새것을 조금 건드려보는 비용이 상대적으로 덜 들 뿐이고, 그래서 그렇게 하는 것뿐이다.
하지만 그건 요점이 아니다. 이런 관점은, 현장에서 이용 가능한 다른 선택지들의 성숙도를 과소평가한다.
Vue는 React만큼 오래됐고, 현재 버전(v3)은 거의 3년 전에 출시됐다. 현대적 Svelte는 React hooks가 나온 지 두 달 뒤에 출시됐다(React hooks가 두 달 전에도 새롭고 반짝이는 거라고 생각했나?), SvelteKit은 거의 1년 전에 1.0을 찍었다. Preact는 10 버전이다. Solid는 2년 넘게 1.0+였다. Astro는 1년 전에 1.0을 찍었다. 여기서 언급한 가장 새로운 항목인 Qwik과 Fresh도, 올해 초 기준으로 둘 다 1.0이다.
그러니 그중 _일부_가 당신에겐 아직 너무 새롭다면, 괜찮다. 이해한다. 하지만 React 대안을 ‘짧은 집중력’으로만 치부하는 건, 현장에서 제공되는 성숙함과 깊이를 오류로 덮어버리는 것이다.
여기서 너무 오래 말하진 않겠다. 이미 이 주제는 많이 다뤄졌고(내가 쓴 다른 글에도 조금 있고, 온라인에서 쉽게 더 찾을 수 있다). 하지만 요지는 이거다: React가 느린 경우, 그 차이가 무시할 만하게 보일 수도 있다(특히 최신/프리미엄 하드웨어와 빠른 인터넷을 쓰는 특권층이라면). 하지만 그 차이는 전혀 사소하지 않다.
React는 많은 경우 성능(여기서는 번들 크기와 실행 속도 모두)에서 2배 이상의 격차로 뒤처진다. (번들 자체는 10배 이상일 수도 있다.) 최신 JS web frameworks benchmark 실행 결과에 따르면 React의 평균 성능은 Solid보다 거의 50% 느리고, Vue보다 25% 느리고, Svelte보다 40% 느리고, Preact보다 35% 느리다. (이 테스트에서는 다른 프레임워크는 उपलब्ध하지 않았다.)
그 비교는 오직 React hooks만 사용한 것이었다; useTransition 훅도, Redux 같은 추가 라이브러리도 없었다.
다른 연구도 많다. 각 결과마다 수치는 조금 다를 수 있고, 언제나 뉘앙스도 있다. 하지만:
어떤 결과를 보더라도, React는 이후에 나온 거의 모든 것보다 더 크고 더 느릴 것이다.
경험적으로 말하자면: 나는 안드로이드에서 내가 채우는 폼이 React를 쓰는지 사용자로서 알 수 있다. 느림이 있다. DOM을 state에 맞추고 state를 DOM에 맞추는 업데이트 루프의 느림은, React가 아니면 잘 느껴지지 않는다.
하지만 일화는 잊자; 데이터가 있다. 그리고 그 숫자들이 크게 안 들릴 수도 있고, 기술 스택 선택에는 성능 외에도 고려할 게 많다. “상황에 따라 다르다.”
하지만 25–50% 개선은 성능 향상으로서 엄청난 수치라는 걸 인정하자. 사용자에게 프론트엔드를 최대 두 배 빠르게 로드하게 하는 것은, ‘있으면 좋은’ 수준의 한계선을 훨씬 넘어선다. 스케일에서 거대한 차이를 만드는 수치다.
웹사이트를 로딩하거나 작업이 끝나길 기다릴 때, 0.1초 단위가 얼마나 가치 있는지 보여주는 수많은 연구를 굳이 인용할 필요가 없길 바란다. 또 거대한 JavaScript 번들을 다운로드할 대역폭이 없거나, 페이지 변화마다 최대 두 배 오래 기다릴 컴퓨팅 파워가 없는 사용자를 고려하는 것이 얼마나 중요한지도 굳이 말하지 않아도 되길 바란다.
그 정도로 큰 로딩/처리 시간을 줄인 엔지니어라면, 이력서의 눈에 띄는 곳에 적는다. 큰 일이다.
React와 나머지 생태계의 성능 차이는 작은 게 아니라, 작아 보이게 만든 것이다.
아마 몇십 문단 전부터 궁금했을 것이다: React가 그렇게 구식이라면, 대안은 뭔가?
여기서 나는 몇 가지를 다루며, 각자의 사용 사례도 언급할 것이다. React의 문제 중 하나는 오랫동안 모두에게 모든 것이 되려 했다는 점이고, React 모양의 도구가 유용할 수는 있지만, 스위스 군용 칼 하나보다 두세 개의 다른 도구가 더 나을 수도 있다고 생각한다.
다만 들어가기 전에 두 가지 빠른 नोट:
나는 위에서 언급한 다른 현대 프레임워크들을 모두 포괄하기 위해, 여러 विकल्प들을 여기서 나열한다. 나는 누구도 이 모든 것을 알아야 한다거나—하물며 써야 한다고 기대하지 않는다. 하나만 고른다면 Svelte, 또는 아마 Vue를 고르면 된다. 어쨌든, 다 나열하는 건 철저함을 위한 것이다.
여기서 모든 옵션을 나열하진 않았다. 다른 것도 있다.
예를 들어 Ember와 Angular는 뺐다. 둘 다 React보다 오래됐고, 벤치마크에서 React보다 크게(혹은 아예) 뛰어나지 않은 경향이 있기 때문이다(미안, Mel).
또 Alpine이나 Petite Vue 같은 경량 옵션도 뺐다. 그것들은 React보다는 jQuery의 대체재에 가깝고, 프레임워크처럼 무거운 것이 필요 없을 때 빛나기 때문이다.
마지막으로, Eleventy 같은 이 범주 주변의 뛰어난 도구들도 뺐다. 그것은 프레임워크라기보다 순수 정적 사이트 생성기(SSG)에 가깝기 때문이다. (하지만 Gatsby를 쓰고 있다면 여전히 볼 가치가 있다.)
그럼에도: 여기 당신의 Discover Weekly.
2023년 졸업생 여러분: Svelte를 쓰세요.
미래를 위한 팁 하나만 드릴 수 있다면, 그건 Svelte일 겁니다.
농담은 제쳐두고: 이 목록에서 React 대신 하나만 추천해야 한다면, 나는 Svelte를 고를 것이다. 나는 오래전부터 “Svelte는 React인데 헛소리 없는 버전”이라고 말해왔고(2019년 트위터에서 처음 던졌던 말이다. RIP), 시간이 지날수록 그 말은 더 진실해졌다.
Svelte는 쓰기 즐겁도록 단순하고, (이미 React 세계에서 왔다면 특히) 배우기도 비교적 쉽고, 거의 모든 경우 훨씬 더 성능이 좋으며, React가 할 수 있는 것과 그 이상을 할 수 있다. 이 사이트와 요즘 내 모든 사이드 프로젝트는 SvelteKit로 쓰고 있다.
Svelte는 빠르다; 사용 가능한 옵션 중 가장 빠른 축에 든다. DX도 훌륭해서, 개발자 설문에서 가장 사랑받는 프레임워크 상위권에 자주 오른다.
Svelte는 가능한 한 웹 플랫폼에 가깝게 붙어 있으므로, 매우 강력하지만 개념은 대체로 익숙할 것이다. Svelte는 또한 트랜지션, easing, CSS 처리, 컴포넌트 스코프 스타일 등 여러 편의 기능을 기본으로 포함한다.
이러면 프레임워크 크기가 걱정될 수 있지만, Svelte의 차이는 이거다: JavaScript 런타임이 아니라 컴파일러다. 쓰지 않는 것은 빌드 시점에 제거되고, 코드는 아주 작은 바닐라 JavaScript 조각으로 트랜스파일된다. 그래서 Svelte 번들은 보통 React의 일부 크기에 불과하다.
프레임워크처럼 느끼고 동작하지만, Svelte는 본질적으로 HTML의 작고 우아한 상위집합이며, 즐겁게 단순한 문법을 갖고 있고, 빠르고 최소한의 번들로 컴파일된다.
Svelte의 메타 프레임워크인 SvelteKit은 다재다능하고 강력하며, 정적, 서버 렌더링, 엣지 배포, 라우트별 혼합까지 가능하다. 2022년 말에 1.0을 찍었고, 프로덕션에 충분히 준비됐다. (Next.js도 만드는 Vercel이 지원하기도 한다.)
위 이유들로, (내가 보기엔) 가장 전반적으로 뛰어난 선택지와 함께 프론트엔드의 즐거움을 다시 찾고 싶다면.
React로 하던 모든 것. Svelte는 React 자체를 대체할 수 있고, SvelteKit은 Next, Gatsby, Remix를 대체할 만큼 다재다능하다(혹은 동시에 전부).
Vue는 React에 가장 가까운 선택지일 수 있고, 아마 두 번째로 큰 생태계를 가졌을 가능성이 높다. 하지만 성능은 React보다 유의미하게 좋고, UI에 조금 더 초점이 맞춰져 있다.
어떤 면에서는, 특히 Vue 3에서 hooks 비슷한 접근이 생긴 지금, Vue는 React에서 가장 작은 점프다. 하지만 Vue는 JSX보다 기본 HTML에 가까운 템플릿 언어를 사용하므로, map과 삼항 연산자 같은 우회로에 기대지 않고도 템플릿 파일에서 조건문과 루프를 훨씬 쉽게 쓸 수 있다.
Vue에는 Next와 비슷한 메타 프레임워크인 Nuxt가 있고, 잘 유지보수되며 강력한 새 기능을 계속 추가하고 있다. Vue는 또한 React보다 배터리 포함(batteries-included) 성격이 조금 더 강해, 스코프 CSS 처리나 쉬운 트랜지션/애니메이션 같은 것들을 기본으로 제공한다.
커뮤니티 규모/프레임워크 인기 자체가 중요한 요소이고; React 비슷하지만 더 배터리 포함이거나 더 HTML 같은 것을 원하며; 대기업 소유가 아닌 독립적인 프레임워크를 선호한다면.
React 자체, 또는 Next로 하던 일을 Nuxt로 대체할 수 있다.
Solid는 내가 ‘React지만 더 나은 것’이라고 부를 만하다. 많은 경우 React와 거의(아니면 완전히) 똑같이 보이지만, Solid는 훨씬, 훨씬 더 성능이 좋다. 사실 가장 빠른 옵션 중 하나다.
Solid는 기본적으로 React에서 출발해, 복잡성, 성능 문제, 보일러플레이트를 없애도록 다시 설계했다. Solid에서는 Signals가 개념으로 등장해, 컴포넌트 렌더링과 라이프사이클 주변의 혼란과 함정 대부분을 제거한다. 2013년 이후 우리가 배운 모든 교훈 위에, 현대에 React를 다시 만든 것이 Solid라고 말해도 과언이 아닐지 모른다.
Solid는 자체 메타 프레임워크인 SolidStart도 제공하지만, 이 글을 쓰는 시점엔 베타다. 다만 Solid 자체는 충분히 성숙해서 사용하기에 무리가 없고, 인상적인 스폰서 갤러리를 자랑한다.
전반적으로 React(와 JSX)를 좋아하지만, 더 현대적이고 더 빠르고/또는 더 쉽길 바라며; 성능이 최우선이라면.
React와 React DOM. SolidStart는 언젠가 Next를 대체할 수 있을 가능성이 크지만, 이 글을 쓰는 시점엔 베타다.
Fresh는 Deno 위에 만들어진, islands 아키텍처를 가진 서버 렌더링 프론트엔드 프레임워크다. 이 목록의 대부분보다 조금 더 젊지만, 최소 JS·island 기반·엣지 실행 프레임워크로서 가능성이 크다. 게다가 Deno로 구동된다. 이는 서버 코드가 더 빠르고 더 안전하며 TypeScript 기본이고, 전통적인 Node 대비 Deno가 주는 다른 이점들(쉬운 1st-party linting, testing, 코드 포맷팅 설정 등)도 함께 온다는 뜻이다.
Fresh 컴포넌트는 응답 시점에 정적 렌더되어 JavaScript 없이 HTML로 제공되거나, “island”여서 클라이언트에서만 렌더된다. 필요에 따라 섞어 쓸 수 있다. Deno 위에서 실행되기 때문에, 전 세계 어디서든 어떤 디바이스에서도 가능한 한 빠르게 로드되는, 매우 빠른 동적 콘텐츠를 위한 문이 열린다.
Fresh는 Preact를 사용하므로 빠르다는 걸 알 수 있고, React에서 왔다면 배우기도 어렵지 않을 것이다. 그리고 다시 말하지만: Deno 위에서 만드는 경험은 정말 좋다.
클라우드에서 전 세계적으로 제공되는 서버 사이드 앱, 절대 최소한의 JavaScript 전송, 그리고/또는 최신 기술 위에서 구축하는 아이디어가 마음에 든다면.
React 진영에서 Fresh와 가장 가까운 건 아마 Remix일 것이다.
Astro는 차세대 고성능 정적 사이트 생성기이면서, 정적 그 이상을 한다. 이 목록에서 더 새로운 선택지 중 하나지만, 이미 매우 안정적인 1.0 릴리스에 도달했고 폭넓은 호평과 채택을 얻었다.
주로 새로운 세대의 SSG로 시작했지만(React 팬들: JSX와 MDX도 지원한다), Astro는 이제 동적 서버 사이드 기능도 갖췄다. Gatsby 같은 것보다, 그리고 콘텐츠가 많은/정적 사이트에 특히 추천한다.
진짜 킬러 기능은 이거다: Astro는 기본으로 JavaScript를 0으로 전송한다. 원하는 것만 opt-in 한다.
Astro는 또한 어떤 프론트엔드 프레임워크와도 호환되므로, React, Vue, Svelte 등으로 템플릿을 만들고 싶다면 그대로 할 수 있다.
대부분 정적이거나 콘텐츠/Markdown 기반 사이트를 만들고 있고(서버 렌더링이나 로직이 조금 필요할 수도 있지만); 최소 JavaScript를 전송하고 싶고; 선호하는 프론트엔드 프레임워크를 가져오고 싶다면.
Gatsby, 또는 비슷한 React 기반 콘텐츠 도구.
React 진영에 있다면 Preact는 이미 알고 있을 가능성이 크지만, 여기서도 언급할 가치가 있다. React의 훨씬 더 슬림하고 훨씬 더 빠른 버전이다. 원래는 거의 drop-in replacement로 시작했지만, 이제는 React에 없는 우수한 기능(이미 언급한 Signals 같은 것)을 얻기 시작했다.
본질적으로 React를 계속 쓰고 싶지만, 더 빠르길 원한다면.
React. (정말로, 그냥 앞에 P를 붙이는 거다. P는 performance의 P다. 전부 내가 지어낸 말이다; Preact 팀 탓 하지 말아라.)
Qwik는 React 같은 코드(JSX)를 서버 렌더링하면서, hydration과 성능에 대한 새로운 접근을 제공한다. 사실 이걸 “hydration”이라고 부르기도 애매하다. 대신 JavaScript를 DOM에 직렬화하고, 필요할 때만 아주 작은 조각으로 로드한다. Qwik은 이 목록에서 더 매니악한 선택지 중 하나지만, 아주 많은 인터랙티비티를 최대한 빠르게 돌려야 한다면 충분히 볼 가치가 있다.
브라우저로 많은 JavaScript를 보내고 있고, 그걸 더 성능 좋게 만드는 방법이 필요하다면.
React 자체(엣지에서 매우 효율적으로 실행되도록).
여기서는 깊게 들어가진 않겠다. 솔직히 나는 이 주제의 적임자가 아니다. 웹 컴포넌트 자체나 웹 컴포넌트 프레임워크에 대한 경험이 충분하지 않아 잘 말하기 어렵다.
그럼에도, 특정 종류의 프로젝트는 Lit, Stencil, Polymer 같은 웹 컴포넌트 프레임워크/라이브러리로 이득을 볼 수 있다. 특정 프론트엔드 프레임워크 안에서만 쓰이는 “독자적” 컴포넌트를 만드는 대신, 이런 라이브러리들은 실제 웹 컴포넌트를 작성하게 도와주고, 그것들은 어떤 웹 프로젝트로도 이식 가능하다.
내 의견으로는, 대부분의 프로젝트는 순수 웹 컴포넌트만 쓰기보다는 프론트엔드 프레임워크를 쓰는 편이(혹은 적어도 둘을 함께 쓰는 편이) 여전히 더 낫다. 미래에는 바뀔 수도 있겠지만, 지금은 순수 웹 컴포넌트 접근의 트레이드오프가 대부분의 경우 불리하다고 본다.
그래도 순수 웹 컴포넌트 기반 접근을 고려해야 하는 사용 사례는 분명 존재한다. 그리고 그런 프로젝트라면 React는 확실히 오버킬이다. 위에 언급한 웹 컴포넌트 라이브러리들이 훨씬 더 잘 맞을 것이다.
여러 환경에서 같은 컴포넌트를 재사용해야 하고; 프레임워크 변화에 대비해 미래 대비를 하고 싶고; 혹은 플랫폼을 선호하며 웹 컴포넌트 작성의 트레이드오프를 감수할 준비가 되어 있다면.
React. 다만 사용 사례에 따라 부분적으로만일 수도 있다.
이 글은 인정하건대, 작년에 쓴 글인 The self-fulfilling prophecy of React와 꽤 비슷하다. 비슷한 영역을 밟고, 비슷한 주장들을 한다(다만 새로운 방식이나 관점이길 바라지만).
반복하려고 한 건 아니지만, 분명 나는 이런 걸 많이 생각한다. 우연히도, 그 글이 प्रकाशित된 즈음 React를 풀타임으로 일하게 된 내 직업적 변화가 자극이 됐을 것이다.
나는 React의 인기가 적지 않은 부분에서, 사람들이 그 너머를 보지 않기 때문이라고 믿게 됐다. React는 최고는 아니지만, 대부분의 사람들은 최고를 찾지 않는다; 그저 충분히 좋은 것을 찾을 뿐이다. (우리는 인간이다. 우리의 결정에는 개인적, 감정적, 비이성적 이유가 많고, 그건 괜찮다. 우리는 바쁘다.)
프론트엔드 세계에서 우리는 기술을 선형으로 진보시키기보다, 도약으로 채택하는 것 같다. 사람들이 React 밴드왜건에 올라탄 원인 중 하나는, 당시 _모두_가 구식 기술에 묶여 있었고 더 나은 것을 찾고 있었기 때문이다. 우리는 작은 कदम으로 새것으로 나아가지 않았다(애초에 그게 옵션이 아니었을 수도 있다); 우리는 있던 자리에서 다음 것으로 거대한 _도약_을 했다.

하지만 문제는 이거다: 우리는 그 도약을 한 뒤로, 대체로 그 같은 자리에서 계속 앉아 있었다.
내 감으로는: 우리는 또 다른 도약에 가까워지고 있다.
그게 뭔지, 왜인지는 모르겠다. 하지만 나는 우리가, jQuery 시절에 그랬듯, React가 실제로 해결하지 못하는 문제들을 점점 더 느끼기 시작했다고 생각한다. 그리고 언젠가, आगे로 나아갈 때가 왔다는 것이 분명해질 것이다.
그 새것은 무엇일까? 모르겠다. 그냥 웹 플랫폼일 수도 있다. 어쩌면 프레임워크가 필요 없게 될지도 모른다. 더 위의 프레임워크일 수도 있고; 아직 보지 못한 무언가일 수도 있다. 심지어 _무언가_가 아닐 수도 있다; 도구의 다양성이 더 커지고, 하나의 단일 표준으로의 수렴이 줄어들 수도 있다(다만 위의 선택지들 중에서는 그게 가장 가능성이 낮아 보이긴 한다. 다시 말하지만: 인간은 바쁘고, 기본값을 좋아하는 작은 원숭이들이니까.)
하지만 나는, React와 그 ‘무언가’(무엇이든 간에) 사이의 격차가 시간이 지날수록 더 커질 거라고 생각한다.
그러니 매일매일은, 당신이 놓치고 있던 것을 탐험하기에 전날보다 더 좋은 날이다.
즐거운 감상 되시길.