-
Notifications
You must be signed in to change notification settings - Fork 1
기술스택 후보 및 의사 결정
다음 요소에 대해 의사결정하였다. 각 요구사항, 선택지, 선택의 근거는 후술한다.
- Language - TypeScript
- Package manager - ? ex )Yarn Berry
- Framework - React.js
- State management - Recoil
- HTTP client - React Query
- Styling - Tailwindcss
- Testing(고민중) - Storybook(UI), Jest(JS), Cypress(E2E)
- CI/CD - github action
- Etc - openAI api
- node - v.20.12
- JavaScript
- TypeScript
TypeScript를 사용한다. 이유는,
- Type hint 를 통해 구조적으로(=프로그래머가 주의집중을 조금 덜해도 시스템을 통해) 코드 오류를 방지할 수 있다.
- Interface 를 통해 다른 프로그래머의 의도를 더 잘 읽어낼 수 있다. 다시 말해, 코드로 말할 수 있다.
- npm
- npx
- yarn
- yarn berry
Yarn Berry를 사용한다. 이유는,
-
기존 프로젝트와의 호환성:
- 이미 기존 프로젝트가
node_modules
를 사용하고 있다면, 새로운 프로젝트도node_modules
를 사용함으로써 이전 프로젝트와의 호환성을 유지할 수 있다.
- 이미 기존 프로젝트가
-
커뮤니티와의 일관성:
- 프로젝트에서 일반적으로 사용되는 패턴이나 표준이 있다면, 그에 따라
node_modules
를 선택하는 것이 커뮤니티와의 일관성을 유지할 수 있다.
- 프로젝트에서 일반적으로 사용되는 패턴이나 표준이 있다면, 그에 따라
-
Build 도구와의 통합:
- 일부 프로젝트는 특정 빌드 도구와 통합되어있어서, 해당 도구의 기능을 사용하기 위해
node_modules
를 사용하는 경우가 있다.
- 일부 프로젝트는 특정 빌드 도구와 통합되어있어서, 해당 도구의 기능을 사용하기 위해
-
개발자의 선호도:
- 개발자 또는 팀의 선호도에 따라
node_modules
를 사용하는 경우가 있다. 일부 개발자는 Zero-Installs를 선호하지 않고, 명시적인 의존성 관리를 원할 수 있다.
- 개발자 또는 팀의 선호도에 따라
-
추가적인 설정 없이 바로 사용 가능:
-
node_modules
를 사용하면 추가적인 설정 없이 대부분의 프로젝트에서 즉시 사용할 수 있다. Zero-Installs를 사용할 경우 설정이나 사용법이 다소 복잡할 수 있다.
-
- Pure React
- Next.js
React.js 를 선택하겠다. 이유는,
-
심플리시티와 유연성:
- ReactJS는 직관적이고 유연하여 다양한 환경에 적합합니다.
-
환경 제약:
- VSCode 확장은 Electron 기반에서 실행되므로, NextJS의 서버 사이드 렌더링 같은 기능이 필요 없습니다.
-
개발자 경험과 생태계:
- React는 방대한 생태계를 가지고 있어 필요한 라이브러리와 도구를 쉽게 찾을 수 있습니다.
-
성능:
- VSCode 확장 기능에서는 React만으로도 충분한 성능을 낼 수 있습니다.
간단히 말해, VSCode 확장 개발에서 ReactJS를 선택하는 것은 그것이 더 단순하고, VSCode 확장 기능의 특성에 더 잘 맞으며, 필요한 도구와 라이브러리를 쉽게 활용할 수 있기 때문입니다.
- 사용성: 사용하기 쉬워야 한다. 어려워서 좋을게 뭔가?
- 디버깅: 디버깅이 쉬워야 한다. 어려우면 못 고친다.
Recoil & React-Query를 선택하겠다. 이유는,
- 작은 프로젝트 & 주로 데이터 fetching이 중심일 경우 React Query만 사용하는 것이 더 단순하고 관리하기 쉽지만 프로젝트 특성상 로컬 상태 관리가 중요한 부분을 차지하므로 Recoil을 추가하여 사용자 입력, UI 상태(모달 열기/닫기), 복잡한 상호작용등의 관리 시 상태 관리가 더 용이할 수 있도록 한다.
-
상태초기화: 코드가 더럽지 않았으면 한다. 아래와 같은 짓을 하고 싶지 않다.
const points = useSelector(state => state.points) useEffect(() => { if(points){ return } fetch('/api/points').then(data => { store.dispatch({type: 'INIT', data}) }) }, [])
-
캐싱: Request 최소화.
-
폴링: 자동적, 주기적으로 동기화.
-
에러: 전역 에러 핸들링이 가능해야 한다.
-
성능: GC 지원해주면 좋다.
-
디버깅: 좋은 디버거가 있어야 한다.
- React Query
- SWR
우선 두 도구 모두 훌륭하며, 아래 작업은 기본적으로 수행한다.
Query, Caching, Polling, Parallel Queries, Initial Data, Window focus re-fetching, Network status re-fetching.
차이점을 기준으로 React-Query를 사용하겠다. 이유는,
- 디버깅: SWR은 공식 디버거가 없고, React Query는 있다.
- 성능: SWR은 GC가 없고, React Query는 있다. 또한 시간을 cacheTime 통해 가비지 수집 시간 설정이 가능하다.
- 사용성: 사용하기 쉬워야 한다.
- 격리: CSS를 컴포넌트에 격리시킴으로써 모든 스타일을 기억할 필요가 없고, 상속 문제가 없어야 한다.
- 네임스페이스: 글로벌로 선언하지 않음으로써 BEM 같은 별도의 규칙이 없어야 한다.
- 상태 공유: JS의 상태값을 공유할 수 있어야 한다.
- 결정적 순서: 비결정적이면 CSS 로드 순서에 따라 우선순위가 달라진다. 이런 일이 없어야 한다.
- 성능: 빠르면 좋다.
- Styled-component
- CSS Module
- Tailwind CSS
Tailwind CSS를 사용하겠다. 이유는, 가장 핫해서,,,
1. 사용성
Tailwind CSS는 유틸리티-퍼스트 방식을 채택하여, 개발자가 HTML 내에서 직접 클래스를 적용함으로써 스타일을 빠르게 구현할 수 있게 합니다. 이 접근 방식은 높은 재사용성과 함께, 컴포넌트의 시각적인 요소를 직관적으로 이해하고 조정할 수 있게 해줍니다. 또한, Tailwind CSS의 문서화는 매우 잘 되어 있어, 새로운 개발자도 쉽게 학습하고 사용할 수 있습니다.
2. 격리
Tailwind CSS는 유틸리티 클래스를 통해 스타일을 적용함으로써, CSS가 특정 컴포넌트에만 적용되도록 합니다. 이는 스타일의 격리를 자연스럽게 달성하며, 다른 컴포넌트로의 스타일 상속 문제를 방지합니다.
3. 네임스페이스
Tailwind CSS는 글로벌 스타일 대신 유틸리티 클래스를 사용하기 때문에, BEM과 같은 별도의 네이밍 규칙을 필요로 하지 않습니다. 각 클래스는 기능별로 명확하게 분리되어 있어, 클래스 네임스페이스의 충돌을 방지합니다.
4. 상태 공유
Tailwind CSS는 JavaScript의 상태값과의 통합을 통해 동적인 스타일 변화를 손쉽게 처리할 수 있습니다. 예를 들어, React에서 Tailwind CSS 클래스를 조건부로 적용하여 컴포넌트의 상태에 따른 스타일 변경을 구현할 수 있습니다.
5. 결정적 순서
Tailwind CSS는 유틸리티 클래스를 사용하여 스타일을 적용하므로, CSS 로드 순서로 인한 우선순위 변화의 영향을 받지 않습니다. 클래스는 명시적으로 HTML에 적용되며, 결과적으로 스타일의 결정적 순서를 보장합니다.
6. 성능
Tailwind CSS는 PurgeCSS와 같은 도구와 통합되어, 최종 프로덕션 빌드에서 사용되지 않는 스타일을 자동으로 제거합니다. 이는 최종 CSS 파일의 크기를 최소화하며, 웹 애플리케이션의 로딩 시간과 성능을 개선합니다.
비즈니스로직 테스트를 위해 Jest