2023 JavaScript Rising Stars
Risingstars
Zustand, 작고 빠르며 확장 가능한 상태 관리 솔루션으로, 간소화된 플럭스 원칙을 기반으로 함. 편리한 훅 기반 API를 가지고 있으며, 불필요한 코드나 리렌더링, 보일러 플레이트가 없음
Next.js 개발 시 자주 마주치는 Hydration 에러 이해하기
Next.js 환경에서 개발을 하다보면 Hydration에러를 종종 만나게 되는데요. 이 에러는 서버에서 생성된 HTML과 클라이언트에서 생성되는 HTML간에 불일치가 발생할때 발생합니다.
가령 useEffect내 API호출을 한다던지, 세션이나 쿠키 같은 요인에 따라 렌더링 컴포넌트가 다를때라던지, 자바스크립트 실행 타이밍이 다를때 이 에러를 접하게 되는데요.
이 Hydration에러는 왜 발생하는 것일까요??
근본적인 원인은 렌더링을 두 번 하기 때문입니다. 서버 사이드 렌더링 후, 클라이언트 사이드에서 추가 렌더링을 하면서 데이터의 불일치가 발생하는 것인데요.
그럼 왜 렌더링을 두 번 할까요? 언뜻 보기엔 두 번 렌더링이 비효율적인것 같아 보이는데요. 두 번 렌더링을 하게 되면 최초 초기 로딩 시 최소한의 정보만을 포함하고 있어 빠르게 렌더링이 가능합니다. 또한 검색엔진은 빠른 렌더링을 중요한 랭킹 요소로 고려하므로 SEO에도 유리 합니다. 초기 렌더링 이후에는 DOM 요소에 속성을 매칭 시키는 작업을 하는데요. 이 이벤트 리스너를 붙이는 작업은 페이지를 다시 그리지 않으므로 추가적인 렌더링 비용이 발생하지 않습니다.
따라서, Hydration은 효율적인 초기 페이지 로딩과 동적 웹 애플리케이션 기능의 균형을 맞추기 위한 과정 입니다. 다만 Hydration 에러는 개발 과정에서 다루기 까다로운 문제중 하나인데요. Next.js 에서도 에러를 줄이기 위한 방안을 지속적으로 모색하고 기술적인 접근을 제공하고 있습니다. 예를 들어 Zustand에서는 과거에 persist미들웨어를 사용할때 Hydration에러가 발생하였는데요 V3부터는 클라이언트 측에서 상태를 다시 로드하도록 하여 서버와 클라이언트 사이의 데이터 불일치 문제를 해결하였습니다.
Hydration 과정과 이로 인해 발생할 수 있는 에러를 제대로 관리하면, 사용자 경험을 향상시키고 웹사이트의 성능을 최적화할 수 있습니다.
2023 JavaScript Rising Stars 리뷰
2023년 JavaScript 생태계의 주요 동향을 조망하는 'JavaScript Rising Stars'가 발표되었습니다.
이 중에서 가장 두각을 나타낸 프로젝트는 React로 구현된 UI 구성요소 모음인 'shadcn/ui'인데요. 이 프로젝트의 특이점은 NPM 패키지 형태로 제공되지 않으며, 사용자가 직접 소스 코드를 복사하여 사용한다는 점입니다. 'shadcn/ui'는 Tailwind CSS와의 호환성, React 서버 구성요소 지원, 우수한 문서화로 인기를 얻었습니다.
다만 Tailwind CSS가 많이 사용되지 않는 우리나라에서는 이 라이브러리가 향후에 인기를 얻을수 있을지는 모르겠네요.
또한, JavaScript 및 TypeScript 애플리케이션용 빠른 올인원 툴킷 'Bun', 새롭게 부상한 CSS-in-JS 라이브러리 'StyleX', 상태 관리 분야에서 'Zustand'가 주목을 받았습니다. 특히 'Zustand'는 기존의 Redux를 대체할 가능성에 대한 기대를 모으고 있는데요.
기존 Redux의 장점인 DevTools를 사용할수 있으면서도 보일러플레이트 코드가 상당히 적어서 대체되는건 아마도 시간문제일것 같습니다.
관심 있으신 분들은 사이트에 직접 방문해서 참고하시는것을 추천드립니다.
https://risingstars.js.org/2023/en#section-all
Zustand v5 릴리즈
2024년 10월 14일자로 Zustand v5가 출시되었습니다. 핵심 변경사항들만 정리해보았습니다.
번들 사이즈가 절반 이상으로 줄었습니다. (1.2kb -> 588b)
As-is (v4)
Minified: 3.1kb
Minified + Gzip 압축: 1.2kb
To-be (v5)
Minified: 1.2kb
Minified + Gzip 압축: 588b
React 최소 요구 버전이 React 18 버전으로 변경되었습니다.
TypeScript 최소 요구 버전이 4.5 버전으로 변경되었습니다.
use-sync-external-store
패키지가 피어 디펜던시로 변경되었습니다.
zustand/traditional
의 createWithEqualityFn
과 useStoreWithEqualityFn
을 사용하고 계셨다면 use-sync-external-store
패키지를 별도로 설치하셔야 합니다.
ES5 지원이 중단되었습니다.
Vite를 사용하시는 분들은 vite.config.ts
파일에서 build.target
옵션을 es2015
이상으로 설정하셨는지 확인해 주세요.
TypeScript 설정도 확인해 주세요. tsconfig.json
파일의 compilerOptions
에서 target
을 ES6
이상으로 설정해야 합니다.
v4 -> v5로 올리시는 분들은 아래 마이그레이션 가이드 링크를 참고해 주세요.
https://github.com/pmndrs/zustand/blob/main/docs/migrations/migrating-to-v5.md
맛있는 zustand와 재미있는 FE 상태관리
여러분들은 회사, 개인프로젝트로 어떤 상태관리 라이브러리를 사용하고 좋아하시나요?
저는 6개월 동안 프로젝트에서 zustand 라는 Front-End 상태관리 라이브러리를 사용해보았습니다.
여러분들의 경험을 가지고 라이브러리들을 비교하면서 읽어보시면 좋을 것 같습니다.
댓글로 다양한 의견 주시면 감사하겠습니다!!
https://hooninedev.com/240222/
nextjs app router
많이들 사용하시나요? 사용한다면 어느 조합으로 사용 하고 계신지 궁금합니다. 주로 궁금한거는 기존의 v13 or v14, 기존의 css-in-js 사용이 불가능한 상황에서 스타일링에는 무엇을 사용하는지, 별도의 데이터 패칭 라이브러리(swr, tanstack-query)와 전역상태도구(zustand, jotai)를 사용하는지. 음 기존 page router 쓰시던 분들은 프로덕션 레벨에서도 마이그레이션 해서 사용중인지도 궁금하네요
추가로 특정 조합에 장점이 있는지도 궁금합니다
감사합니다!
현재 react-query와 zustand를 같이 쓰면서 고민이 있습니다. 현재코드는 useQuery를 통해 데이터를 가져오고 그 데이터를 가공해서 zustand에 넣어놓고 데이터를 수정하거나 추가등의 변화가있을 때 useMutaion onSuccess -> queryClient.invalidateQueries를 통해 자동으로 갱신하게 로직을 작성했어요. 이렇게 작성하면 데이터를 수정하거나 추가등의 변화가있을 때 마다 최신데이터가 갱신되기는 하지만 서버에 재요청을 해야하는 단점이 있어서 useMutaion onSuccess -> queryClient.invalidateQueries를 통해 자동으로 갱신하는 부분을 zustand에 추가로 데이터를 넣어주고 새로고침할때만 useQuery로 데이터를 받아오는 방식으로 변경할려고 해요. 근데 이렇게되면 새로고침하지 않으면 다른사람이 갱신한 데이터는 가지고 있지 못하게 되요. 서버 요청횟수를 줄이는 것보다 최신데이터를 가지고 있는게 더 중요한가요? 제 지인은 유저는 사이트안에서 계속왔다갔다 거릴거라 대부분은 최신데이터를 즉각적으로 갱신시켜줄 필요가 없다고 하고 저도 이 말이 맞는거같은데 다른사람들은 어떻게 생각할지 궁금해서 질문드립니다..
안녕하세요! 휴학 중에 개인 프로젝트 한번 만들어봤습니다! 아직 감이 잘 안 잡히다보니 chatGPT에 꽤나 의존했던 것 같습니다. 폴더 구조와 ssr, csr 사용 부분에서 피드백을 받고자 합니다! 또, containers 폴더 안 create 폴더에 있는 RouteChangeListener.tsx를 사용하여 퀴즈를 만들거나 푸는 도중에 현재 페이지를 벗어나려는 움직임을 감지하면 alert 창이 나오도록 설정하였습니다. 제가 생각해봤을 때 페이지가 이동했다가 다시 돌아오는 부분이 비효율적이라고 생각이 들어서 미들웨어나 다른 방법을 통해 해결할 수 있는지 여쭤보고 싶습니다. 감사합니다! 프로젝트 설명 : 퀴즈를 만들고 풀 수 있는 웹페이지 만들어봤습니다! vercel로 배포하였고, PWA 사용하여 모바일에서도 다운로드 가능하게 했습니다! 웹 앱 둘다 가능하지만 웹으로 봐주시는 것을 권장드립니다~!! 프로젝트 기술 스택: Next.js, react-query, zustand, firebase 테스트 아이디: 123@naver.com 테스트 비밀번호: 123123 GitHub 주소 : https://github.com/kmj0973/donquiz Vercel 배포 주소 : https://donquiz.vercel.app/ 따끔한 피드백 주시면 감사드리겠습니다!! 감사합니다!!
프론트엔드 부트캠프 수강 중인 학생입니다. 현재 팀 프로젝트를 들어가기전에 상태관리 라이브러리를 활용해서 간단한 redux(CRUD), zustand(CRUD)까지 구현 해봤습니다. 질문1) 팀플젝을 장점인 많은 zustand로 하려고 했으나 취업 합격자들, 취업어플 정보들을 봤을때 redux와 recoil이 많더라구요. 그래서 저도 redux, recoil을 한정해서 플젝을 해야할까요? 질문2) zustand로 플젝해도 회사 자격요건에 회사에서 redux를 쓴다던가 redux경험 우대사항이 적혀 있다던가 하면 불이익이 있을까요?
아무거나 쓰셔도 됩니다. 추정컨대 부트캠프 프로젝트의 기술 수준에서 상태 관리 라이브러리에 대한 아주 깊은 이해가 필요한 영역까지 다루시지는 않으시겠죠? 그렇다면 그냥 잘 다루실 수 있는 거 다루시면 됩니다. 혹은 어차피 학습하는 단계니까 일부러라도 낯선 도구를 사용해보시는 것도 좋습니다. (프로젝트 데드라인에 대한 압박이 심하지 않다면 개인적으론 이걸 더 추천합니다.) 물론 지원하는 회사의 job description과 내가 익숙한 기술 일치한다면 당연히 어느 정도 메리트는 있습니다. 그런데 신입 레벨에서 redux냐 zustand냐가 크게 고려될 거 같지는 않습니다. 그보다 크리티컬한 요소가 훨씬 많으니까요. 다만 기술 선택에는 항상 근거가 필요합니다. 그 근거가 부실하면 아래와 같은 다양한 면접 질문에 제대로 답하지 못하게 되겠죠. - 왜 상태 관리 라이브러리를 썼나, 그냥 리액트 기능만으로 짜면 안되나 - 왜 많은 옵션들 중에서 zustand를 선택했냐 - zustand가 팀프로젝트를 진행하는데 장점이 많다고 했는데 어떤 점이 그러한가 - zustand를 좋아한다고 하셨는데 그럼 혹시 이런 이런 기능을 써보셨냐 혹은 zustand의 어떤 어떤 api의 작동 원리에 대해 설명해줄 수 있나
안녕하세요~! 최근에 프론트엔드를 배우게 되어서 여쭤봅니다.. react 를 사용하면서 props drilling 을 겪고, 복잡한 코드가 되어 가는 중입니다. 궁금한 점은 zustand를 전역 상태 관리 도구로 사용하고 있는데 zustand를 어떻게 사용해야 잘 사용하는 것 일까요? 렌더링을 조금 깔끔하게 하고 싶어서 문의드립니다. 상황에 따라 다르겠지만 zustand를 많이 써서 state를 store 형태로 보관해서 사용하는게 좋을까요? 전문가들의 고견 부탁드립니다.(_ _)
글의 항간이 느껴져서 zustand를 잘 사용하는 법보다는 store를 보다 더 잘 쓸 수 있는 방법에 대해서 말씀드리고 싶은데요. react는 한마디로 "중첩 스코프의 세계"라고 말할 수 있습니다. 보통 App이라는 스코프 아래에 Layout이라는 스코프가 있고, 그 스코프 아래에 다시 여러 Component 스코프가 켜켜이 쌓일 겁니다. 이런 중첩 구조에서는 동등한 서열 간의 스코프나 분기되어 서로 다른 곳으로 뻗어나간 스코프 사이에서 어떠한 값을 공유하려면 분기되기 전의 상위 스코프에 그 값이 놓여있어야 합니다. 그래야만 참조가 가능하죠. react의 초기 문서에는 이것을 두고 "끌어올리기"라는 표현을 썼습니다. zustand를 사용한다고 해서 이 구조를 바꿀 수 있는 것은 아닙니다. state 도구의 provider는 늘 App을 감싸는 것이 보통인데, 이는 분기 이전의 스코프가 필요하다는 구조적인 이슈는 바뀌지 않으니 끌어올리기를 극단적으로 맨꼭대기까지 한 결과입니다. 이렇듯 react의 구조를 바꾸지 못하고 편승함에도 store라는 스코프를 사용하는 이유는, 실질적인 구조는 바꾸기 때문입니다. store 이하의 모든 컴포넌트는 실질적으로는 중첩이 아닌 모두 평행 상태가 됩니다. App으로부터 30개 이상의 중첩을 거친 스코프에서나 App 바로 아래의 스코프나 모두 store와 직접 연결할 수 있고, 어느 단계의 스코프에서도 set과 get이 가능하고 그 값을 공유할 수 있습니다. 이로 인해서 각 스코프는 자신이 참조해야 할 값과 그 값을 변경시켜야 할 파이프라인만을 지니는, 자기 성격이 매우 강한 형태가 될 수 있습니다. 따라서 props 의존성이 대폭 줄어들죠. 이를 돌려말하면 의존성을 주입받는 것이 아니라 스코프 자신이 의존성을 결정하는 방식으로 가버린다는 의미입니다. 쉽게 말하면 용도가 뚜렷해서 다른 것으로 확장하거나 전환하기 어려워집니다. 그래서 사용하는 데에 있어 안배가 필요합니다. props 의존성을 가지고 있어야 하지만, 그걸 받아오기 위한 drilling의 정도가 심하다면 store를 사용하되 그 부모 컴포넌트가 값을 참조하여 내려주도록 조정하시고, props 의존성이 없어도 되고 특정 값을 오롯이 사용한다면 store와 직접 연결하도록 만드세요. 만약 store부터로 값을 참조하고, 그 값을 다루어야 하는 이벤트들이 얽혀있다면 state 계층을 분리해서 hook으로 만들어 view로부터 떼어내는 것도 한 방법입니다. store가 코드의 복잡성이나 불가분한 것들을 해결해주는 만능은 아니라는 점에 유의하시면 좋을 것 같습니다.
안녕하세오 zustand 사용 중 궁금한게 있어 글 쓰게 되었습니다 zustand는 이전 값과 변경된 값을 비교해서 true가 리턴되면 리렌더링이 일어나는 것으로 알고 있는데 값이 객체일때 acion으로 객체를 수정하게 되면 이전 값도 바뀐 값으로 콘솔에 찍힙니다. 원시값일땐 이전값과 변경한값이 잘 찍히는데 객체만 이러는 이유가 있을까요? 뭔가 놓치고 있다면 답변 주시면 감사하겠습니다.