원티드 프리온보딩 프론트엔드 챌린지 사전 과제 개선
2023.1.9 ~ 2023.1.20
[코드 리팩토링 2-2차]
소스 폴더 구조
📦src
┣ 📂api
┃ ┣ 📂auth
┃ ┃ ┗ 📜auth.ts
┃ ┗ 📂todo
┃ ┃ ┣ 📜createTodo.ts
┃ ┃ ┣ 📜deleteTodo.ts
┃ ┃ ┣ 📜getTodoById.ts
┃ ┃ ┣ 📜getTodos.ts
┃ ┃ ┗ 📜updateTodo.ts
┣ 📂components
┃ ┣ 📂auth
┃ ┃ ┣ 📂views
┃ ┃ ┃ ┣ 📜SignInView.tsx
┃ ┃ ┃ ┗ 📜SignUpView.tsx
┃ ┃ ┣ 📜SignIn.tsx
┃ ┃ ┗ 📜SignUp.tsx
┃ ┣ 📂common
┃ ┃ ┣ 📂view
┃ ┃ ┃ ┣ 📜HeaderView.tsx
┃ ┃ ┃ ┣ 📜ModalView.tsx
┃ ┃ ┃ ┗ 📜NoticeView.tsx
┃ ┃ ┣ 📜Header.tsx
┃ ┃ ┣ 📜Modal.tsx
┃ ┃ ┗ 📜Notice.tsx
┃ ┗ 📂toDo
┃ ┃ ┣ 📂views
┃ ┃ ┃ ┣ 📜ChangeTodoView.tsx
┃ ┃ ┃ ┣ 📜CreateTodoView.tsx
┃ ┃ ┃ ┗ 📜GetTodosView.tsx
┃ ┃ ┣ 📜ChangeTodos.tsx
┃ ┃ ┣ 📜CreateTodo.tsx
┃ ┃ ┗ 📜GetTodos.tsx
┣ 📂hook
┃ ┣ 📂auth
┃ ┃ ┗ 📜useAuth.tsx
┃ ┣ 📂mutation
┃ ┃ ┣ 📜useCreate.tsx
┃ ┃ ┣ 📜useDelete.tsx
┃ ┃ ┗ 📜useUpdate.tsx
┃ ┗ 📂query
┃ ┃ ┗ 📜useGetTodoById.tsx
┣ 📂screen
┃ ┣ 📜Home.tsx
┃ ┣ 📜Login.tsx
┃ ┗ 📜NotFound.tsx
┣ 📂types
┃ ┣ 📂auth
┃ ┃ ┗ 📜auth.ts
┃ ┣ 📂common
┃ ┃ ┣ 📜header.ts
┃ ┃ ┣ 📜modal.ts
┃ ┃ ┗ 📜notice.ts
┃ ┗ 📂toDo
┃ ┃ ┗ 📜todo.ts
┣ 📜Root.tsx
┣ 📜Router.tsx
┣ 📜atom.ts
┣ 📜index.tsx
┣ 📜react-app-env.d.ts
┣ 📜setupProxy.js
┣ 📜setupTests.ts
┗ 📜until.ts
값을 변경했을 때, 변경된 값을 바로 적용시키는 것 ✅
(이미 손을 봐두었는데, 컴포넌트를 분리하면서 오류가 나는 것 같다.)
(if문 때문에 걸려서 빈 값으로 설정되고 있었다.)
url로 접근 시에 token 확인 ✅
(로그아웃 후에도 접근해서 삭제가 가능한 것을 확인했다.)
변경된 값이 없을 시 안내 메세지 로직 수정 ✅
추가적인 리팩토링 및 파일 구조 ✅
sign up api 요청 시 useMutation 이용 🆗
(불필요하다고 판단했다. useMutation을 이용할 수도 있지만, 이미 커스텀 훅을 통해 sign in, sign up을 메서드로 묶어놓았기 때문에 이걸 또 해체할 필요는 없어보인다.)
로그인 상태로 토큰을 삭제하여 할 일 상세 목록을 클릭했을 때 로그인 페이지로 리다이렉트 시키기 ✅
회원가입 비밀번호 유효성 검사 로직 추가 ✅
404 페이지 추가 ✅
변경 전
const ChangeToDoProps: IChangeTodoProps = { onSubmit(e) { ... if (newToDo.title === "") setNewToDo({ ...newToDo, title: toDo?.title || "" }); if (newToDo.content === "") setNewToDo({ ...newToDo, content: toDo?.content || "" }); setNewToDo({ title: "", content: "" }); setActionType("update"); setIsOpen(true); },
변경 후
const ChangeToDoProps: IChangeTodoProps = { onSubmit(e) { ... if (titleRef) { const titleValue = titleRef?.current?.dataset.set; if (newToDo.title === titleValue) return setNoticeMsg("값이 변경되지 않았습니다."); if (newToDo.title === "") { setNewToDo({ ...newToDo, title: titleValue || "" }); } } if (contentRef) { const contentValue = contentRef?.current?.dataset.set; if (newToDo.title === contentValue) return setNoticeMsg("값이 변경되지 않았습니다."); if (newToDo.content === "") { setNewToDo({ ...newToDo, content: contentValue || "" }); } } setActionType("update"); setIsOpen(true); },
변경 사항이 제대로 즉각 반영이 안되었다. 구체적으로 말하면, 값이 반영되지 않고 빈항목으로 나온다는 점이었는데, 이걸 고쳐보았다.
컴포넌트를 분리하면서 발생한 것이 아닌 if문
을 건드리면서 나타난 에러인데, 빈 값이 저장되고 있었다.
예를 들어, title의 값은 바꾸지 않고 content의 값만 바꾼다고 가정했을 때, title의 값은 "" 빈 값이다. 때문에 건드리지 않은 값은 빈 값으로 저장되었다. 즉, toDo의 값이 비었기 때문에 빈 항목이 저장되던 것.
이것을 보다 확실하게 잡아주기 위해 useRef를 사용하여 값을 가져오기로 했다. 다른 방법도 존재하겠지만 나는 이것을 DOM 요소에 dataset으로 저장해주고 가져왔다.
값이 변경되지 않았다면 기존 값(dataset의 값)을 저장해준다.
차라리 변경되지 않았다면, 값 저장을 하는 게 아닌 아예 건드리지 않고 return 시키는 방법도 괜찮을 것 같다.
이렇게 사용해도 자잘한 버그는 있어서 이에 대한 새로운 해결책이 필요해보인다. (띄어쓰기를 하거나 등등의 자잘한 버그)
조건 렌더링과 6번 이슈로 해결했다.
1번 이슈와 동일한 이슈이다. 안내 메세지만 수정을 했다.
불필요하다고 판단했다. useMutation을 이용할 수도 있지만, 이미 커스텀 훅을 통해 sign in, sign up을 메서드로 묶어놓았기 때문에 이걸 또 해체할 필요는 없어보인다.
const [isLoggedIn, setIsLoggedIn] = useRecoilState(isLogged);
const params = useParams();
const setNoticeMsg = useSetRecoilState(noticeMsgAtom);
const navigator = useNavigate();
useEffect(() => {
if (localStorage.getItem("token")) {
return setIsLoggedIn(true);
} else {
return setIsLoggedIn(false);
}
}, [isLoggedIn]);
useEffect(() => {
if (params.id && !localStorage.getItem("token")) {
setNoticeMsg("로그인을 해주세요.");
return navigator("auth");
}
}, [params.id]);
전역 상태 관리로 로그인 상태를 관리한다.
주소가 바뀔 때마다, token을 확인하고 토큰이 없다면 알림과 함께 로그인 페이지로 redirect 시켜준다.
useEffect로 로그인 상태를 관리해주는 로직이 두 개인데, 동일한 내용이 보인다.
setIsLoggedIn을 사용해 로그인 페이지로 redirect 시켜줘도 좋을 것 같다.
onChange: (e) => {
const {
currentTarget: { name, value },
} = e;
const password = name === "password" && value;
const confirmPassword = name === "confirmPassword" && value;
if (password && password.length < 8) {
setPasswordNotice("비밀번호는 8자리 이상 작성해주세요.");
} else {
setPasswordNotice(null);
}
if (confirmPassword && password !== confirmPassword) {
setConfirmNotice("비밀번호가 같지 않습니다.");
} else {
setConfirmNotice(null);
}
setUser({ ...user, [name]: value });
},
confirm password를 추가하여 비밀번호 확인을 한 차례 더 거친다. 같지 않다면 비밀번호가 같지 않다고 알림을 띄워준다.
if문에서 에러가 발생하겠지만 확실하게 하기 위해 return 값으로 함수를 종료시키는 게 좋아보인다.
잘못된 페이지에 접근 시 404 페이지를 보여준다.
블로그로 작성하는 건 코드를 작성하고 시간이 좀 지난 뒤라 기억을 더듬어보았다. 확실히 코드를 작성한 뒤에 바로 블로그를 하는 게 좋지만, 아직은 그게 어렵다. 시간적인 문제나 코드를 치고 난 뒤에는 쉬고 싶은 마음이 큰 것 같다.
개선 사항은 더 남았지만 큰 줄기는 제거했다.
제대로 코드를 작성해본 것 같아 즐거웠고 앞으로도 이 때의 경험을 기억해두며 해당 코드 작성법으로 진행해야겠다.