자란다 기업과제 회고

배포 주소

🔗 자란다 - Team RE4CT

Github 미팅로그


어떻게 협업을 했는가?

7인 팀프로젝트였고, 만들어야할 기능은 크게 로그인/회원가입/관리자 페이지였다.

그래서 로그인팀/회원가입팀/관리자팀으로 2~3명씩 팀을 나눴고,

나는 그 중 회원가입팀에 들어가 혜린님과 함께 작업한 후 작업 내역을 전체에 합쳤다!

으로 프로그래밍 하는 경험, 페어로 프로그래밍 하는 경험을 모두 해볼 수 있었다.

이번 협업에서 배운점, 좋았던 점 👍

  • Rebase와 Squash로 깔끔해진 커밋로그
  • Utils, Constants, GlobalStyles 사용
  • 다른 사람의 코드를 읽고 배우기

완벽한 회원가입 form을 만들기 위한 고군분투 🧐

useInput : Custom Hook 사용하기

import { useState, useRef } from 'react'

export const useInput = (initialValue) => {
  const [value, setValue] = useState(initialValue)
  const onChange = (e) => {
    setValue(e.target.value)
  }
  const inputRef = useRef(null)
  return [value, setValue, onChange, inputRef]
}

이전에 강의에서도 본 적이 있고, 여러 블로그에도 올라와 있는 Custom Hook이다.

리액트에서 Form 관련 라이브러리를 사용하지 않고 Form을 구현하려면, input창 하나마다 각각 state, setState가 필요하고, onChange될 때마다 state를 변경해주는 onChange 함수 로직이 필요하다.

그리고 이번 과제에서는 잘못된 값을 입력한 input창으로 focus를 자동으로 옮겨주는 기능을 구현하고자 했기 때문에 모든 input창에 ref도 필요했다.

const [email, , onChangeEmail, inputEmail] = useInput('')
const [pwd, , onChangePwd, inputPwd] = useInput('')
const [name, setName, , inputName] = useInput('')
const [age, setAge, , inputAge] = useInput('')
const [post, setPost, , inputPostCode] = useInput('')
const [addr, setAddr] = useInput('')
const [extraAddr, setExtraAddr, onChangeExtraAddr] = useInput('')
const [cardNum, setCardNum, , inputCard] = useInput('')

반복적으로 필요한 것들을 묶어 useInput으로 만들어 잘 활용했다!

Daum 우편번호 API 연동

다음 우편번호 API는 사용하기 매우 편리했다.

key를 발급받을 필요도 없고, CDN link 한 줄만 추가해주면 바로 사용이 가능하다.

<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>

npm에 react-daum-postcode라고 더욱더 편리하게 사용할 수 있는 패키지가 있었으나.. 그냥 곧바로 API를 가져와 연동해봤다.

const daum = window.daum // 최상단에 daum을 선언해주어야 한다.

function setDaumAddr({ setPost, setAddr, setExtraAddr }) {
  daum.postcode.load(function () {
    new daum.Postcode({
      oncomplete:  function (data) {
				// 원하는 방식을 API 문서에서 예시코드를 가져와 사용하면 된다.
      },
    }).open()
  })
}

Daum 주소 팝업창 관련 에러가 발생한 경우 여기에서 FAQ를 읽어보거나 issue 탭에서 다른 사용자들이 겪었던 에러를 검색해보면 금방 해결할 수 있다!

주소를 선택해도 팝업창이 닫히지 않는 에러가 있었는데, “주소 검색” 버튼의 type이 “submit” 상태여서 검색을 눌렀을 때 팝업 아래의 부모 페이지가 새로고침 되어, 부모 페이지가 팝업창을 제어할 수 있는 권한을 잃어버리는 문제였다…!

https://github.com/daumPostcode/QnA/issues/596 를 보고 해결할 수 있었다.

내가 겪은 문제는 나만 겪는 문제가 아니라 누군가 이미 겪었던, 앞으로 누군가 겪을 문제라는 것!

개발이 재밌는 이유 중 하나다. 🎮

비밀번호 유효성 검사 UI

Untitled

자란다 홈페이지를 많이 참고하면서 회원가입을 구현했는데,

자란다 홈페이지의 회원가입에서 눈에 띈 부분은 비밀번호 유효성 검사에 대해 사용자가 인지하기 편하게 비밀번호 입력폼 하단에 체크체크 할 수 있는 UI가 있다는 점이었다!

마음에 드는 UI였고 따라해보고 싶어 구현해보았다.

사용자에게 비밀번호 규칙을 직관적으로 알려주면서도, 유효성 검사도 할 수 있는 좋은 UI라는 생각이 들어 재밌게 만들어 볼 수 있었다!

정규식을 사용한 유효성 검사

유효한 값을 입력했는지, 정규식을 활용하여 검사를 했다.

편리한 정규식! good!

const validation = {
isName(data) {
    if (!data) {
      return false
    }
    const reg = /^[가-힣]{2,6}$/
    return reg.test(data)
  },

isAge(data) {
    if (!data) {
      return false
    }
    const reg = /^[1-9]?[0-9]{1}$|^100$/
    return reg.test(data)
  }, 

...
}

useRef로 focus 제어

useRef는 사용할 일이 잘 없는 Hook이라고 생각했는데

focus를 자동으로 이동시키도록 해주기 위해서는 HTML 요소에 접근이 필요했다.

focus가 이동시켜지길 원하는 input 태그에 ref 인자를 추가해주고

inputRef.current.focus();

위와 같이 자동으로 focus를 이동시켜 줄 수 있었다.


내가 만들었지만 아쉬웠던 코드 🤔

const onSubmitHandler = (e) => {
	if (isValidatedUserInfo) {
	      userListStorage.save([...usersInfo, newUserInfo])
	      isValidatedUserInfo && toast(toastMsg.SIGNUP_SUCCESSED)
	      setTimeout(() => {
	        history.push('/login')
	      }, 500)
    }
  }

아쉬운 점 : 비동기 처리에 자신이 없어서 일단 setTimeout을 사용했다

  • setTimeout은 시간을 0.00001초만 주어도 비동기함수로 처리된다

async/await로 해보면 좋지 않았을까?


과제를 마치며…

원래 정해진 기한이 있는 프로젝트를 끝내고 나면 만족감보다는 뭔가 더 잘할 수 있었겠다는 아쉬움이 훨씬 크게 느껴졌었다.

그런데 이번 프로젝트는 팀원들의 합도 잘 맞았고! 결과물이 정말 마음에 들었다.

디자인 (자란다 홈페이지를 clone) 에 신경을 썼고, 추가기능(마이페이지 구현, 관리자 페이지의 섬세한 기능들! 등)을 구현했고, 더 나은 코드에 대한 고민을 하면서 개발해서였던 것 같다. 만족스럽다 🥰


Written by@irisdew
Junior Frontend Developer

GitHub