2P by GN⁺ | ★ favorite | 댓글 1개

19.0.0 (2024년 12월 5일)

새로운 기능

React
  • Actions: startTransition은 이제 비동기 함수를 수용할 수 있음. 이 함수들은 "Actions"라 불리며, 상태를 백그라운드에서 업데이트하고 UI를 한 번에 커밋함. Actions는 비동기 요청과 같은 부작용을 수행할 수 있으며, Transition이 완료되기 전에 작업을 기다림.
  • useActionState: Transition 내에서 Actions를 정렬하고 상태에 접근할 수 있는 새로운 훅임. 초기 상태와 reducer를 받아들임.
  • useOptimistic: Transition이 진행 중일 때 상태를 업데이트하는 새로운 훅임. Transition이 완료되면 상태가 새로운 값으로 업데이트됨.
  • use: 렌더링 시 리소스를 읽을 수 있는 새로운 API임. Promise나 Context를 수용하며, Promise가 제공되면 값이 해결될 때까지 중단됨.
  • ref를 prop으로 사용: forwardRef가 필요 없이 ref를 prop으로 사용할 수 있음.
  • Suspense 형제 프리워밍: 컴포넌트가 중단되면 React는 가장 가까운 Suspense 경계의 대체를 즉시 커밋함.
React DOM 클라이언트
  • <form> action prop: Form Actions는 자동으로 폼을 관리하고 useFormStatus와 통합함. 성공 시 폼을 자동으로 재설정함.
  • 문서 메타데이터 지원: 문서 메타데이터 태그를 컴포넌트에서 네이티브로 렌더링할 수 있음.
  • 스타일시트 지원: Suspense 경계의 콘텐츠를 공개하기 전에 클라이언트의 <head>에 스타일시트를 삽입함.
  • 비동기 스크립트 지원: 컴포넌트 트리 어디에서나 비동기 스크립트를 렌더링할 수 있음.
React DOM 서버
  • prerenderprerenderToNodeStream API 추가: 정적 사이트 생성을 위한 API로, Node.js 스트림 및 웹 스트림과 같은 스트리밍 환경에서 작동하도록 설계됨.
React 서버 컴포넌트
  • RSC 기능: 지시문, 서버 컴포넌트, 서버 함수가 안정화됨. 서버 컴포넌트를 포함한 라이브러리는 이제 React 19를 피어 종속성으로 타겟팅할 수 있음.

폐기 예정

  • element.ref 접근: element.props.ref를 선호하여 element.ref 접근을 폐기함.
  • react-test-renderer: React 19에서는 react-test-renderer가 폐기 경고를 기록하며 웹 사용을 위해 동시 렌더링으로 전환됨.

주요 변경 사항

React
  • 새로운 JSX 변환 필수: 번들 크기를 개선하고 React를 가져오지 않고 JSX를 사용할 수 있도록 하는 새로운 JSX 변환이 필요함.
  • 렌더링 오류가 다시 던져지지 않음: 오류가 Error Boundary에 의해 잡히지 않으면 window.reportError에 보고됨.
  • propTypes 제거: propTypes 사용이 조용히 무시됨. TypeScript로 마이그레이션을 권장함.
  • 함수의 defaultProps 제거: ES6 기본 매개변수를 대신 사용할 수 있음.
  • 문자열 refs 제거: 문자열 refs 사용을 ref 콜백으로 마이그레이션해야 함.
React DOM
  • react-dom/test-utils 제거: actreact-dom/test-utils에서 react로 이동함. 다른 유틸리티는 제거됨.
  • ReactDOM.render, ReactDOM.hydrate 제거: 동시 렌더링을 위한 ReactDOM.createRootReactDOM.hydrateRoot로 대체됨.

주목할 만한 변경 사항

React
  • <Context>를 제공자로 사용: <Context.Provider> 대신 <Context>를 제공자로 렌더링할 수 있음.
  • 커스텀 엘리먼트 지원: React 19는 모든 커스텀 엘리먼트 테스트를 통과함.
  • StrictMode 변경 사항: useMemouseCallback은 첫 번째 렌더링의 메모이제이션 결과를 재사용함.
React DOM
  • 하이드레이션 오류에 대한 차이점: 불일치가 발생할 경우, React 19는 불일치된 콘텐츠의 차이점을 포함한 단일 오류를 기록함.

TypeScript 변경 사항

  • 암시적 반환 금지: refs는 이제 정리 함수만 수용함. 암시적 반환은 오류를 발생시킴.
  • useRef의 초기 인수 필요: 초기 인수는 이제 필수임.
  • 엄격한 ReactElement 타이핑: React 요소의 props는 이제 any 대신 unknown으로 기본 설정됨.

댓글과 토론

Hacker News 의견들
  • 여기서 왜 이렇게 많은 사람이 React를 싫어하는지 잘 모르겠음
    Laravel과 순수 JS로 커리어를 시작했는데, React를 써본 뒤로는 확장 가능한 앱을 만드는 게 현실적으로 느껴지고 프런트엔드도 재미있어졌음
    회사가 바뀌어도 React는 다시 잡기 쉽고, TypeScript 지원과 큰 생태계 덕분에 무엇이든 꽤 쉽게 만들고 키울 수 있다는 느낌임
    새 기능이 왜 사람들을 겁나게 하는지도 모르겠음. 여전히 SPA나 예전 방식으로 만들 수 있고, NoSQL DB나 Spring Boot, Kotlin이 나왔을 때도 쓰기 싫으면 안 쓰면 됐던 것과 비슷함
    Jetpack Compose와 SwiftUI도 React에서 영감을 받은 것으로 알고 있었는데, 예전에 Android 문서에서 본 것 같지만 지금은 못 찾겠음
    다만 아직 수십 년 경력은 아니라서, 예전 대규모 팀이 jQuery나 순수 JS로 Airbnb 같은 큰 웹앱을 만들 때 얼마나 즐거웠는지는 모름. 지금은 상태 관리, DOM 조작, 부수 효과를 순수 JS로 어떻게 풀지 상상하기도 어려워졌음
    언젠가는 나도 새 프레임워크를 불평하며 React가 좋았다고 말할지도 모름

    • React를 향한 반감은 보통 실제로 많이 써보지 않은 사람들에게서 나오는 것 같아 잘 이해가 안 됨
      대개 논리는 “프런트엔드는 늘 새롭고 반짝이는 것을 쫓고 React도 그중 하나”라는 식인데, React는 2013년부터 있었고 2015년쯤부터는 꽤 주류였음
      또 프레임워크와 라이브러리가 복잡도를 더한다고 하지만, 구체적으로 어떤 복잡도냐고 물으면 거의 답을 못 들음. 프레임워크 없이 의미 있는 앱을 만들면 결국 관리도, 테스트도, 문서화도 부족한 자체 프레임워크를 발명하게 됨
      컴파일과 번들링 단계도 자주 불평하지만, 이제는 Expo, Next.js, Meteor 같은 검증된 프레임워크가 있어서 webpack 설정이나 빌드 파이프라인을 직접 짤 이유가 거의 없음
    • 대부분의 웹사이트는 애초에 일 필요가 없음. 일부는 필요하지만, 그런 경우도 대개 맞춤 제작이 필요함
      모든 곳에 웹 프레임워크를 밀어 넣는 흐름은 지난 10년간 느리고 고장 잘 나는 사이트를 양산했고, 과도하게 설계됐는데도 2008년의 사용자 경험보다 크게 나아지지 않은 경우가 많았음
      어떤 프런트엔드 개발자에게는 질문이 무엇이든 답이 React / Node / Vite / Angular / Vue / Nuxt / Next / Bun / Deno / Svelte / SvelteKit 등의 조합이고, 가능하면 Kubernetes가 지배하는 수십 개 Docker 스웜 위에서 굴러가야 함. “이력서를 온라인에 올리고 싶다고? 그럼 앞으로 3주 동안 앱의 상태 흐름도를 그리자” 같은 식임
      React가 특히 더 욕먹는 건 프레임워크 유행을 좇는 사람들은 이미 다음 반짝이는 것으로 넘어갔고, 원래 이런 프레임워크를 싫어하던 사람들은 계속 싫어했기 때문에 이제 이 난장판을 방어할 사람이 남지 않았기 때문으로 보임. 나머지 프레임워크도 시간이 지나면 같은 운명을 맞을 것 같음
    • 클래스 시대의 React는 괜찮고 평범하고 지루하지만 유용한 UI 프레임워크였다고 봄. 반면 은 쓰기 매우 어려움
      실제 동작 방식이 많이 숨겨져 있고 직관적이지 않으며, 실수하기 쉽고 성능 낮은 UI도 쉽게 작성됨
      무엇이 몇 번 실행되는지, 의존성 배열에 무엇을 넣어야 하는지, useCallbackuseEffect에는 무엇을 넣어야 하는지 계속 생각해야 해서 인지 부하가 큼
      커뮤니티 일부는 프로젝트에 필요 없는 React 의존성까지 권장해 오버헤드와 복잡도만 늘리기도 함
      비즈니스 로직과 UI 로직이 섞이기도 쉬움
    • jQuery는 크고 복잡한 앱을 만들기 시작하면 심하게 무너졌음. 실제로 그 시기를 겪은 사람이 그때를 그리워하진 않을 것 같음
      한동안 SPA는 MPA에 비해 단점이 있었지만, 최신 웹 표준과 SPA 프레임워크의 서버 측 렌더링 도입으로 그 문제들은 지금은 거의 해결됐음
    • “NoSQL DB가 나왔을 때 아무도 불평하지 않았다”는 건 아님. 우리 중 많은 사람이 MongoDB가 얼마나 나쁜지 꽤 크게 불평했음
      https://www.youtube.com/watch?v=b2F-DItXtZs
  • 멋진 릴리스지만, 지금 프런트엔드 개발에 입문하는 사람은 좀 안됐다는 생각도 듦
    “Transition 안에서 Action을 정렬하고, action 상태와 pending 상태에 접근하는 새 hook이며, Action을 호출할 수 있는 reducer와 첫 렌더에 쓰는 초기 상태를 받고, form action prop에 넘겨질 경우 폼의 점진적 향상을 지원하기 위한 선택 문자열도 받는다” 같은 설명은 기능은 좋아 보여도 너무 장황함
    오늘 웹사이트 개발을 시작한다면 어디서부터 시작해야 할지 막막할 듯함
    그래도 React는 여전히 뛰어난 프레임워크이고 이번 릴리스도 개선임. 비판은 React만이 아니라 프런트엔드 개발 전반에 가까움

    • 팁을 주자면, 가능하다면 React를 아예 피하는 것부터 시작하겠음
      예전식 서버 측 렌더링에 HTMX 같은 것을 쓰면 훨씬 나음
      React 프런트엔드 개발로 4년간 돈을 벌었고 2005년에 첫 웹사이트를 만들었는데, 지금 한 클라이언트 프로젝트를 React에서 HTMX로 옮기는 중이고 훨씬 더 낫다고 느낌
      버그도 적고, 훅을 잘못 써서 생기는 함정도 적음
      클라이언트 측 렌더링이 필요하면 Solid나 Vue를 쓰겠지만 React는 피하겠음. 선택권이 없다면 행운을 빔
    • React는 흥미로운 접근이었지만 처음부터 무시된 위험 신호가 있었다고 봄
      단방향 바인딩, 가상 DOM, 재렌더링, 차이 계산이라는 기본 전제가 근본적으로 납득되지 않았음. 브라우저 메모리를 두 배로 쓰고, 모든 상호작용마다 전체 재렌더링과 차이 계산을 한다는 것임
      당시 답은 “먼저 안정적으로 만들고, 그다음 빠르게 만들자”였지만, 지금은 빠르게 만들기 위한 해킹성 구조가 가득하고 빠르지도 안정적이지도 않음
      정직한 양방향 바인딩 프레임워크는 최소한 빠름은 보장되고, 안정성은 경험에서 나온다고 봄. React는 그냥 혼란스러움. 첫 프런트엔드 입문이 React였던 엔지니어들은 배우는 것보다 지우고 다시 배우기가 훨씬 어려울 것 같아 안타까움
      VBScript, JS, jQuery, Mootools, Applets, ActionScript, YUI/Ext/Sencha, Backbone, Knockout, Angular 1, Angular 2, React, Vue 1까지 거쳐온 입장에서는 Flutter를 시도해보라고 말하고 싶음. 정말 신선함
      다만 Dart가 문제임. Flutter가 TypeScript였다면 이상향에 조금 더 가까웠을 텐데, Dart가 프런트엔드의 끝없는 churn 정신을 계속 살리고 있음
    • 오히려 반대로 느낌. 내가 React를 쓰기 시작했을 때는 몇 주마다 바뀌었고, 지금은 문서와 API가 훨씬 더 안정적이고 일관적임
      웹 표준도 전반적으로 어느 때보다 안정적임. 젊은 개발자들은 페이지를 여러 브라우저에서 제대로 보이게 하려고 수백 가지 레이아웃 꼼수를 배울 필요가 없고, 때로는 한 브라우저만 맞추기 위한 해킹도 덜 필요함
      JavaScript 피로감은 이해하지만, 지금은 배우기 가장 좋은 시기 중 하나라고 봄
    • 주로 저수준 코딩을 했고 웹 프런트엔드와의 접점은 대체로 싫어했는데, 몇 년 전 개인 프로젝트로 React를 잡아보고 크게 놀랐음
      전체가 실제 제대로 된 개발처럼 느껴졌고, 이전 상황과 비교하면 신선한 공기 같았음
    • 시작은 쉽다고 봄. 그 선택 기능을 쓰지 않으면 됨
      개발자의 99%라면 앱이 어느 정도 성장하기 전까지 그런 기능은 필요 없고, 끝까지 필요 없을 수도 있음. React가 강제하지도 않음
  • React 같은 클라이언트 측 프레임워크를 한때 좋아했지만, 결국 가능한 모든 곳에 복잡도를 더했다는 걸 깨달았음
    백엔드, 프런트엔드, DevOps 스택, 어디에나 복잡도가 들어갔고, 그 분산된 복잡도를 동기화하려고 더 많은 계층이 계속 추가될 것임

    • 작은 애플리케이션을 넘어가면 프런트엔드 프레임워크는 실제로 더 단순하게 만들어줌
      데이터나 모델이 바뀔 때 UI가 자동으로 다시 렌더링되는 건 올바른 방향임
      세부 방식은 논쟁할 수 있지만, 데이터가 바뀔 때마다 명령형으로 UI를 직접 바꾸는 방식은 코드베이스나 팀 규모 측면에서 오래 버티기 어려움
    • React는 웹 프런트엔드에서 거리를 두게 만든 이유였음
      웹브라우저가 원래 의도하지 않은 방식으로 박스를 렌더링하게 만들려고 엄청난 복잡도를 얹었고, 코딩 패러다임을 바꾼다는 명목으로 생산성과 도구 체계도 크게 잃었음
      멋진 아이디어와 구현은 있었지만 그만한 가치가 있었는지는 모르겠음. 일종의 직업 안정성 장치였던 걸까 싶기도 함
      ReactJS만의 문제는 아니고 JavaScript 생태계 전체가 라이브러리와 도구로 미쳐 돌아갔지만, React는 특히 시작하기가 짜증 나서 결국 합리적인 시간 안에 hello world 앱을 만들 수 있게 create react app이 나왔음
    • 벤처투자를 받은 소프트웨어 개발은 똑똑하고 재미도 원하는 사람들을 위한 복지 프로그램이라서 그렇다고 봄. 괜찮음
    • React를 좋아하지만, hooks가 나온 v16.8 이후 React의 변화는 기술 과시처럼 느껴짐
      클래스 컴포넌트 API를 훅으로 바꾼 이유를 이해하려는 기대를 멈췄음
    • 복잡도를 직접 추가한 것인지도 돌아볼 필요가 있음
      더 단순한 프레임워크를 선택할 수도 있고, 서버 오케스트레이션을 피할 수도 있음
      선택권이 없다면, 단순한 스택으로 효율 우위를 가질 수 있다고 믿는 프로젝트를 직접 시작해볼 수도 있음
  • 이번 릴리스에서 가장 좋은 부분 중 하나는 ref를 prop으로 쓸 수 있게 된 것임. 이제 forwardRef가 필요 없어짐

  • 블로그 글이 더 읽기 쉬움: https://react.dev/blog/2024/12/05/react-19

    • const error = await updateName(newName);에서 왜 updateName이 오류를 반환하는지 모르겠음
      JS/TS답게 그냥 Error를 던지면 안 되는 건가?
  • 지금까지 댓글 45개 중 “redux” 언급이 7번이라면, 여기서는 Recoil 계열을 대표해 Jotai를 언급하고 싶음. 아마 React 19에서도 별도 변경 없이 이미 동작할 가능성이 큼
    프런트엔드 복잡도가 충분히 커지면 다른 상태 관리 도구들이 필요 이상으로 방해가 되곤 함
    React를 싫어하게 됐지만 사실은 끝없는 action 상수 벽, prop 배관, 중첩 provider/context와의 싸움, pub-sub로의 도피에 지친 것이라면 Jotai 같은 것을 한번 써볼 만함

    • Jotai를 만든 팀은 ZustandValtio도 만들었음
      https://github.com/pmndrs/zustand
      https://github.com/pmndrs/valtio
      Jotai는 수동 보일러플레이트가 너무 많게 느껴지고, Valtio는 프록시 “마법”이 많아서 개인적으로는 좋아해도 팀에는 좋은 선택인지 확신이 안 듦
      Zustand는 보일러플레이트와 마법 사이의 중간에 있어서, 지금 진행 중인 큰 프로젝트에 선택했음
    • 상태 관리에 왜 그렇게 이상한 용어가 많은지 모르겠음
      몇 년 전 React 앱 작업을 시작했을 때 본 모든 상태 관리 패키지가 그런 용어로 가득했고, 지금도 여전함
      결국 그런 것에서 벗어나 일에 집중하려고 직접 해결책을 만들었고 [1], 운영 환경에서 잘 동작하고 있음. 비슷하게 동작하는 대중적인 선택지가 없어서 아쉬움
      [1] https://github.com/facepunch/react-class-model
    • Jotai npm 문서 페이지(https://www.npmjs.com/package/jotai)를 봐도, 여러 context provider나 Redux 사용에서 어떻게 벗어나게 해주는지 잘 와닿지 않음
      context hook의 좋은 점은 조합 가능하다는 것이고, 캐시된 쿼리와 결합하면 꽤 유지보수 가능한 패턴을 만들 수 있음
      Jotai가 여기서 어떤 실질적 개선을 제공하는지 궁금함
    • 큰 편인 프로젝트에서 Jotai를 써봤고 꽤 마음에 들었음
      다시는 redux나 sagas를 다루지 않기를 정말 바람
    • 모두 https://starfx.bower.sh를 시도해보면 좋겠음. 상태 관리와, 더 중요하게는 부수 효과 관리에 대한 새로운 접근임
  • 새로 도입된 기능 대부분은 마음에 들지 않음
    Actions와 useActionState / useOptimistic 훅은 큰 복잡도 함정처럼 보임. use 훅은 이름이 너무 정보가 없고, 컴포넌트 내부에서 만든 promise를 처리하지 않음
    분명 좋은 이유가 있겠지만, promise를 prop으로 넘기고 use 훅으로 처리하는 방식은 현재 우회책보다 더 많은 복잡도를 만들 것 같음
    Server Components도 꽤 복잡해 보이고, 아직 다룰 일이 없어서 다행임
    hydration 오류 메시지가 개선된 것은 환영할 만하고, provider로 쓰는 변경과 ref를 prop으로 쓰는 변경은 좋은 품질 개선임
    전반적으로 SPA를 만드는 용도라면 React/Preact를 좋아함. MUI 같은 기능 풍부한 컴포넌트 라이브러리와 Preact Signals 같은 단순한 상태 관리 해법을 함께 쓰면 SPA 제작은 꽤 직관적임
    다만 복잡도가 조금씩 기어들어오는 것이 걱정됨. 릴리스 노트의 새 훅 설명만 읽어도 인지 부하가 크게 느껴짐
    반면 React Compiler는 꼭 필요한 도구임. 프로그래머가 전형적인 최적화를 컴포넌트 내부에 직접 쓰지 않아도 되어 컴포넌트가 덜 복잡해질 것임
    릴리스와 Vite 등과의 통합을 기대하고 있고, 들은 바로는 Preact도 지원할 예정임

  • use API는 훅의 공통 접두사와 다른 이름으로 바꾸면 좋겠음
    React 훅에 새로 입문한 사람이 use는 조건부로 호출할 수 있지만 일반 hooks는 그럴 수 없다는 걸 보면 혼란스러울 것 같음

  • 병렬 Suspense 문제를 해결하려고 릴리스를 늦춘 건 정말 반가움
    아직 써보진 않았지만 기대가 크고, 전반적으로 훌륭한 릴리스임

  • 속보: custom elements를 완전히 지원함. 즉 Web Components임