-
Notifications
You must be signed in to change notification settings - Fork 3
Home
- 회의는 화(오프라인), 금(온라인)에 1시간씩 진행한다.
- 회의 시간을 지킵니다.
- 코드 리뷰는 24시간 내에 반드시 합니다.
- 컨벤션을 잘 지킵니다.
- 프로젝트 관련 논의 내용은 즉석에서 오프라인으로 이루어지더라도 반드시 “문서화” 합니다.
- 매일 스크럼 시간(오전 10시)에 칸반보드를 최신화 합니다.
-
Guthub 레포지토리 접속 https://github.com/codeit-bootcamp-frontend/0-crypto-meter-technokings
-
이슈 생성
- 이슈 번호 확인 (브랜치명에 필요)
-
브랜치 생성후 작업
- 현재 repo를 fork 딴다.
- 그럼 현재 repo가 upstream repo, 본인 repo에 있는 fork repo가 origin repo가 된다.
- fork한 origin repo를 로컬에 clone한 뒤
- dev 브랜치를 기준으로 feature 브랜치 등을 분기해서 작업을 끝내고
git push origin feature
후에 - dev 브랜치를 기준으로git switch -c feature/delete_irrelevants/#3
후에git push origin feature/delete_irrelevants/#3
- origin feature 브랜치에서 바로 upstream dev로 PR 날린다. (개인 feature => 공용 dev로 PR)
- 코드리뷰를 받았다면,
- upstream repo의 dev와 origin repo의 dev 브랜치 싱크를 맞춰줘야 한다 (혹은 origin dev 브랜치에서 git pull upstream dev)
4-1. 브랜치 생성후 작업(보다 자세한 설명)
a.개인 로컬 dev
브랜치를공용 dev
브랜치와 sync
b.개인 로컬 dev
(hotfix의 경우로컬 main
)브랜치에서 작업할 새 브랜치 생성
`git branch refactor/delete_irrelevants/#3`
`git checkout(or switch) refactor/delete_irrelevants/#3`
OR
`git checkout -b refactor/delete_irrelevants/#3`
OR
`git switch -c refactor/delete_irrelevants/#3`
c. 작업 완료 후 push
git push origin refactor/delete_irrelevants/#3
- PR날리기
작업한 브랜치 → 공용 레포의 dev 또는 main 브랜치
-
main
브랜치: 프로덕션 브랜치(여기에 push하면 netlify의 CI/CD가 실행됨) -
dev
브랜치: 버그 픽스가 아닌 모든 작업(꼭 새로운 기능이 아니라도 리팩토링, dev 브랜치 버그 픽스 등) + dev 브랜치도 netlify에 배포한다(개발모드) -
hotfix
브랜치: 버그 픽스 브랜치, 현재 main브랜치에 있는 버그들을 바로 고치고 merge하는 hotfix 브랜치 역할
이렇게 3개의 브랜치로 운영한다. 당장은 dev 브랜치에서 모든 작업을 하므로, hotfix 브랜치를 쓸 일이 없지만, 이후 프로젝트가 끝나고 지속적인 유지/보수를 위해 일단 3개의 브랜치를 운영하는 것으로 한다. 현업처럼 release브랜치까지 나눠서 관리하기엔 규모가 작고 인원도 작아 오히려 유지보수하는데 어려울 것 같아서 과감하게 조금 더 가벼운 브랜치 전략으로 선택했다.
-
<category>/<description>/<issue-ref>
순으로 이름을 짓기로 한다.- category:
feature
,bug
,refactor
로 구분 - description: 간략한 설명(너무 상세할 필요 X), kebab-case로 작성한다.
- issue-ref: 이슈번호
- category:
-
예를 들어 예시1)
✅ 리팩토링 작업 중 불필요한 변수를 제거하는 작업을 진행한 브랜치이고, 대응하는 이슈번호는 1번이다.refactor/remove-unused-variables/#1
예시2)
✅ 회원가입 폼 관련 버그(dev브랜치에서 발견된 버그)를 고치는 작업을 진행한 브랜치이고, 대응하는 이슈번호는 3번이다.bug/register-form-not-working/#3
예시3)
✅ 호버 텍스트 기능을 구현하기 위한 작업을 진행한 브랜치이고, 대응하는 이슈 번호는 4번이다.feature/hover-text/#4
⭐️⭐️ 작업 전후로 반드시 해야하는 upstream-fork sync 과정 ⭐️⭐️
- 핵심은 공용 dev와 개인 dev를 항상 같은 상태로 유지시키는 것입니다.
- 수시로 sync해줌으로써 conflict를 최소화할 수 있습니다.
- 다음의 과정을 작업 전후로 항상 진행하는 것을 원칙으로 합니다.
-
새로운 기능을 개발하는 경우 (개인 작업 브랜치 → dev로 머지)
- 깃허브에서 관련 내용의 이슈를 생성합니다.
-
dev
브랜치에서feature/hover-text/#4
와 같은 이름의 새 브랜치를 만듭니다. - 새 브랜치에서 작업 후, 리모트에 push합니다.
-
dev
브랜치로 merge하는 PR을 생성합니다. - 코드리뷰와 머지가 완료되면 이슈를 close하고 작업한 브랜치를 삭제합니다.
-
main브랜치에서 발견한 버그를 고치는 경우 (공용 hotfix 브랜치 → main으로 머지)
- 깃허브에서 관련 내용의 이슈를 생성합니다.
-
hotfix
브랜치로 이동한후, 새 브랜치를 만들 필요 없이 버그 수정 작업을 진행합니다. - 작업이 완료되면 리모트로 push후,
main
으로 merge하는 PR을 생성합니다. - 코드리뷰와 머지가 완료되면 이슈를 close합니다.
-
리팩토링 작업이 필요한 경우 (개인 작업 브랜치 → dev로 머지)
- 깃허브에서 관련 내용의 이슈를 생성합니다.
-
dev
브랜치에서refactor/remove-unused-variables/#5
와 같은 이름의 새 브랜치를 만듭니다. - 새 브랜치에서 작업 후, 리모트에 push합니다.
-
dev
브랜치로 merge하는 PR을 생성합니다. - 코드리뷰와 머지가 완료되면 이슈를 close하고 작업한 브랜치를 삭제합니다.
-
dev 브랜치에서 발견한 버그를 고치는 경우 (개인 작업 브랜치 → dev로 머지)
- 깃허브에서 관련 내용의 이슈를 생성합니다.
-
dev
브랜치에서bug/register-form-not-working/#7
와 같은 이름의 새 브랜치를 만듭니다. - 새 브랜치에서 작업 후, 리모트에 push합니다.
-
dev
브랜치로 merge하는 PR을 생성합니다. - 코드리뷰와 머지가 완료되면 이슈를 close하고 작업한 브랜치를 삭제합니다.
-
dev에서 의미 있는 기능 묶음들이 정상적으로 동작할 때(새 버전 릴리즈) (dev → main 으로 머지)
- 깃허브에서 관련 내용의 이슈를 생성합니다. (또는 release 생성)
- dev 브랜치에서 main 브랜치로 merge하는 PR을 생성합니다.
- 리뷰가 완료되면 merge합니다. (dev → main)
- hotfix 브랜치 최신화를 위해 main → hotfix merge도 해줍니다.
리뷰어가 코드리뷰가 끝나면 Approve 후 마지막에 리뷰한 리뷰어가 Merge하도록 합니다. 리뷰어가 바로 Approve하지 않고 변경사항을 Request하는 경우 해당 PR을 올린 Assignee가 코드를 수정 후 리뷰를 재요청하도록 합니다.
case
- 일반변수:
camelCase
- 상수:
SCREAM_SNAKE_CASE
convention
- 명사로 작성한다.
- 예외) boolean 변수는 is~ has~ includes~ 등의 현재형 동사로 시작한다.
case
camelCase
convention
- 현재형 동사 + 명사로 작성한다.
- 핸들러함수:
handle~
로 시작한다.
case
PascalCase
convention
- 두 단어 이상의 조합으로 작성한다.
LoginPage.tsx
HomeButton.tsx
- Styled Component:
S~
로 시작한다.
export const Sdiv = styled.`
// ...
margin-top: ${({mgt}) => mgt ?? '0'};
${({ct}) => css`display: flex; justify-content: center, align-items: center`};
// ....
case
- 컴포넌트:
PascalCase.jsx
- 일반 파일 : 전부 소문자로 작성한다. 단어와 단어 사이는 dot으로 구분한다.
axios.instance.js
case
- 컴포넌트, 페이지 폴더:
PascalCase
- 일반 폴더: 소문자, 복수형,
kebab-case
(예: components, pages, hooks, …)
├─ src/
│ ├─ assets/
│ │ └─ favicon.svg
│ ├─ components/
│ │ ├─ ToggleButton
│ │ │ └─ ToggleButton.js
│ │ ├─ FilterChip
│ │ │ └─ FilterChip.js
│ │ └─ index.js
│ ├─ (contexts)
│ ├─ data/
│ ├─ services/
│ ├─ styles/
│ │ ├─ colors.js
│ │ └─ styled.components.js
│ ├─ utils/
│ ├─ App.css
│ ├─ App.jsx
│ └─ main.jsx
- assets: 이미지, 폰트 등
- components: 컴포넌트
- data: 정적인 고유 데이터 (mock.json, maps 등)
- services: api 관련 기능들
- styles: 공용 스타일 관련 폴더
- utils: 공용 유틸리티 함수들
- Main.jsx: 엔트리포인트
- App.jsx: 메인 앱
- App.css: 메인 앱 스타일 (reset 포함)
-
feat
: 새로운 기능(기능 구현) -
fix
: 버그 수정 -
docs
: documentation 변경 -
style
: 코드 의미에 영향을 주지 않는, 코드 스타일에 관련된 변경 사항(포맷, 공백, 빼먹은 세미콜론, 함수 이름 변경, 줄간격, 파일 이름, 의미없는 주석 삭제) -
refactor
: 리팩토링에 대한 커밋(버그를 수정하지 않고 기능을 추가하지 않는 코드 변경) -
chore
: 패키지 매니저 설정할 경우, 코드 수정 없이 설정을 변경(eslint, prettier…패키지 설정), 이외에도 특정 영역에 들어가기 애매한 잡다한 작업들
Emoji | Category | Description |
---|---|---|
🎉 | init | Start a project. |
✨ | feat | Introduce new features. |
✏️ | fix | Fix typos. |
🐛 | fix | Fix a bug. |
📝 | docs | Add or update documentation. |
🎨 | style | Improve structure / format of the code. |
♻️ | refactor | Refactor code. |
🔥 | chore | Remove code or files. |
💩 | poop | Write bad code. |
🚚 | chore | Move or rename resources |
🍱 | chore | Add or update assets. |
🔖 | feat/fix | Release / Version tags. |
✨: 회원가입 기능 개발
🐛: 회원가입 시 사용자 이름이 안보이는 버그 수정
> npm i -g gitmoji-cli # 글로벌 주의
# or
> brew install gitmoji
git add . # (add 할 것들 스테이징에 올리고)
gitmoji -c # 입력해서 이모티콘 선택하고
#커밋 타이틀, 커밋 메시지 입력하고
git push ... #로 origin 브랜치에 넣기
- 화살표 함수를 사용합니다.
- if else 문 사용을 지양하고 early return 패턴을 사용합니다.
- 스타일드 컴포넌트는 컴포넌트 하단에 작성합니다. - 이를 위해 .eslintrc의 rule에
"no-use-before-define": "off",
를 추가합니다- 조건부 렌더링 패턴 - undefined 배열 처리 패턴: 가독성을 위해 옵셔널 체이닝을 사용합니다.
array?.map(()=>{})
- 양자 택일 렌더링 패턴: else를 최대한 지양하고, 코드의 의미 전달을 높일 수 있게 early return 패턴을 사용합니다.
```
if (condition)
return <ThisComponent />
return <ThatComponent />
```
- 부분 조건부 렌더링 패턴:
- 옵션이 2개 일 때는 삼항 연산자를 사용합니다.
- 옵션이 3개 이상일 때는 object mapping을 사용합니다.
- default value가 필요한 경우 nullish coallescing 문법을 사용합니다.
```
<span>{title ?? "default"}</span> // 값이 없는 상황에 default 값을 보여줄 때
<span>{isIncreased ? "going up!" : "going down hard.."}</span> // boolean일 때
<span>{messageMap[message]}</span>
```
- 비동기 함수를 사용할 때는 콜백 헬 방지를 위해 async/await를 사용합니다.
- import 경로 - 절대경로를 사용합니다. - aliasing을 사용하여 src, components 등의 큰 폴더 경로의 별칭을 설정하여 사용합니다.
- 컴포넌트안에서 props 객체는 구조분해 할당하여 사용합니다.
- 커스텀 훅은 배열이 아닌 객체를 반환하도록 합니다.
- eslint 설정 - airbnb extends를 사용합니다. - import문은 외부 모듈과 내부 모듈로 분리합니다.
```
// .eslintrc.cjs
extends: [airbnb],
```
```
// .eslintrc(eslintrc.js) 파일 안 "overrides" > "rules" 안에 작성
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal"],
"pathGroups": [
{
"pattern": "react",
"group": "external",
"position": "before"
}
],
"pathGroupsExcludedImportTypes": ["react"],
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
],
//example .eslintrc.js
{
"rules": {
"quotes": ["error", "double"]
},
"overrides": [
{
"rules": {
"import/order": [...]
}
}
]
}
```
- prettier 설정
```
// .prettierrc
{
"singleQuote": false,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"printWidth": 80,
"bracketSpacing": true,
"arrowParens": "always"
}
```
- CSS문 작성 규칙: 다음의 스타일 정의 순서를 지켜 가독성을 높이고 수정을 용이하게 합니다.
```
e. 선언 순서
const SInput = styled.input`
/* 레이아웃 */
display: ..
visibility: ..
..
/* Box model */
width: ..
height:..
..
/* 폰트 */
font: ..
color: ..
..
`
레이아웃 : display, visibility, overflow, float, clear, position, top, right, bottom, left, z-index
BOX : width, height, margin, padding, border
폰트 : font, color, letter-spacing, text-align, text-decoration, text-indent, vertical-align, white-space
```
- String concatenation은 +연산자 대신 템플릿 리터럴을 사용합니다.
```
w + "px" // X
`${w}px` // O
```
- 컴포넌트는 재사용성과 범용성을 위해 최대한 dumb하게 유지합니다. - 컴포넌트 외부 스타일에 영향을 미치지 않습니다(전체 마진 등) - 컴포넌트 안에서 api 호출을 하지 않습니다(app.js에서 호출)
- Semantic 태그 사용을 지향합니다.
- State로부터 파생된 state를 사용하는 경우, 원활한 동기화를 위해 reference를 사용합니다.
```
const [coins, setCoins] = useState([
{id: 1, name: "Bitcoin",},
{id: 2, name: "Dogecoin",},
]);
// 파생된 값을 가진 상태(X)
const [selectedCoin, setSelectedCoins] = useState({...});
// 파생된 reference를 가진 상태 (○)
const [selectedCoinId, setSelectedCoinId] = useState(2);
```
Language
- Javascript
- HTML5
- CSS3
Framework
- React v18
State Management
- Zustand
CSS
- styled components
Utils
- react-date-picker
- recharts
Ajax
- axios
공통 선정 기준
- 대중적으로 사용되어 학습 자료가 많고 기술 습득이 쉬운가
- 커스텀화가 가능한가
Chart
- [Rechart](https://recharts.org/en-US/storybook) - 요구사항 기능과 매치되는 점이 많다. - 툴팁 자동 생성 - vertical line 호버시 자동 생성 - 사용법이 쉬워 2주 프로젝트 기간에 사용하기 적합하다. - prop이 직관적이고 많지 않다. - https://dillonreedy.github.io/recharts-storybook/?path=/docs/recharts-area-chart--simple - 무거운 번들 사이즈
CSS
- styled-components - js 문법을 사용하여 props등의 자바스크립트 변수를 사용할 수 있어 생산성이 높아진다. - props를 적극 활용하여 디자인 시스템과 비슷한 환경을 구축할 수 있다.
상태관리 툴
- Zustand - recoil과 유사한 수준의 쉬운 난이도를 자랑한다. - redux 다음으로 사용자가 많아 참고자료가 많다.
협업 툴
- GitHub - 브랜치 관리, 백보드를 통한 task 상황 관리(Projects), 회의록 작성(Wiki) 등 다양한 기능을 사용할 수 있다. - 위 기능을 한 플랫폼으로 통합하여 협업의 능률을 높일 수 있다.
AJAX
- Axios - 커스텀 인스턴스를 만들어 추상화 및 서비스에 맞는 요청과 응답 세팅이 용이하다. - 사용방법이 직관적이라 팀 프로젝트에 적합하다.
- Netlify 배포 관리
- README 업데이트
- 노션, 슬랙 문서 관리
- 슬랙 관리(운영질문, 학습질문, 프로젝트 관련 질문 담당)
- GitHub 위키
- 공용 레포
- GitHub 프로젝트(칸반보드, 로드맵)
- 노션 내
프로젝트 때 새로 알게 된 것들(혹은 이건 뭐지 싶은 것들) 모음집
문서 관리 담당
- 회의록 작성 및 업로드
- 모든 질문 담당 (운영, 학습, 프로젝트 관련, 멘토링 등 질문 담당)
- 컴포넌트 스켈레톤 제작
- 스타일 @케니
- 디자인 시스템
- 마이크로 컴포넌트 제작
- 전역 스타일 지정
- 인터페이스 설계 @헨리
- mock.json
- 각 컴포넌트 별 상태, prop 등 지정
- 공통 컴포넌트 제작 @이안
- 기타 정적인 컴포넌트 제작(차트 칸 기본 컴포넌트 등) @이안
- 페이지 구성
- 컴포넌트 조립
- 반응형
- 스타일
- 추가 컴포넌트 (ex. 모달)
- 애니메이션
- 기능 구현
- API
- 페이지네이션
- SNS 공유 링크
- 전역 상태 관리
- 차트
- 테스트 및 배포
- dev 서버 운영
- 지속적인 테스팅
- 버그 리포팅
- 사용자는 어떤 코인을 언제 얼마나(금액 기준으로) 샀는지 설정할 수 있다.
- 구매한 금액을 직접 입력할 수 있다.
- 구매한 날짜를 선택할 수 있다.
- 구매한 코인을 선택할 수 있다.
- 구매한 금액을 chip(5000원, 10000원 등)을 통해 설정할 수 있다.
- 사용자는 전체 코인의 현재 현황을 테이블로 확인할 수 있다.
- 보여지는 컬럼
- 화폐 이름(로고포함)
- 변동 폭
- 거래량
- 총 시가
- 현재가
- 테이블을 컬럼별로 정렬할 수 있다.
- 보여지는 컬럼
- 사용자는 선택한 코인의 정보를 차트로 확인할 수 있다.
- 기간별 차트를 선택할 수 있다. (일봉, 주봉, 월봉, 1년, 전체)
- 마우스로 차트상 특정 시점을 갖다대면 당시 날짜와 가격을 확인기능
- 사용자는 선택한 코인 정보를 SNS로 공유할 수 있다.
- 사용자는 한 번 계산된 과거와 현재 시세 차이를 다시 계산할 수 있다.
- 사용자는 기준이 되는 화폐 단위를 바꿀 수 있다.
- 사용자는 본인의 계산 기록을 확인할 수 있다.
- 계산 기록을 모두 지울 수 있다.
smart/dumb component architecture strategy (비즈니스 로직과 뷰 로직을 분리)
- dumb(스타일 ⇒ 스타일드 컴포넌트 조합해서) smart(로직)
컴포넌트의 로직과 스타일을 분리시켜 효율적인 디버깅 및 수정을 가능하게 합니다.
export const HistoryButton = () =>{
// 로직을 통해 prop를 만들어
const handleClickSearchRecord = ()=>{...};
const containerProps = { onClick: handleClickSearchRecord, };
return (
<ButtonContainer {...containerProps}/>
)
}
export const ButtonContainer = ({onClick, isDown?})=>{
return (
<SDiv pdt={40} ct onClick={onClick}>
...
<SText>{isDown ? "down" : "up"}</SText>
</SDiv>
);
}
-
공통 컴포넌트
- 가격 설정 버튼
- chip

- 유틸리티 버튼
<br/>

- select 버튼
<br/>

- input
<br/>

- filter icon
<br/>

- sns icon
<br/>
- navigate 버튼
<br/>
- Logo
<br/>
- 페이지 구성 컴포넌트
- 헤더
- 입력 창
<br/>

- 차트
<br/>

- 테이블
<br/>

- coinList: 지금까지 /coins/markets 요청으로 받아온 코인 리스트(페이지네이션)
- selectedCoinId: 현재 선택된 코인의 id
const [selectedCoinId, setSelectedCoinId] = useState<string>("");
- currency (원, 달러)
GET /coins/markets 요청으로만, 이 요청으로 받은 데이터들을 전역 상태로 관리한다.
- 입력보드에서는 스크롤해서 페이지네이션
- 전체 테이블에서는 버튼 클릭으로 페이지네이션
두 상태는 전역으로 관리되므로 싱크가 맞음.
selected의 경우 불러온 전역 데이터 중에서 id 값 찾아서 불러오면 됨.
왜 이렇게 하냐면,
전체 테이블에서 데이터 받아오는 것과 입력보드에서 데이터 받아오는 걸 GET 요청 분리하는 것보다
전역으로 관리하면 하나의 get 요청으로 데이터를 관리할 수 있다.
로고와 이름만 받아올 수 있는 api가 있으면 따로 해도 되는데, 없다면 위와 같이 관리하는 게 더 낫다.
또는 코인 이름과 아이디만 리스트에 담아 static한 json파일로 만들어서 data폴더안에 넣어두는것도 고려해볼 수 있음. 이 방법의 장점은 select 태그 안에서 get 요청을 하지 않아도 되고, 필요한 부분만 렌더링할 수 있음.
selectedCoinId를 가지고
- GET /coins/{selectedCoinId}/market_chart
- GET /coins/{selectedCoinId}/market_chart/range
- 스타일링
- 인터페이스 설계
- 공통 컴포넌트 제작
- 기타 정적 컴포넌트 제작
- 컴포넌트 조립
- 반응형
- 스타일
- 추가 컴포넌트 (ex, 모달)
- 애니메이션
- API
- 페이지네이션
- SNS 공유 링크
- 전역 상태 관리
- 차트