소북소북(2023~2024)

2023-10-31 소북소북 | user 관련 기능 구현(react-hook-form, redux-toolkit, 페이지 별 권한 설정)

기뮹정 2023. 10. 31. 13:35

react-hook-form + Typescript + MUI

  • 꼬박 하루를 열심히 싸운 부분 ㅠ 일단 열심히 구글링을 해가면서 공부한 부분은 포스팅으로 정리했다.
  • https://codekyz.tistory.com/73
 

react-hook-form에서 useController사용하기(feat.제네릭)

들어가며 프로젝트를 진행하다 보니 이제는 기본적인 UI작업을 끝내고 실질적인 기능구현이 필요한 차례가 되었다. 가장 기본적으로 로그인을 구현해야 하는데 폼 요소를 컨트롤 하는 것에서

codekyz.tistory.com

  • 다른 것 보다 MUI를 쓰면서 텍스트필드 자체를 공통 컴포넌트로 빼버리고 거기다가 Typescript를 적용하려니까 props Type 관련해서 가장 어려웠다.
  • 사실 잘 작성된 코드를 찾아서 거의 가져다 쓴 다음에 그 코드를 이해할 수 있도록 공부했다. 완벽히 마스터 했다곤 볼 수 없고 그냥 간단한 폼 검증 구현까지 할 수 있게 되었다.

form field rules : 정규 표현식

  • 정규 표현식은 다 까먹어서 계속 강의 하나 듣고 정리하려 했는데 미루고 미루다 보니 프로젝트에서 닥쳐서 공부했다.
  • 아이디나, 닉네임, 자기소개 부분은 간단하고,,, 비밀번호랑 이메일 부분이 제일 어려웠다.
  • 비밀번호는 영문(대소문자), 숫자, 특수문자를 필수로 넣어야 하며 6~15자까지 허용한다. validate를 이용해 현재 비밀번호 확인 필드의 value와 위에서 입력한 비밀번호가 일치하는지 확인한다.
  • 이메일은 영문(대소문자),숫자,"-_."(안들어가도 됨)을 허용하고 중간에 "@" 다시 앞부분이랑 반복 "." 뒤에는 영문(대소문자)로 2~3자만 허용한다.
  • 일단 정규표현식으로 다 때려넣긴 했는데 "@"를 기준으로 나눠서 텍스트 필드를 넣는 편이 보기 좋을 것 같다. 추후에 수정하는 걸로.
// 비밀번호 check
rules={{
	required: true,
	pattern: /^(?=.*?[a-zA-Z])(?=.*?[0-9])(?=.*?[#?!@%^&+-]).{6,15}$/,
	validate: (value) => value === getValues("password"),
}}

// 이메일
rules={{
	required: true,
	pattern:/^[a-zA-Z0-9]([-_.]?[a-zA-Z0-9])*@[a-zA-Z0-9]([-_.]?[a-zA-Z0-9])*\.[a-zA-Z]{2,3}$/,
}}

  • 그래도 나름 에러메세지까지 표시 되도록 구현해두었다.
  • 텍스트 필드 스타일링 까지 맞게 해주면 좋겠지만 이것도 넘 세세해서 나중으로ㅠ

redux-toolkit 설정

  • redux 설정은 처음에 어떤 state를 redux로 관리해야 할지 잘 모르겠어서 고민을 많이했다.
  • 하지만 구현하면서 필요하다고 느껴지면 하나씩 추가하는 걸로 하고 일단 기본적으로 user정보는 여러 페이지에서 필요로 하기 때문에 설정을 해두었다.
  • Typescript를 사용하기 때문에 타입 정보를 착실히 기입하고 user state의 interface는 @types 폴더에 따로 빼두었다.
  • store를 설정하고 slice를 만들어서 필요한 reducer를 작성하고 사용하는 흐름은 이해를 했지만 근본적으로 이걸 써야할 필요가 있을까 라는 고민은 계속 하고 있다.
  • 사실 이게 없어도 구현이 될 것 같은데,,,? 요런 생각. 하지만 엄청나게 props로 전달해대는건 또 아닌 것 같고,,,🙄
  • 참 그리고 아무 생각 없이 로컬에서 테스트 하면서 새로고침을 해댔는데 자꾸 store의 정보가 없어지는 것이었다! 그런데 생각해보니 SPA이라 주소창에 주소가 바뀌긴 하지만 페이지 이동할 때 컴포넌트만 바뀌는건데 새로고침하면 휘발되는건 당연한거 아닌가,, 하고 새삼 깨닳았다. SPA, MPA, CSR, SSR 정리가 필요하다.

페이지 별 접속 권한 설정

  • 페이지 별로 접속 권한을 설정하는 부분도 고민을 많이 했다.  HOC를 만들어서 모든 페이지를 둘둘 싸버릴지,,,
  • 그런데 접속 권한이 없어서 강제로 이동 될 때 MUI snackbar를 넣고 싶어졌다! 그래서 컴포넌트를 새로 만들기로 했고 상위 라우터를 추가해서 권한에 따라 그냥 <Outlet />을 보여주거나 snackbar를 보여주고 이동 시키는 방법을 택했다.
  • 새로 만든 컴포넌트는 어느 폴더에 넣을지 고민되어서 그냥 pages 밑에 auth폴더를 만들어서 때려 넣었다.

  • 페이지는 이렇게 구성되어있고 접근 권한에 따라 나누어 놓고 상위 라우터를 추가해주었다.

  • 권한이 없어 페이지 강제 이동될 때는 아래와 같이 배경에 blur 효과를 주고 snackbar를 띄웠다. 설정한 시간이 지나면 자동으로 이동되기도 하고 창을 닫아도 이동된다.

기타 기능 구현(follow, user page)

  • follow기능은 데이터가 없어서 고민하다가 이것도 샘플 데이터를 추가해서 구현했다.
  • 현재 로그인한 유저의 follow목록에 해당 유저가 있으면 "언팔로우"를 보여주고 없으면 "팔로우"를 보여준다.
  • 버튼을 누르면 기존 상태에 따라 follow 목록에서 해당 유저를 삭제하거나 추가한다.

  • User Page에서는 상태가 두가지로 나뉜다. 현재 로그인한 유저 본인의 페이지의 접속한 경우, 다른 사람의 페이지의 접속한 경우,,,
  • 상태에 따라 팔로우 버튼이 아예 보이지 않도록 구현했고 정보수정/탈퇴 메뉴에는 본인의 페이지일 경우에만 표시되도록 하고 접속을 제한하는 부분이,,, 생각해보니 빼 먹었다. 이부분은 추후 수정하기✨
  • 아무튼 맨 첫 페이지에서는 간단한 유저 프로필과 유저의 서재, 독서 기록 정보가 3개까지만 표출된다.
  • 이후 탭 메뉴를 통해 이동하면 전체 서재, 독서 기록 정보를 제공한다.

  • 컴포넌트를 따로 빼서 작성한 부분이라 props로 미리보기 여부를 받아서 선택적으로 filter를 적용하도록 했다.
{props.userBookList
	.filter((bookItem, index) => (props.isPreview ? index < 3 : bookItem))
	.map((bookItem) => (
    ...
)}

할일

  • fe/feat/
    • library : 기능 구현 - Dialog 꼬인거 제일 먼저 고치기, progress Component 기능 구현
    • feed : Pagenation 구현
    • reaction : comment 부분 기능 구현
    • search : 카카오 도서 검색 api 연동 구현
    • sociallogin : 카카오 로그인, 구글 로그인 구현
  • 코드 확인하고 주석 달기

💥주저리주저리

지지난주 수요일(18일)날 팀플 모임을 가지고 UI는 마무리를 했는데 기능 구현을 시작하는데 일주일이 걸렸다.

여행+감기 때문에ㅠ 27일부터 다시 코딩을 열심히 했다. 그래도 user 관련 기능은 거의 구현을 했고 미리 기능을 정리해둬서 순서대로 찬찬히 구현하면 이번주 안에는 얼추 될 듯 싶다. 물론 어딘가에서 막혀서 쩔쩔매지 않는 다는 가정하에😣

내일 또 팀플 모임이 있기 때문에 만나면 api 연동해서 테스트해볼 수 있게끔 정리해야 한당.