원티드 프리온보딩 1주차 첫 번째 과제


✏️ 과제 설명

동료학습을 통해서 팀에서 생각한 원티드 프리온보딩 프론트엔드 인턴십 선발 과제의 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();
    

Best Practice 산정

  • 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 는 완료 된 (체크박스 표시) 만을 보여주도록 합니다.

👏 협업 방법

주된 커뮤니케이션 툴로 팀 노션 페이지와 디스코드, ZEP을 사용했습니다.

노션 페이지

  1. 팀원들의 코드를 분석하고, 그 중에서 Best Practice를 정리하였습니다.
  2. commit 컨벤션, git flow 전략, 네이밍을 정의하였습니다.
  3. 팀원들의 역할 분담, 일정 조율을 위해 활용되었습니다.

디스코드 & ZEP

  1. 팀원들의 의사소통 및 화면 공유를 통한 협업을 위해 활용되었습니다.

⭐️ 과제 구현

1. 로그인 / 회원가입

✅ Assignment 1

  • 회원가입과 로그인 페이지에 이메일과 비밀번호의 유효성 검사기능을 구현해주세요

    • 이메일 조건: @ 포함
    • 비밀번호 조건: 8자 이상
    • 이메일과 비밀번호의 유효성 검사 조건은 별도의 추가 조건 부여 없이 위의 조건대로만 진행해주세요 (e.g. 비밀번호 유효성 검사에 특수문자 포함 등의 새로운 조건을 추가하는 행위를 지양해주세요)
  • 입력된 이메일과 비밀번호가 유효성 검사를 통과하지 못한다면 button에 disabled 속성을 부여해주세요

  • 보안 상 실제 사용하고 계신 이메일과 패스워드말고 테스트용 이메일, 패스워드 사용을 권장드립니다.

✅ Assignment 2

  • 회원가입 페이지에서 버튼을 클릭 시 회원가입을 진행하고 회원가입이 정상적으로 완료되었을 시 /signin 경로로 이동해주세요

✅ Assignment 3

  • 로그인 페이지에서 버튼을 클릭 시, 로그인을 진행하고 로그인이 정상적으로 완료되었을 시 /todo 경로로 이동해주세요

    • 로그인 API는 로그인이 성공했을 시 Response Body에 JWT를 포함해서 응답합니다.
    • 응답받은 JWT는 로컬 스토리지에 저장해주세요

✅ Assignment 4

  • 로그인 여부에 따른 리다이렉트 처리를 구현해주세요

    • 로컬 스토리지에 토큰이 있는 상태로 /signin 또는 /signup 페이지에 접속한다면 /todo 경로로 리다이렉트 시켜주세요
    • 로컬 스토리지에 토큰이 없는 상태로 /todo페이지에 접속한다면 /signin 경로로 리다이렉트 시켜주세요

2. TODO LIST

✅ Assignment 5

  • /todo경로에 접속하면 투두 리스트의 목록을 볼 수 있도록 해주세요
  • 목록에서는 TODO의 내용과 완료 여부가 표시되어야 합니다.
  • TODO의 완료 여부는 <input type="checkbox" />를 통해 표현해주세요
  • TODO는 <li> tag를 이용해 감싸주세요

모든 todolist, 완료, 미완료 카테고리를 나누어 사용자 측면에서 좀 더 관리하기 쉬운 UX로 하기로 결정하였습니다.


✅ Assignment 6

  • 리스트 페이지에 새로운 TODO를 입력할 수 있는 input과 추가 button을 만들어주세요

    • TODO 입력 input에는 data-testid="new-todo-input" 속성을 부여해주세요
    • TODO 추가 button에는 data-testid="new-todo-add-button" 속성을 부여해주세요
  • 추가 button을 클릭하면 입력 input의 내용이 새로운 TODO로 추가되도록 해주세요

✅ Assignment 7

  • TODO의 체크박스를 통해 완료 여부를 수정할 수 있도록 해주세요.

✅ Assignment 8

  • TODO 우측에 수정버튼과 삭제 버튼을 만들어주세요

    • 수정 버튼에는 data-testid="modify-button" 속성을 부여해주세요
    • 삭제 버튼에는 data-testid="delete-button" 속성을 부여해주세요

✅ Assignment 9

  • 투두 리스트의 삭제 기능을 구현해주세요

    • 투두 리스트의 TODO 우측의 삭제버튼을 누르면 해당 아이템이 삭제되도록 해주세요

✅ Assignment 10

  • 투두 리스트의 수정 기능을 구현해주세요

    • TODO 우측의 수정 버튼을 누르면 수정모드가 활성화 되도록 해주세요
    • 수정모드에서는 TODO의 내용을 변경할 수 있어야 합니다.
    • 수정모드에서는 TODO의 내용이 input창 안에 입력된 형태로 변경해주세요
      • 수정 input창에는 data-testid="modify-input" 속성을 부여해주세요
    • 수정모드에서는 TODO의 우측에 제출버튼과 취소버튼이 표시되게 해주세요
      • 제출버튼에는 data-testid="submit-button" 속성을 부여해주세요
      • 취소버튼에는 data-testid="cancel-button" 속성을 부여해주세요
    • 제출버튼을 누르면 수정한 내용을 제출해서 내용이 업데이트 될 수 있도록 해주세요
    • 취소버튼을 누르면 수정한 내용을 초기화 하고, 수정모드를 비활성화 해주세요


✨ 컨벤션

1. 커밋 컨벤션

feat : 새로운 기능 추가
fix : 버그 수정
docs : 문서 수정
style : 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우
refactor : 코드 리팩토링
test : 테스트 코드, 리팩토링 테스트 코드 추가
chore : 빌드 업무 수정, 패키지 매니저 수정

2. 네이밍 컨벤션

Components : Pascal case (ex. H3.js, Button.js)
Non-component: Camel case (ex. fetchApi.js)

참조

3. 브랜치 컨벤션

├─ main // 최종, 배포 branch
│  └─ dev // 개발계 merge branch
│     ├─ feat/auth // 각 기능별 개발 branch
│     ├─ feat/todo // 각 기능별 개발 branch
└─    └─ feat/api // 각 기능별 개발 branch
각자 브랜치는 로컬에서 작업 후 각 기능별 개발 branch로 pull Request

참조


4. Eslint

  "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"
      }
    ]

5. Prettier

{
  "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) : 유승윤, 이유태, 박수지