언어 및 기술 스택
[ 언어 ]
- Typescript
[ 라이브러리 및 프레임워크 ]
- React
주 라이브러리
- Next.js
프레임워크
- Redux
상태 관리 라이브러리
- Emotion
스타일 컴포넌트 라이브러리
- Storybook
컴포넌트 테스트 및 관리
[ 협업 툴 ]
- Jira
백엔드와 함께 에픽 단위로 프로젝트를 관리
- Figjam
아이디어 확장 및 프론트엔드 와이어프레임 관리
[ Lint & Prettier Rules ]
Lint
{ "env": { "browser": true, "node": true, "es6": true }, "parser": "@typescript-eslint/parser", "parserOptions": { "tsconfigRootDir": "./", "project": ["./tsconfig.json"] }, "plugins": [ "prettier", "@typescript-eslint" ], "extends": [ "airbnb", "airbnb-typescript", "next/core-web-vitals", "plugin:prettier/recommended" ], "rules": { "react/jsx-props-no-spreading": "off", "react/require-default-props": "off" }, "settings": { "react": { "version": "detect" } }, "overrides": [ { "files": [ "*.config.js" ], "rules": { "@typescript-eslint/no-var-requires": "off" } } ] }
Prettier
{ "singleQuote": true, "semi": true, "useTabs": false, "tabWidth": 2, "trailingComma": "all", "printWidth": 80, "endOfLine": "lf" }
Git Flow
[ 브랜치 전략 ]
develop (default)
- 개발할 때 사용하는 default branch
- 이 브랜치는 무결해야 하며, 강제로 force push하거나 허락 없이 바로 merge할 수 없도록 branch protection rule이 설정되어 있습니다.
develop
브랜치에 병합하기 전 확인 사항
- 작업 한 브랜치는
develop
브랜치와 병합 충돌이 발생해서는 안됩니다.
- 병합 충돌이 발생하지 않더라도, 병합하기 전 rebase 후 병합해야 합니다.
- git graph를 깔끔하게 관리하기 위함
# local develop branch에서 git fetch origin develop git rebase origin/develop git checkout feature/your_branch git rebase develop # if conflict # shell로 작성하는 것이 gui를 쓰는것 보다 좋다. git add . git rebase --continue # orgin branch에 push 시 --force 옵션이 없을 경우 커밋이 꼬일 수 있으므로 # 반드시 --force 옵션을 줘야 함 git push --force
- 작업한 branch의 작업물이 브라우저 상에서 콘솔 상 오류가 없어야 합니다.
- 작업한 branch의 작업물 코드 상 lint error(빨간 줄)이 발생하면 안됩니다.
- 불필요한 console.log를 제거해야 합니다.
{jira_ticket_number}
ex) WOOR-14
- 기능을 개발하거나, 버그를 수정해야 할 때에는
develop
브랜치로부터 checkout을 한 뒤 작업을 진행합니다. - 커밋 컨벤션 우선순위와 동일하게 기능 개발을 하면서 관련 버그가 수정되었다면, feature가 더 높은 우선순위를 가질 수 있습니다.
main
- 배포를 위한 브랜치입니다.
[ 커밋 컨벤션 ]
- 커밋 prefix는 다음과 같으며, 위쪽이 우선순위가 더 큽니다.
feat
: 기능 상의 변화가 있을 때 (제품 코드 수정 발생)fix
: 버그 수정docs
: 문서 추가 및 삭제, 변경 (코드 수정 X)style
: 코드 형식 및 정렬, 주석 변경refactor
: 코드 리팩토링chore
: 그 외 나머지
- 커밋 메시지는 다음과 같이 작성합니다.
ex)
feat: 로그인 기능 구현
[ 이슈 컨벤션 ] - Jira 상태에 따라 변할 수도 있습니다.
ex)
Feature/이미지 드래그앤 드랍 기능 구현
[ PR 컨벤션 ]
- PR을 작성할 때는 prefix로
#{jira_ticket_number}
를 사용합니다. 그리고 나머지 부분은 issue와 동일한 제목을 붙입니다.
ex)
WOOR-14/이미지 드래그앤 드랍 기능 구현
Pull Request관련
PR이 빠르게 리뷰가 이루어지기 위해 리뷰어는 다음을 지켜주시면 감사하겠습니다.
- PR 리뷰 기간은 PR 이 올라온 뒤 24시간 이내로 리뷰를 진행
PR이 빠른 리뷰가 이루어질 수 있도록, Assignee는 다음의 규칙을 지켜주시기 바랍니다.
- 이슈 단위 최소화
- 처음 이슈 등록시 수정 범위가 너무 커지지 않도록 이슈 범위를 잡아주세요.
- 코드의 수정량이 200줄 근처로 맞춰주세요 (필수는 아니지만, 최대한 지키려고 노력합시다)
- 커밋 단위와 수정 단위를 일치
- 코드 가독성 신경쓰기
폴더 구조
# next.js 는 src 폴더가 없습니다. |- pages | |- api |- components | |- Input | | |- index.ts | | |- Input.tsx | | |- styles.ts or Input.styles.ts | | |- Input.stories.tsx |- utils |- store |- hooks
JSX 문법이 없으면 ts, 있으면 tsx를 쓰면 됩니다.
개발 컨벤션
[ 함수 선언 ]
- 컴포넌트를 포함한 함수는 함수 선언문으로 선언합니다. 단,
*.stories.tsx
는 이를 무시할 수 있습니다.
- 리액트 컴포넌트 내부에 활용되는 함수는 분리할 수 있다면 외부에 함수 선언문으로 작성하고, 분리할 수 없다면 내부에 함수 표현식으로 작성할 수 있습니다.
// bad const Component: React.FC = () => { return <div /> } // good function Component () { const [state, setState] = useState(false) const toggle = () => setState((prev) => !prev) return <div /> }
[ 인터페이스 및 타입 ]
- 불가피하게 Type을 사용할 수밖에 없는 경우를 제외하고는, Interface를 사용합니다.
- Interface와 Type은 PascalCase를 사용합니다.
- Interface는 Interface임을 표시할 수 있도록 앞에 I prefix를 붙입니다.
- Type은 Type임을 표시할 수 있도록 뒤에 Type 또는 Types postfix를 붙입니다.
// bad type someType = { color: string; } function Component({color}: sometype) {} // good interface ISomeInterface { color: string } type ReturnTypes = [boolean, () => void] function Component({color}: ISomeInterface): ReturnTypes { const [state, setState] = useState(false) const toggle = useCallback(() => { setState((prev) => !prev) }, []) return [state, toggle] }
- 인터페이스가 전역으로 사용될 여지가 있을 경우에는 types 또는 interface 폴더에 넣어서 사용할 수 있습니다.
- 그 외 단순 컴포넌트의 Props state를 정의하거나 전역적으로 사용되는 타입이나 인터페이스가 아니라면 해당 함수가 선언된 위치에서 인터페이스 정의 후 export 할 수 있습니다.
[ 파일 구조 ]
- 스타일 관련 컴포넌트 파일이라면 다음의 네이밍 컨벤션을 가져야 합니다.
Component.styles.ts
- postfix가 tsx로 끝나지 않는다는 것에 유의하세요.
- 컴포넌트 폴더에서 다음의 파일은 세트로 구성됩니다. 단 모든 폴더가 하위 4개의 파일을 모두 가져야만 하는 것은 아닙니다.
index.ts
: 파일을 import하고 export 하는 용도Component.tsx
: 실제 컴포넌트가 정의된 위치Component.styles.ts
: 컴포넌트의 스타일이 반영된 위치Component.stories.tsx
: 컴포넌트 Storybook 파일
[ 스타일 ]
- 스타일은 8px rule를 지켜서 정의합니다.
[ import ]
- import 순서는 다음의 규칙을 따릅니다.
- react 관련 import
- next 관련 import
- 라이브러리 관련 import
- 모듈 or 커스텀 Hook 관련 import
- 스타일 import
// react 관련 import React, { useEffect, useState, useContext, useCallback } from 'react'; // next import Image from 'next/image'; // libraries import axios from 'axios'; import dayjs from 'dayjs'; // modules import CustomComponent from 'components/CustomComponent'; // styles import * as S from './style'; import 'global.module.scss';
[ CSS 작성 순서 ]
css는 다음의 순서에 맞게 작성합니다.
1. display: 객체의 노출여부/표현방식 2. list-style 3. position 4. float 5. clear 6. width / height 7. padding / margin 8. border / background 9. color / font 10. text-decoration 11. text-align / vertical-align 12. white-space 13. other text 14. content