
곧 3차 프로젝트가 시작된다...
프론트 둘이서 백 다섯명을 감당할 수 있을지 성현님이랑 벌써부터 떨고있다.. ㅋㅋㅋ
그래서 이것을 최대한 해결하기 위해 가장 중요한 것은 상태관리를 어떻게 할것이 제일 중요할 것이라 판단했다 (CSS도 같이!)
Redux, Zustands, Recoil, Jotai
Redux는 전역 상태 관리를 위한 매우 널리 사용되는 라이브러리로, React 애플리케이션에서 복잡한 상태를 체계적으로 관리할 수 있게 도와준다. Redux는 애플리케이션의 모든 상태를 하나의 스토어에 보관하고, 액션과 리듀서를 통해 상태를 업데이트하는 구조로 작동한다. 이 덕분에 상태 관리가 명확해지고, 애플리케이션이 커져도 일관성을 유지할 수 있다.
- 스토어: 애플리케이션 상태를 한 곳에서 보관하는 중앙 저장소다.
- 액션: 상태 변화를 유발하는 신호로, 상태를 어떻게 변경할지 정의하는 역할을 한다.
- 리듀서: 액션에 따라 상태를 어떻게 변화시킬지를 결정하는 순수 함수다.
- 디스패치: 액션을 리듀서로 전달해 상태를 업데이트하는 과정이다.
- 미들웨어: 비동기 작업 처리나 로깅 등 액션이 리듀서로 전달되기 전에 중간에서 추가 처리를 할 수 있는 기능이다.
상태의 중앙 집중화: 상태를 한 곳에서 관리함으로써 상태 흐름이 명확해지고, 여러 컴포넌트 간 상태 공유가 수월해진다.
디버깅 용이: 상태 변경 이력을 추적해 문제 발생 시 디버깅이 쉽다.
유연한 전역 상태 관리: 여러 컴포넌트에서 동일한 상태를 쉽게 접근하고 변경할 수 있다.
Redux는 강력한 상태 관리 도구지만, 학습하는 데 시간이 많이 걸리고 구현 과정이 복잡할 수 있다. 특히 Redux의 구조(액션, 리듀서, 스토어)를 완전히 이해하고 이를 프로젝트에 적용하려면 충분한 시간과 노력이 필요하다.
백5프2 프로젝트에서는 빠르게 상태 관리를 도입해야 했고, Redux를 배우고 적용하는 데 많은 시간이 필요했기 때문에 선택하지 않았다.
Recoil은 메타(구 Facebook)에서 개발한 React 애플리케이션을 위한 상태 관리 라이브러리로, Atom과 Selector라는 개념을 도입하여 상태를 세분화하고 효율적으로 관리할 수 있다. Atom은 상태의 최소 단위로, 여러 컴포넌트에서 공유하거나 독립적으로 사용할 수 있으며, 상태가 변경될 때 필요한 부분만 리렌더링 되도록 최적화된다. 이를 통해 불필요한 리렌더링을 줄이고, 성능을 크게 개선할 수 있다.
또한, Selector는 파생된 상태(derived state)를 관리하는 기능으로, Atom에서 생성된 상태를 기반으로 특정 데이터를 계산하거나 변형할 수 있다. Selector는 비동기 데이터도 처리할 수 있어 서버 상태나 외부 API와의 통합이 수월하다. 이런 구조 덕분에 Recoil은 복잡한 상태 관리가 필요한 대규모 애플리케이션에서도 유연하고 강력하게 작동한다.
특히 React와의 깊은 통합이 Recoil의 큰 장점으로, React의 컴포넌트 트리와 상태가 자연스럽게 연결되어 있어 React의 Concurrent Mode와도 호환된다. 이 덕분에 Recoil은 비동기 상태 관리가 필요한 상황에서도 효율적으로 동작할 수 있다.
최근 메타가 Recoil에 대한 적극적인 지원을 중단하고, 버전 업데이트도 이루어지지 않으면서 장기적인 관점에서 사용에 대한 위험성이 커졌다. 지속적인 업데이트와 버그 수정이 이루어지지 않으면, 프로젝트 유지보수와 확장성에 큰 문제가 발생할 수 있기 때문에 이러한 이유로 Recoil을 선택하지 않았다.
비록 Recoil의 Atom 개념은 매력적이었지만, 장기적인 안정성을 고려해 다른 상태 관리 라이브러리를 선택할 필요가 있었다.
Jotai는 간결하고 최소한의 보일러플레이트로 상태 관리를 할 수 있는 상태 관리 라이브러리다. Atom이라는 개념을 도입해 상태를 관리하는 방식에서 Recoil과 유사한 점이 있으며, 불필요한 렌더링을 줄이고 성능을 최적화할 수 있다는 장점이 있다. React Hook을 사용해 직관적으로 상태를 관리할 수 있어, 상태 관리의 복잡성을 크게 줄여준다.
Jotai는 가볍고 간단한 상태 관리 라이브러리지만, 커뮤니티와 생태계의 성숙도가 다른 상태 관리 라이브러리들에 비해 상대적으로 낮다. 프로젝트에서 문제가 발생하거나 확장 기능이 필요할 때, 이를 지원하는 리소스가 부족할 가능성이 있었다. 또한, 확장성과 대규모 상태 관리에 대한 검증이 충분하지 않다고 판단했기 때문에, 장기적인 안정성과 지원이 필요한 프로젝트에서는 Jotai를 선택하지 않았다.
Zustand를 선택한 이유는, 간결함과 성능 최적화 덕분에 상태 관리 시스템을 빠르고 효율적으로 구축할 수 있기 때문이다. Zustand는 Redux와 같은 복잡한 상태 관리 라이브러리와 비교할 때 보일러플레이트 코드가 거의 필요 없으며, 상태를 React Hooks 기반으로 관리할 수 있어 학습이 오래 안걸린다.
Zustand는 불필요한 렌더링을 최소화하는 구조로 설계되어 있다. 이는, 상태 변화가 발생했을 때 상태를 구독하고 있는 컴포넌트만 리렌더링 되도록 최적화하는 방식 덕분이다. 이를 통해 애플리케이션의 성능을 유지하면서도 상태 관리를 손쉽게 처리할 수 있다. 또한, Zustand는 모듈화된 상태 관리를 지원해 분리된 상태를 각각 관리할 수 있어, 하나의 커다란 전역 상태 트리에 의존하지 않고 더 유연한 상태 관리가 가능하다.
Zustand는 가벼운 구조 덕분에 개발 속도를 크게 향상시킬 수 있다. 불필요하게 복잡한 설정 과정이 없고, 상태 관리 로직을 간결하게 작성할 수 있어 개발 초기부터 신속한 구현이 가능하다. 이러한 장점은 특히 대규모 상태 관리가 필요하지 않은 프로젝트에서 빛을 발한다. 상태 관리의 복잡도가 낮고, 빠르게 변하는 요구 사항에 대응해야 하는 상황에서는 Zustand의 간결함이 더 큰 이점을 제공한다.
추가적으로, Zustand는 중간 규모 프로젝트에서도 충분한 확장성을 가지고 있어, 프로젝트가 커지더라도 복잡한 상태 관리로 인한 오버헤드를 최소화할 수 있다. 이를 통해 개발자는 상태 관리에 지나치게 얽매이지 않고, 더 중요한 비즈니스 로직과 기능 구현에 집중할 수 있다.
Redux로 해보고 싶었지만, 현재 많은 작업량을 소화해야 하는 상황과 NaverMapAPI 학습 및 상태 관리 통합까지 고려했을 때, 프로젝트의 시간이 짧다고 판단하여 Zustand를 선택한다. Redux는 강력한 상태 관리 도구지만, 학습 곡선이 높고, 이를 제대로 구현하는 데 시간이 필요하기 때문에, 신속한 상태 관리 도입이 요구되는 이번 프로젝트에서는 간결하고 빠른 구현이 가능한 Zustand가 더 적합하다고 판단한다.
Tailwind CSS는 빌드타임에 프로젝트의 설정 파일(tailwind.config.js)을 기반으로 CSS를 생성한다. 이 설정 파일에서는 사용할 색상, 폰트, 여백 등의 특성을 정의하며, 해당 특성에 맞춰 Tailwind CSS가 필요한 CSS 클래스를 생성한다.
Tailwind CSS는 프로덕션 환경에서 빌드할 때 "Purge CSS" 기능을 사용하여 사용되지 않는 CSS를 자동으로 제거한다. 이를 통해 빌드된 CSS 파일의 크기가 작아지고, 불필요한 스타일이 제거되어 페이지 로딩 속도를 향상시킬 수 있다.
Tailwind CSS가 빌드타임에 생성한 CSS 파일은 런타임에 웹 애플리케이션에 로드되어 사용된다. 개발자는 HTML 또는 프레임워크 컴포넌트에서 Tailwind CSS의 클래스를 사용해 스타일을 적용할 수 있다.
Tailwind CSS는 동적으로 클래스를 추가할 수 있는 기능을 제공한다. 예를 들어, hover:나 focus:와 같은 접두사를 사용해 마우스 오버나 포커스 상태일 때 스타일을 변경할 수 있다.
빌드타임과 런타임에서의 Tailwind CSS의 역할은 각각 설정 파일을 기반으로 CSS를 생성하고, 이를 웹 애플리케이션에 로드하여 사용하는 것이다. 이 방식은 Tailwind CSS가 사용자의 설정에 맞춰 사용자 정의 스타일을 생성하고, 이를 런타임에 유연하게 적용할 수 있게 한다.
Vite는 서버 시작 시간이 CRA보다 매우 빠르다. 이는 Vite가 모듈을 요청할 때마다 동적으로 변환하는 방식이기 때문이다. 반면, CRA는 개발 서버를 시작할 때 모든 모듈을 한 번에 변환한다.
Vite는 개발 모드에서 ES 모듈을 사용해 브라우저가 직접 모듈을 로드하게 한다. 이를 통해 HMR(Hot Module Replacement)이 매우 빠르게 이루어진다. 반면, CRA는 Webpack을 사용해 모든 코드를 번들로 만든다.
CRA는 설정이 모두 미리 구성되어 있어 편리하지만, 사용자 정의 설정을 추가하려면 eject 과정이 필요하다. 반면, Vite는 사용자 정의 설정을 쉽게 추가할 수 있다.
Vite는 빌드 시 Rollup을 사용해 빠른 빌드를 제공한다. Rollup은 JavaScript 모듈 번들러로, 특히 라이브러리와 애플리케이션 번들링에 특화되어 있다. Vite는 개발 모드에서는 동적 모듈 변환을 제공하고, 빌드 시에는 Rollup을 사용해 최적화된 번들을 생성한다.
Rollup의 tree-shaking 기능은 사용되지 않는 코드를 제거하여 최종 번들 크기를 최소화하며, 이를 통해 로딩 시간을 단축시킨다. Vite는 Rollup을 사용함으로써 빌드 속도를 최적화하고, 개발 모드에서는 빠른 HMR을 제공한다.
Vite는 아직 Webpack이나 Parcel과 같은 기존 번들러들만큼 풍부한 플러그인 생태계를 갖추고 있지 않다. 따라서 특정 작업을 수행할 때 필요한 플러그인을 찾지 못할 수 있다.
Vite는 주로 클라이언트 측 렌더링에 중점을 두고 있으며, 서버 사이드 렌더링(SSR)과 같은 고급 기능 지원은 덜 발달되어 있을 수 있다. SSR을 사용하는 프로젝트에서 Vite를 도입할 때는 이 점을 고려해야 한다.
zustand는 context를 사용하지 않습니다. 모든 데이터를 state가 아닌 리액트 바깥에서 object로 관리하고 있기 때문에 Provider가 필요 없는 것입니다. react에서 값을 호출할때 넘기는 selector function을 listner로 등록해 놓았다가 setter가 호출되면 값을 업데이트하는 동시에 모든 listner를 실행, 값이 바뀌었다면 해당 위치에서 forceUpdate를 호출하여 리렌더를 발생시키는 프로세스입니다.