올해 nextjs로 개발하면서 form, input에 대해 고민 없이 개발을 했던 제가 이번 빅프로젝트를 통해서 배운 것을 정리했습니다. 제가 사용한 패키지들이 다소 에이블러분들에게 생소하실 수 있으니, 경험이 없으시면 넘어가시는 것을 추천드립니다.
사용한 패키지
- nextjs
- typescript
- redux-toolkit
- tailwindcss
- shadcn/ui
- react-hook-form, zodResolver, zod
- axios
추가 설명으로 사용
- @tanstack/react-query
구현 과정
shadcn/ui과 useForm, zod 설정
위와 같이 zodResolver를 사용하기 위해서 설정을 해주어야 합니다. Validation을 zod로 설정해주는 것입니다. 추가로 Interface도 설정하여 응답을 받거나, 요청을 보낼때의 타입도 설정했습니다.
useForm에 타입을 넣어주고 zodResolver에 스키마를 넣어주면 끝입니다. 여기서 제가 이해가 되지 않았던 것은 defaultValues를 적지 않으면 작동은 되지만 콘솔에 에러가 발생했었습니다.
컴포넌트 마운트시 작동 로직 (tanstack/react-query)
위와 같이 useQuery를 리턴하는 customHook을 만들었지만 사용하지 않았습니다. 그 이유는 profile 페이지에 자주 접근하지 않을 뿐더러, 캐싱을 해야하는 이유가 없었기 때문입니다.
useForm에 defaultvalues로 빈 문자열로 초기화 했던 것을 useEffect를 통해 프로필 정보를 GET요청 후 form.setValue를 통해서 값을 넣어주었습니다.profileImage와 description은 경우에 따라서 없는 경우도 있기 때문에 삼항연산자를 사용했습니다.
프로필 이미지 미리보기
react-hook-form으로 file type은 처음 써봤었는데, onChange를 통해서 state를 관리했고, 인덱싱을 통해서 항상 파일이 1개만 들어가도록 처리했습니다. 여기서 setImageFile을 하게 되면 imageFile에 실제 파일이 담기게 됩니다.
알아보니 자바스크립트에서 Blob과 File 내장 클래스가 있다는 것을 알게 되었고, Blob과 File은 기본적으로는 동일하지만 File이 상위 클래스이며 좀 더 추가정보가 들어있었습니다. 저는 그래서 useState에 File | undefined로 타입을 주었습니다.
이미지 미리보기를 구현하는 것은 저에게 낯설었는데 찾아보니 URL interface로 가능했습니다. imageFile과 imageUrl을 useState로 만들고, imageFile이 있을 때 imagePreview를 만들어주도록 했습니다. 만약에 imagePreview가 있을 때는 URL.revokeObjectURL 매소드를 통해서 메모리 누수를 처리했습니다.
당시 백엔드에서 데이터베이스에 null 허용을 하지 않도록 했어야 했는데, 유저가 회원가입을 했을 때 처음에는 profileImage가 null로 채워지다보니, 프론트에서 예외처리를 추가적으로 위 이미지처럼 해줘야하는 불편함이 있었습니다. 이미지가 없는 경우에는 public 폴더에 있는 이미지가 보여지고, 이미지를 업로드했거나, 이미 프로필이미지가 존재하면 해당 이미지가 보여지도록 했습니다.
백엔드로 요청
try, catch를 통해서 예외처리를 해주고, profileData로 요청 보낼 데이터를 IProfileInfoForm 타입 설정과 함께 생성했습니다. if문을 통해서 description과 profileImage를 예외처리 해주고, 이미지가 있는 경우에는 아래 이미지에 있는 encodeFileToBase64 함수를 통해서 변환 후에 값을 넣었습니다.
보내줄 데이터가 완성된 후에는 updateProfile 함수를 통해서 PATCH 요청이 성공했을 때, router.reload()를 통해 새로고침을 해주고, toast UI를 보여주도록 했습니다.
Promise와 FileReader를 사용해서 resolve, reject로 비동기 처리를 해주었습니다. 오랜만에 코드를 봤더니 mimeType을 제거해주는 것 같아서 이렇게 해야 작동했던 것인지 기억이 나지 않네요... 이 함수를 만들면서 생각보다 자바스크립트의 여러 API에 대해 제가 지식이 없다는 것을 느꼈습니다.
요청을 보낼 때는 CORS 설정과 Django의 crsf token 설정을 포함하여 요청을 보내야하기 때문에, axios instance를 import 해서 썼습니다.
onSubmit 함수에서 검증을 거치지만 if 문으로 한번더 검증을 거친 후에 PATCH요청을 보내고 응답으로 true, false가 나오는 함수를 만들어서 최종 구현을 해서 작동되는 것을 확인했습니다.
최종 구현 UI
출처
https://www.react-hook-form.com/api/useform/setvalue/
https://www.taeny.dev/file-object
https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable
https://github.com/orgs/react-hook-form/discussions/10091
'Experience > - KT AIVLE School' 카테고리의 다른 글
KT AIVLE School 빅프로젝트 - 웹캠 영상 녹화 시 에러 경험 (0) | 2023.07.19 |
---|---|
KT AIVLE School 빅프로젝트 - 프론트에서 S3의 GET요청을 대기하는 로직 (0) | 2023.07.19 |
KT AIVLE School 빅프로젝트 - 배포 과정 정리 (0) | 2023.07.19 |
KT AIVLE School 빅프로젝트 - 개발 환경 설정 (0) | 2023.07.19 |
KT AIVLE School 빅프로젝트 - Django와 React 소통하기 (0) | 2023.07.19 |
AIVLE School 17주차 정리 - 미니프로젝트 7차 (0) | 2023.05.27 |
댓글