1. 기술스택 확정
2. 스펙 세부 논의
3. 폴더구조 및 파일 구조
2. eslint, prettier
4. 브랜치 룰 , 리뷰 및 PR 컨벤션 정하기
rebase merge VS commit push merge
5. Zenhub 세팅
6. 와이어 프레임 작성
1. 기술 스택 선정
1. 스펙관련 Overview
✅ 1. 사용확정
React
,Typescript
,Axios
,EsLint + Prettier
,React-Router
,React-query + Recoil
,Storybook
,MaterialUI
✅ 2. 의논 필요
react-query + recoil
선호
VS contextAPI- MUI
Basic
- 아토믹 디자인 도입 여부
- common 컴포넌트 + domain단위 컴포넌트
- 스토리북
Basic
- 테스트
Adv
⛔️ 3. 프론트 개발 포인트
고민이 필요하다.
> 우리의 목적 <
- 1차 프로젝트 회고를 전부 읽어보면서, 사전에 도입하면 좋았던 부분들을 생각해보기
[후보]
- 협업
- 체계적인 능률 향상을 위한 방법론들 도입
- 페어 프로그래밍
- 좋은건 좋은건데, 단, 가능한 환경이냐?
- 라이브러리 활용 최대화
- react-query, recoil 등 공식문서를 온전히 이해하고, 제대로 사용하고자 함
- UX 최대화
- 사용자 입장에서 최적화 고려
- 로딩, 스켈레톤 , …
- 예외처리, 모든 입력에 대한 대응
- 수치나 근거가 있어야하는데?
- 컴포넌트 범위나 책임, 역할 분리
지향해야하는데 지킬 수 없는 약속에 가깝다.
매력적인선택지
- 걱정되는 것은 거시적이다…
- 고민한다고 되는 분야인가..
- 시간과 일정이 넉넉치 않은 상황에서 가능한가?
- basic first, refactor later 와 반대의 길?
- 성능 최적화
부적합
나는 노력을 했어요 밖에 안되니까
,선택할 수 없는 선택지
- 리팩토링 할 때는 강점일 수 있는데, 기준점 정하기가 어렵기 때문에, 초기 프로젝트에서 포인트로 정하기 어렵다.
- 라이트하우스 기준으로 ~점수의 ~측면이 낮아서 → 어떤 개선액션을 취했고 → ~한 개선효과를 측정했다.
- 리렌더링 되는 모든 컴포넌트를 탐색 후 → 리렌더링 최소화 개선 액션 → ~~한 효과 측정
2. 🎤 스펙 관련 세부 논의
🎤 스택관련 세부 논의
[2.1. Next.js
보류
]- 도메인 어울리긴 하는데, 시간적인 측면, 생산성 측면을 고려할 때, 프로젝트 이후 리팩토링 단계에 더 적합하다고 판단
[2.2 상태라이브러리
react-query+recoil
]- server상태:
react-query
- ⚠️ 승범 제안, 인수 찬성, 채우 대기
- react-query 도입 참고 자료
- 전역상태:
contextAPI
||recoil
- recoil 사용성 장점
- contextAPI 가장 row한 단계라는 특징
- 의견
- 인수
- react-query 안쓰고 Context API 하거나
- react-query 쓴다면 Recoil 같이 사용하기
[2.3 스타일
emotion + MaterialUI + storybook
]3. 폴더 구조
src ┣ api ┣ components // 공통 컴포넌트 ┃ ┗ Header // 컴포넌트 ┃ ┃ ┣ Header.jsx // jsx file ┃ ┃ ┣ Header.style.js //style file ┃ ┃ ┗ index.js // export file ┣ hooks // 공통 hooks ┣ recoil // recoil 로직 ┣ utils // 기타 js로직 폴더 ┣ @type// typescript type 관련 폴더 ┣ constants ┗ pages // page 폴더 ┃ ┣ components // page에서만 쓰이는 컴포넌트 ┃ ┗ hooks // page 내에서만 쓰이는 hooks
4. 패키지 설치
- react-router
- react-query
- recoil
- storybook
- axios
- feather-icons
npm install feather-icons --save
<Icon
name
="triangle"
size
={30}
rotate
={270}
fill
/>
[설치]
[실제 사용시]
[Icon Component]
code
function Icon({ name, size = 16, strokeWidth = 2, color = '#222', rotate = 0, fill, addStyle, ...props }: propsType) { const iconStyle = { 'stroke-width': strokeWidth, stroke: color, width: size, height: size, fill: fill ? color : 'none', }; const shapeStyle = { width: size, height: size, transform: rotate ? `rotate(${rotate}deg)` : undefined, }; const icon = icons[name]; const svg = icon ? icon.toSvg(iconStyle) : ''; const base64 = Buffer.from(svg, 'utf8').toString('base64'); return ( <IconWrapper style={{ ...shapeStyle, ...addStyle }} {...props}> <img alt={name} src={`data:image/svg+xml;base64,${base64}`} /> </IconWrapper> ); } export default Icon;
5. ESLint 및 Prettier
인수 ESLint
{ "env": { "browser": true, "node": true, "es6": true }, "extends": [ "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "airbnb", "plugin:react/recommended", "plugin:react-hooks/recommended", "plugin:prettier/recommended" ], "plugins": [ "prettier" ], "rules": { "linebreak-style": "off", "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn", "react/jsx-filename-extension": [ 1, { "extensions": [ ".js", ".jsx", "tsx" ] } ], "import/no-unresolved": "off", "react/react-in-jsx-scope": "off", "react/jsx-props-no-spreading": "off", "react/require-default-props": "off", "import/no-extraneous-dependencies": [ "error", { "devDependencies": true } ], "import/extensions": "off", "@typescript-eslint/no-non-null-assertion": "off", "prettier/prettier": ["error", { "endOfLine": "auto" }], "no-underscore-dangle": "off", "import/prefer-default-export": "off", }, "overrides": [ { "files": [ "*.ts", "*.tsx" ], "rules": { "no-undef": "off", "no-unused-vars": "off" } }, { "files": [ "*.config.js" ], "rules": { "@typescript-eslint/no-var-requires": "off" } } ], "parser": "@typescript-eslint/parser" }
승범 ESLint
{ "extends": ["airbnb", "plugin:prettier/recommended"], "plugins": ["react", "jsx-a11y", "import"], "parserOptions": { "ecmaVersion": 2021 }, "rules": { "prettier/prettier": ["error", { "endOfLine": "auto" }], "react/jsx-filename-extension": [ "error", { "extensions": [".js", ".jsx"] } ], "jsx-a11y/img-has-alt": "off", "react/function-component-definition": "off", "react/jsx-props-no-spreading": "off", "consistent-return": "off", "no-undef": "off", "import/no-unresolved": "off", "no-underscore-dangle": "off" } }
채우 ESLint
module.exports = { env: { browser: true, es2021: true, }, extends: [ 'plugin:react/recommended', 'plugin:react-hooks/recommended', 'airbnb', 'plugin:prettier/recommended', ], parserOptions: { ecmaFeatures: { jsx: true, }, ecmaVersion: 'latest', sourceType: 'module', }, plugins: ['react'], rules: { 'prettier/prettier': [ 'error', { endOfLine: 'auto', }, ], 'react/jsx-filename-extension': ['warn', { extensions: ['.js', 'jsx'] }], 'linebreak-style': 0, 'react/react-in-jsx-scope': 0, 'comma-dangle': 0, 'no-unused-vars': 1, 'import/no-unresolved': 0, 'no-unused-expressions': ['error', { allowShortCircuit: true }], 'react/jsx-props-no-spreading': 0, 'react/forbid-prop-types': 0, 'consistent-return': 0, 'no-shadow': 0, 'no-underscore-dangle': 0, }, };
Prettier
code
{ "singleQuote": true, "semi": true, "useTabs": false, "tabWidth": 2, "trailingComma": "all", "printWidth": 80 }
"eslint-plugin-prettier": "^4.0.0", "eslint-config-prettier": "^8.5.0",
6. 브랜치 룰 리뷰 및 PR 컨벤션
6.1 브랜치 룰
main : 배포용
develop : 개발
feat : 기능 구현
feat/[이슈번호]
ex)
feat/123
6.2 PR컨벤션 및 리뷰 룰
[리뷰]
- PR 단위
- issue 단위
- issue 생성 시 고려하기
- 리뷰 강도
- 작성자의 PR 포인트 위주로
- 리뷰 시간
- 급함: 30분 이내 리뷰시작
- 일반: 다음 코탐 전 까지
PR Template
예시
📌 PR 설명
아주 기본적인 Card 컴포넌트를 만들었습니다.
- CheQuiz의 대부분 컴포넌트는 사각형 구조로 되어 있습니다. 이런 구조 Container를 만들 때, 바로 가져와서 쓰도록 Base 컴포넌트로서 Card를 구현하였습니다.
💻 요구 사항과 구현 내용
e684479 Card 컴포넌트를 구현했습니다.
✔️ PR 포인트 & 궁금한 점
일단 아주 기본적이지만 필요했던, Card 컴포넌트만 구현해 놨습니다.
- 각 파트에서 사용하고 있는 Card 비슷한 컴포넌트도 만들어 드리고 싶었는데, 스타일드 컴포넌트로만 구현하기에는 어려움이 있어 일단 보류했습니다.
- 일단 기본적인 제가 맡은 컴포넌트는 여기까지인데, 있으면 좋겠다 하는 컴포넌트가 혹시 있을까요?close [Feat] 카드 컴포넌트 구현 #163
- 라벨
급함
: 다음작업이 연속적일 때- PR 후 슬랙 메세지 보내기
- PR 후 30분 이내 보기
- 일반
- 다음 코탐 이전까지
- rebase merge 사용