You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
올바르지 않은 예 ) feat: 카카오 로그인 연동 기능을 추가했다, 혹은 추가함 (#3)
옳은 예 ) feat: 카카오 로그인 연동 기능 추가 (#3)
주제는 소스 코드를 보지 않고도 변경 사항이 무엇인지 알 수 있도록 작성해야 한다.
올바르지 않은 예 ) design: CSS 조정 (#4)
옳은 예 ) design: text box와 layout frame 사이에 left padding 추가 (#4)
커밋 메시지는 제삼자가 봤을 때 무엇을 했는지 파악할 수 있게 자세히 작성한다.
커밋 메시지는 어떻게 보단 무엇과 왜를 설명한다.
한 커밋에는 한 가지 기능만 담는다.
예 ) 화면 개발의 경우 : 컴포넌트 단위로 커밋
예2 ) 기능 개발의 경우 : 각 기능 단위로 커밋
3-1-3. 커밋 메세지
- fix: 올바르지 않은 동작을 고친 경우
- feat: 새로운 기능을 추가한 경우
- refactor: 내부 로직은 변경하지 않고 코드를 개선한 경우
- style: 코드 개선과 상관없이 사소하게 코드를 수정한 경우
- design: 사용자 UI를 추가, 수정한 경우 (마크업, 퍼블리싱 작업)
- add: 폴더, 파일 등을 추가한 경우
- move: 폴더, 파일, 코드 등의 위치를 이동한 경우
- rename: 폴더명, 파일명 등을 수정한 경우
- remove: 폴더, 파일, 코드 등을 삭제한 경우
- assets: 에셋을 추가, 수정한 경우
- docs: 문서를 추가, 수정한 경우
- chore: 위의 모든 경우에 포함되지 않는 기타 수정사항
3-2. 협업 방식
- 공통 이슈만들고, 공유하고 싶은 문제가 있는 경우 이슈로 작성하여 공유하고 작업한 이력 남기기
useEffect(()=>{if(!['email','accountname'].includes(id))return;if((id==='email'&&!EMAIL_REGEX.test(formData.email))||(id==='accountname'&&!ID_REGEX.test(formData.accountname))||formData['accountname']===userAccountname// 프로필 수정 페이지에서 현재 로그인한 유저의 accountname인 경우 이미 가입된 계정이라는 에러 메세지를 보여주지 않기 위함){return;}consterrorMsg=id==='email' ? '이미 가입된 이메일 주소 입니다.' : '이미 가입된 계정ID 입니다.';consttimer=setTimeout(()=>{checkDuplication(errorMsg);},300);return()=>{clearTimeout(timer);};},[formData.email,formData.accountname]);
email과 accountname만 중복 검사를 진행하기 때문에 id가 다른 값이 되면 return을 합니다.
그 다음 formData.email, formData.accountname이 변경될 때마다 실행이 됩니다.
조건문을 통해 입력된 이메일과 계정 ID의 형식이 올바른지 확인한 뒤, formData.accountname이 현재 로그인한 사용자의 계정 ID와 일치하지 않는지 확인 후, 만약 조건에 해당하지 않는다면 함수를 종료합니다.
그 이외에, 중복된 이메일 또는 계정 ID 에러 메시지를 설정하고, 300밀리초 후에 checkDuplication 함수를 호출합니다. timer 변수에는 setTimeout 함수로 생성된 타이머 ID가 저장되며, clearTimeout을 사용하여 타이머 취소가 가능합니다.
useEffect의 반환 함수는 해당 이펙트가 정리(clean-up)될 때 실행하고, 여기서 타이머를 취소하기 위해 clearTimeout을 호출합니다.
디바운싱 기능을 적용함으로써 사용자가 입력할 때마다 서버요청을 하지 않기에 통신 비용이 발생하지 않습니다.
이미지 업로드를 위한 커스텀 훅
import{useState}from'react';import{uploadImages}from'../api/image';constALLOWED_EXTENSIONS=['.jpg','.gif','.png','.jpeg','.bmp','.tif','.heic'];constMAX_SIZE=10*1024*1024;constuseImagesUpload=()=>{const[images,setImages]=useState([]);constonUpload=async(files,length)=>{if(images.length+length>3)returnalert('이미지는 최대 3개까지 업로드 할 수 있습니다.');constformData=newFormData();for(leti=0;i<length;i++){constfile=files[i];constfileExtension=file.name.split('.').pop().toLowerCase();if(ALLOWED_EXTENSIONS.includes(`.${fileExtension}`)&&file.size<=MAX_SIZE){formData.append('image',file);}}try{constdata=awaituploadImages(formData);constfilenames=data.map((data)=>data.filename);setImages((prev)=>[...prev, ...filenames]);}catch(error){console.log(error.message);}};constonDelete=(index)=>{setImages((prevImages)=>{constupdatedImages=[...prevImages];updatedImages.splice(index,1);returnupdatedImages;});alert('삭제되었습니다.');};return{ images, onUpload, onDelete };};exportdefaultuseImagesUpload;
이미지 업로드는 특성상 회원가입 시 프로필 설정, 프로필 수정, 게시글 작성, 상품 등록 등 여러 페이지에서 반복적으로 사용됩니다. 그래서 여러 이미지를 업로드 할 수 있는 상태를 선언하고, 새롭게 들어오는 이미지들과 기존 이미지를 합친 값이 3이 넘으면 더 이상 업로드 할 수 없도록 구현합니다.
FormData 객체를 생성하고, files 배열을 순회하면서 허용되는 확장자 목록과 이미지 사이즈를 검사한 뒤, 통과한다면 formData에 image 라는 키 값으로 파일을 추가할 수 있습니다.
그 다음 uploadImages 함수를 통해 서버에 이미지를 업로드하고, 서버 응답에서 파일명을 추출하여 상태를 업데이트하고, setImages 함수를 사용해 이전 상태값인 prev 배열과 새로운 파일명 배열인 filenames를 합쳐서 상태를 갱신합니다.
이렇게 함으로써, 이미지 업로드 후의 상태값을 업데이트하고 React 컴포넌트가 리렌더링될 수 있도록 합니다.