동료학습을 통해서 팀에서 생각한 원티드 프리온보딩 프론트엔드 인턴십 선발 과제의 Best Pratice를 만들어주세요.
🚀 이번 과제의 목적은 동료학습, 팀으로 일하는 법에 익숙해지는 것, 과제를 대하는 태도를 연습하는 것 입니다.
git clone https://github.com/wanted-pre-onboarding-internship-1team/wanted-pre-onboarding-internship-1team-project_1.git
cd wanted-pre-onboarding-internship-1team-project_1/
echo "REACT_APP_BASE_URL = {api 호출 주소}" > .env
npm install
npm start
https://preonboarding-internship-9th-1.netlify.app/
📄 src
├── App.js
├── apis # api 서버와 통신하는 비즈니스 로직
│ ├── auth.js
│ ├── index.js
│ ├── instance.js
│ └── todo.js
├── components # 각 pages 의 하위 컴포넌트
│ ├── common # 공통 사용되는 컴포넌트
│ │ ├── HeadButton.jsx
│ │ ├── TodoInput.jsx
│ │ ├── button
│ │ │ └── FormButton.jsx
│ │ └── input
│ │ └── FormInput.jsx
│ └── todo
│ ├── AddTodo.jsx
│ ├── FilterContext.jsx
│ ├── Todo.jsx
│ ├── TodoContext.jsx
│ ├── TodoHeader.jsx
│ └── TodoList.jsx
├── const # 상수값을 정의
│ └── filter.js
├── hooks # 공통으로 사용되는 기능 및 비즈니스 로직의 관심사를 분리
│ ├── useApi.js
│ ├── useFilter.js
│ └── useTodo.js
├── index.js
├── pages # route 경로 별로 pages 관리
│ ├── signIn
│ │ └── SignIn.jsx
│ ├── signUp
│ │ └── SignUp.jsx
│ └── todo
│ └── TodoPage.jsx
├── routers # 라우터 설정 관련 컴포넌트
│ ├── AuthRoute.jsx
│ ├── NonAuthRoute.jsx
│ └── Router.jsx
├── style
│ └── Global.js
├── tree.txt
└── utils
└── utilOnChange.js
-
todo
- todoList, filter 데이터의 setter, getter 를 깊은 depth 의 컴포넌트 끼리 공유하기 위해 ContextApi 사용
[Provide] <TodoProvider> <FilterProvider> <TodoHeader /> <TodoList /> </FilterProvider> </TodoProvider> [Consume] const { todos, setTodos } = useTodoContext(); const { currentFilter, filterTitle } = useFilterContext();
-
auth
-
간단한 유효성 검사를 위해서 정규표현식을 사용하는 것은 불필요하다고 판단하여
includes()
,length()
등의 메서드를 사용하여 유효성 검사를 진행했습니다.- 각 메서드들이 하는 역할과 네이밍이 직관적이기 때문에 코드의 가독성을 높여줍니다.
-
에러 핸들링 처리를 통해 사용자에게 회원가입 성공/실패 유무를 알려줌으로써 사용자가 에러 발생 사실을 인지할 수 있습니다.
-
-
todo
- todoList state CRUD 관리에 useState 대신 useReduce를 사용했습니다.
- reduce 는 type 데이터와 switch 의 조합으로 todoLsit state CRUD 코드의 가독성을 높여줍니다. (CRUD 비즈니스 로직을 hook 내에서 관리)
- Filter 기능을 추가했습니다. (todoList View)
- all, active, completed 세 가지 필터가 있으며 버튼을 클릭해 필터링 된 결과를 볼 수 있습니다.
- all 은 모든 todo
- active 는 완료 안 된 todo
- completed 는 완료 된 (체크박스 표시) 만을 보여주도록 합니다.
- all, active, completed 세 가지 필터가 있으며 버튼을 클릭해 필터링 된 결과를 볼 수 있습니다.
- todoList state CRUD 관리에 useState 대신 useReduce를 사용했습니다.
주된 커뮤니케이션 툴로 팀 노션 페이지와 디스코드, ZEP을 사용했습니다.
- 팀원들의 코드를 분석하고, 그 중에서 Best Practice를 정리하였습니다.
- commit 컨벤션, git flow 전략, 네이밍을 정의하였습니다.
- 팀원들의 역할 분담, 일정 조율을 위해 활용되었습니다.
- 팀원들의 의사소통 및 화면 공유를 통한 협업을 위해 활용되었습니다.
-
회원가입과 로그인 페이지에 이메일과 비밀번호의 유효성 검사기능을 구현해주세요
- 이메일 조건:
@
포함 - 비밀번호 조건: 8자 이상
- 이메일과 비밀번호의 유효성 검사 조건은 별도의 추가 조건 부여 없이 위의 조건대로만 진행해주세요 (e.g. 비밀번호 유효성 검사에 특수문자 포함 등의 새로운 조건을 추가하는 행위를 지양해주세요)
- 이메일 조건:
-
입력된 이메일과 비밀번호가 유효성 검사를 통과하지 못한다면 button에
disabled
속성을 부여해주세요 -
보안 상 실제 사용하고 계신 이메일과 패스워드말고 테스트용 이메일, 패스워드 사용을 권장드립니다.
- 회원가입 페이지에서 버튼을 클릭 시 회원가입을 진행하고 회원가입이 정상적으로 완료되었을 시
/signin
경로로 이동해주세요
-
로그인 페이지에서 버튼을 클릭 시, 로그인을 진행하고 로그인이 정상적으로 완료되었을 시
/todo
경로로 이동해주세요- 로그인 API는 로그인이 성공했을 시 Response Body에 JWT를 포함해서 응답합니다.
- 응답받은 JWT는 로컬 스토리지에 저장해주세요
-
로그인 여부에 따른 리다이렉트 처리를 구현해주세요
- 로컬 스토리지에 토큰이 있는 상태로
/signin
또는/signup
페이지에 접속한다면/todo
경로로 리다이렉트 시켜주세요 - 로컬 스토리지에 토큰이 없는 상태로
/todo
페이지에 접속한다면/signin
경로로 리다이렉트 시켜주세요
- 로컬 스토리지에 토큰이 있는 상태로
/todo
경로에 접속하면 투두 리스트의 목록을 볼 수 있도록 해주세요- 목록에서는 TODO의 내용과 완료 여부가 표시되어야 합니다.
- TODO의 완료 여부는
<input type="checkbox" />
를 통해 표현해주세요 - TODO는
<li>
tag를 이용해 감싸주세요
모든 todolist, 완료, 미완료 카테고리를 나누어 사용자 측면에서 좀 더 관리하기 쉬운 UX로 하기로 결정하였습니다.
-
리스트 페이지에 새로운 TODO를 입력할 수 있는 input과 추가 button을 만들어주세요
- TODO 입력 input에는
data-testid="new-todo-input"
속성을 부여해주세요 - TODO 추가 button에는
data-testid="new-todo-add-button"
속성을 부여해주세요
- TODO 입력 input에는
-
추가 button을 클릭하면 입력 input의 내용이 새로운 TODO로 추가되도록 해주세요
- TODO의 체크박스를 통해 완료 여부를 수정할 수 있도록 해주세요.
-
TODO 우측에 수정버튼과 삭제 버튼을 만들어주세요
- 수정 버튼에는
data-testid="modify-button"
속성을 부여해주세요 - 삭제 버튼에는
data-testid="delete-button"
속성을 부여해주세요
- 수정 버튼에는
-
투두 리스트의 삭제 기능을 구현해주세요
- 투두 리스트의 TODO 우측의 삭제버튼을 누르면 해당 아이템이 삭제되도록 해주세요
-
투두 리스트의 수정 기능을 구현해주세요
- TODO 우측의 수정 버튼을 누르면 수정모드가 활성화 되도록 해주세요
- 수정모드에서는 TODO의 내용을 변경할 수 있어야 합니다.
- 수정모드에서는 TODO의 내용이 input창 안에 입력된 형태로 변경해주세요
- 수정 input창에는
data-testid="modify-input"
속성을 부여해주세요
- 수정 input창에는
- 수정모드에서는 TODO의 우측에 제출버튼과 취소버튼이 표시되게 해주세요
- 제출버튼에는
data-testid="submit-button"
속성을 부여해주세요 - 취소버튼에는
data-testid="cancel-button"
속성을 부여해주세요
- 제출버튼에는
- 제출버튼을 누르면 수정한 내용을 제출해서 내용이 업데이트 될 수 있도록 해주세요
- 취소버튼을 누르면 수정한 내용을 초기화 하고, 수정모드를 비활성화 해주세요
feat : 새로운 기능 추가
fix : 버그 수정
docs : 문서 수정
style : 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우
refactor : 코드 리팩토링
test : 테스트 코드, 리팩토링 테스트 코드 추가
chore : 빌드 업무 수정, 패키지 매니저 수정
Components : Pascal case (ex. H3.js, Button.js)
Non-component: Camel case (ex. fetchApi.js)
├─ main // 최종, 배포 branch
│ └─ dev // 개발계 merge branch
│ ├─ feat/auth // 각 기능별 개발 branch
│ ├─ feat/todo // 각 기능별 개발 branch
└─ └─ feat/api // 각 기능별 개발 branch
각자 브랜치는 로컬에서 작업 후 각 기능별 개발 branch로 pull Request
"extends": ["react-app", "plugin:prettier/recommended"],
"rules": {
"no-var": "error", // var 금지
"no-multiple-empty-lines": "warn", // 여러 줄 공백 금지
"no-console": ["warn", { "allow": ["warn", "error"] }], // console.log() 금지
"eqeqeq": "warn", // 일치 연산자 사용 필수
"dot-notation": "warn", // 가능하다면 dot notation 사용
"no-unused-vars": "warn", // 사용하지 않는 변수 금지
"react/destructuring-assignment": "warn", // state, prop 등에 구조분해 할당 적용
"react/jsx-pascal-case": "error", // 컴포넌트 이름은 PascalCase로
"react/no-direct-mutation-state": "error", // state 직접 수정 금지
"react/jsx-no-useless-fragment": "warn", // 불필요한 fragment 금지
"react/no-unused-state": "warn", // 사용되지 않는 state
"react/jsx-key": "warn", // 반복문으로 생성하는 요소에 key 강제
"react/self-closing-comp": "warn", // 셀프 클로징 태그 가능하면 적용
"react/jsx-curly-brace-presence": "warn", // jsx 내 불필요한 중괄호 금지
"linebreak-style": 0, // 윈도우는 꼭 설정 LF, CRLF 문제 해결위함
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
{
"tabWidth": 2,
"printWidth": 80,
"endOfLine": "lf",
"arrowParens": "avoid",
"singleQuote": true,
"jsxSingleQuote": true,
"semi": true,
"bracketSpacing": true,
"bracketSameLine": true
}
조병민(팀장) |
구수정 |
김요한 |
손혜수 |
|
유승윤 |
박수지 |
신공섭 |
윤동희 |
이유태 |
auto / todo / API & Router 3가지로 분류
auth (로그인/회원가입, 유효성 검사, 예외 처리, 리다이렉트) : 조병민, 구수정, 손혜수
todo (header, list, add, context) : 김요한, 신공섭, 윤동희
API & Router (instance, intercepter, router) : 유승윤, 이유태, 박수지