원티드 프리인턴쉽 과제후기

승환입니다·2023년 4월 7일
1
post-thumbnail

원티드 프리인턴쉽 과제후기

원티드 프리인턴쉽 과제를 시작한 이유

같이 스터디를 하고있는 지인이 원티드에서 진행하고있는 원티드 프리인턴쉽을 추천해주었다.

처음에는 아무생각없이 일단 하면 좋겠지라는 마음으로 시작을 했는데 과제 내용을 보니까 되게 배울게 많아보였고 같이 스터디를 하는분들이 다 같이 하자고해서 시작하게되었다.

원티드 프리인턴쉽 과제를 통해 느낀점

다 같이 기획하고 다 같이 배포하고,, 하지만 학생들끼리 하는 프로젝트고 실제 서비스를 하는 것은 아니였기때문에 내가 유동적으로 어떤 기능을 바꿀 수 있었고 시간이 없다면 사용자 입장을 생각하지않고 충분히 내가 원하는 모양을 만들면서 개발을 할 수 있었다.

하지만 원티드 프리인턴쉽에서는 요구사항을 미리 정해두었고 그 틀에 맞게 코드를 짜야했기떄문에 똑같진않겠지만 간접적으로 회사에서 일을 하면 이런식이겠구나 라는 생각이 들었다.

과제에서 요구하는 기능은 크게 로그인 / 로그아웃 / todoList (CRUD) 였다.

중간중간 짜잘하게 유효성검사 토큰관리 disabled 등 요구사항이 있었지만 전체적으로

과제의 구현 난이도는 높지않았다.

구현 난이도가 높지않았기때문에 그 만큼 내가 부족한 부분이 어느부분인지 알 수 있었고 남은 취준기간을 더 열심히 살 수 있는 계기가 된거같다.

원티드 프리인턴쉽 과제를 통해 배운점

1.custom hook을 만들어보았다.

과제에서는 상태를 관리해야하는 변수 , 유효성검사유무를 나타내주는 변수 , input의 상태값을 계속 봐줘야하는 onChange함수가 여러개 필요했기떄문에 hook으로 만들어 재사용성을 높였다.

직접 짜보는건 처음이였는데 hook으로 만들어 코드를 짜니까 처음에는 번거롭다고 생각했지만 개발을 진행 할수록 편하다는 느낌을 받았다.

import { useCallback, useState } from "react";

type UseInputReturnType<T> = [
  T,
  (event: React.ChangeEvent<HTMLInputElement>) => void,
  boolean,
  React.Dispatch<React.SetStateAction<T>>
];

const useInput = <T>(
  initialValue: T,
  validation?: (value: T) => boolean
): UseInputReturnType<T> => {
  const [value, setValue] = useState<T>(initialValue);
  const [error, setError] = useState<boolean>(true);

  const onChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const newValue = e.target.value as unknown as T;
      if (validation && !validation(newValue)) {
        setError(true);
      } else {
        setError(false);
      }

      setValue(newValue);
    },
    [validation]
  );

  return [value, onChange, error, setValue];
};

export default useInput;

2. useCallback , useMemo , react.memo를 통한 리렌더링 최적화

useCallback,useMemo,react,memo을 적극적으로 활용해보았다.

리액트는 VDom 방식으로 업데이트 전의 dom과 업데이트 후 의 dom을 비교해서(diffing)

바뀌는 dom 노드를 기점으로 뿌리노드까지 재 렌더링이 된다. 전부 다 렌더링이 된다면 불필요한 리렌더링이 발생하게 되는데 그떄 발생하는 리렌더링을 최소화해주는게 useCallback , useMemo , react.memo 이다. 이번 과제에서 애매했던 개념을 다시 학습해보는 기회가 되었다.

import React from "react";
import { NonClickedTodoProps } from "../../types/todo";
import "./index.scss";
const NoClickedTodo = ({
  todo,
  retouchHandler,
  deleteTodo,
  id,
  isCompleted,
  checkBoxhandle,
}: NonClickedTodoProps) => {
  return (
    <div className="nonClickTodo">
      <li key={id}>
        <label>
          <input
            onClick={() => checkBoxhandle(id)}
            checked={isCompleted}
            type="checkbox"
            readOnly
          />
        </label>
        <span>{todo}</span>
        <div>
          <button
            data-testid="modify-button"
            id={id}
            onClick={() => retouchHandler(id)}
          >
            수정
          </button>
          <button onClick={() => deleteTodo(id)} data-testid="delete-button">
            삭제
          </button>
        </div>
      </li>
    </div>
  );
};

export default React.memo(NoClickedTodo);

3. react-hook-form을 이용하지않고 유효성검사

지금까지는 react-hook-form이라는 form라이브러리에 의존해서 쉽게 유효성검사를 할 수 있었는데 이번에는 특정 라이브러리를 제외한 다른 라이브러리를 제한해서 hook-form없이 유효성 검사를 해야했다.

export const emailValidation = (email: string) => {
  const pattern = /@/;
  if (pattern.test(email)) {
    return true;
  } else {
    return false;
  }
};

export const passwordValidation = (password: string) => {
  const pattern = /^.{8,}$/;
  if (pattern.test(password)) {
    return true;
  } else {
    return false;
  }
};

이렇게 validation 함수를 만들어서 위에 useInput의 인자에 넣어서 커스텀 훅으로 함께만들어 주었다. 생각보다 어렵진않았지만 한번 만들어보면서 도움이 많이 된것같다.

4. todo의 로직구현

CRUD를 많이 해봤다고 생각했지만 생각해보니까 CRUD중에 CRD만 많이해봤지 업데이트는 해보지않았고 생각보다 가장 번거로워서 생각을 많이 했었던 로직이다.

코드를 보면 지금봐도 별로지만 일단 구현한걸로 만족하고 나중에 리팩토링을 해봐야겠다.

//todo를 업데이트해주는 함수입니다.
  const updateTodo = useCallback(
    async (e: React.MouseEvent<HTMLButtonElement>) => {
      let id = e.currentTarget.id;
      let findTodo = todos.find((todo) => todo.id == id);
      if (findTodo) {
        try {
          const result = await updateTodoApi(
            editInput,
            findTodo.isCompleted,
            findTodo.id
          );
          let newTodo = todos.map((todo) =>
            todo.id == result.data?.id ? result.data : todo
          );
          setTodo(newTodo);
          setClickId("");
        } catch (e) {
          console.log("실패ㅜㅜ");
        }
      }
    },
    [editInput, todos]
  );
export const updateTodoApi = async (
  todo: string,
  isCompleted: boolean,
  id: string
) => {
  const token = localStorage.getItem("token");
  return await instance.put(
    `/todos/${id}`,
    {
      todo,
      isCompleted,
    },
    {
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
        withCredentials: true,
      },
    }
  );
};

마치며

이 과제를 진행하는 짧은 기간동안 내가 부족한 부분이 너무나 많이보여서 열심히해야겠다.

부족한 부분을 찾고 고쳐야겠다는 생각이 들어서 다행이다.

profile
자바스크립트를 좋아합니다.

0개의 댓글