본문 바로가기
프론트앤드/[React]

[React] 로그인 구현 + 비밀번호 보이게 기능 코드정리

by 헬리이 2023. 3. 27.
728x90

 

기업협업중이다.

 

로그인 페이지부터 맡았는데, westagram 을 하고 난 뒤 그 후로는 카카오로그인을 맡았던 터라.. (?) 

구현하는방법이 긴가민가..했다

 

그래서 기억기억 🤨 여차저차 생각해냈다!

 

 

기억난 김에 블로그에 정리해야지 🙋🏻‍♀️

 

일단 처음에 적은 코드이고, 여기서는 

 

 

백엔드와 해야하는 통신을 하는 로직은 주석처리해서 따로 여기에 적지는 않았다! 

//Login.jsx

const Login = () => {
  const navigate = useNavigate();

  const [inputId, setInputId] = useState('');
  const [inputPw, setInputPw] = useState('');
  const [showPw, setShowPw] = useState(false);

  const saveUserId = e => {
    setInputId(e.target.value);
  };
  const saveUserPw = e => {
    setInputPw(e.target.value);
  };

//useEffect로 백엔드와으 통신은 일단 주석처리!

return (
    <div>
      <h1>로그인</h1>
      <input
        name="id"
        type="text"
        placeholder="아이디"
        value={inputId}
        onChange={e => {
          saveUserId(e);
        }}
      />
      <input
        name="pw"
        type={showPw ? 'text' : 'password'}
        placeholder="비밀번호"
        value={inputPw}
        onChange={e => {
          saveUserPw(e);
        }}
      />
      <div>
        <input type="checkbox" />
        <label>로그인 상태 유지</label>
      </div>
      {inputId.length > 1 && inputPw.length > 1 ? (
        <button onClick={goToHome} disabled={false}>
          <span>로그인</span>
        </button>
      ) : (
        <button disabled={true}>
          <span>로그인</span>
        </button>
      )}

      <Link to="/signup">
        <button>회원가입</button>
      </Link>
    </div>
  );
};

export default Login;

이 코드를 좀 더 간단하게 할 수 없을까 해서 

열심히 찾아낸 끝에 정리된 코드

 

const [input, setInput] = useState({ id: '', pw: '', showPw: false });

  const saveInput = e => {
    setInput(prevInput => ({ ...prevInput, [e.target.name]: e.target.value }));
  };

  const toggleShowPw = () => {
    setInput(prevInput => ({ ...prevInput, showPw: !prevInput.showPw }));
  };
  
  return (
    <div>
      <h1>로그인</h1>
      <input
        name="id"
        type="text"
        placeholder="아이디"
        value={input.id}
        onChange={saveInput}
      />
      <input
        name="pw"
        type={input.showPw ? 'text' : 'password'}
        placeholder="비밀번호"
        value={input.pw}
        onChange={saveInput}
      />
      <button onClick={toggleShowPw} />
      <div>
        <input type="checkbox" />
        <label>로그인 상태 유지</label>
      </div>
      <button
        onClick={() => goToHome(input.id, input.pw)}
        disabled={input.id.length < 2 || input.pw.length < 2}
      >
        <span>로그인</span>
      </button>
      <Link to="/signup">
        <button>회원가입</button>
      </Link>
    </div>
  );
};

export default Login;

 

 

자 이제 뭐가 다른지 한번 보자! 

 

//첫번째로 한 코드 : 쓸데없이 비슷한 코드를 나열해서 적음 = 가독성X

const Login = () => {
  const navigate = useNavigate();

  const [inputId, setInputId] = useState('');
  const [inputPw, setInputPw] = useState('');
  const [showPw, setShowPw] = useState(false);

  const saveUserId = e => {
    setInputId(e.target.value);
  };
  const saveUserPw = e => {
    setInputPw(e.target.value);
  };
//두번째 코드 : 가독성 좋게 정리된 코드 

const [input, setInput] = useState({ id: '', pw: '', showPw: false });

  const saveInput = e => {
    setInput(prevInput => ({ ...prevInput, [e.target.name]: e.target.value }));
  };

  const toggleShowPw = () => {
    setInput(prevInput => ({ ...prevInput, showPw: !prevInput.showPw }));
  };

 

설명

 

1)

 const [inputId, setInputId] = useState('');
 const [inputPw, setInputPw] = useState('');
 const [showPw, setShowPw] = useState(false);

=>

const [input, setInput] = useState({ id: '', pw: '', showPw: false });

첫 번째 코드에서 id,pw그리고 비밀번호 보이기를 구현하기 위해 useState가 3번 쓰였다면,

 

두 번째 코드에서는 input에 3개의 useState가 1번만으로도 구현이 가능했다. 

 

 

 

 

 

2)

  const saveUserId = e => {
    setInputId(e.target.value);
  };
  const saveUserPw = e => {
    setInputPw(e.target.value);
  };
  
  
  =>
  
   const saveInput = e => {
    setInput(prevInput => ({ ...prevInput, [e.target.name]: e.target.value }));
  };

첫 번째 코드처럼 saveUserId, Pw를 따로 두지 않고,

두 번째에는 saveInput 으로 통일해서 onChange 이벤트에 의해 호출되며, e 인자로 이벤트 객체를 받는다.

 

 

 

const saveInput = e => { setInput(prevInput => ({ ...prevInput, [e.target.name]: e.target.value })); };

여기서  setInput 함수는  prevInput을 이용하여 이전 input 객체를 복사하고 ,

이전 input 객체의 속성 중에서 변경할 속성만 새 값으로 덮어쓴 새로운 input 객체(saveInput)을 만들었다. 

 

 

이렇게 함으로써, 이전 input 객체를 직접 수정하지 않고도 새로운 객체를 만들어서 상태를 갱신할 수 있어졌고, 

이전 input 객체를 복사하는 방법으로, 스프레드 연산자 ... 를 사용했다.

 

{ ...prevInput } 구문은 이전 input 객체를 복사한 새 객체를 만들고,

이후에, [e.target.name]: e.target.value 구문은 새 객체에 [e.target.name] 속성에 e.target.value 값을 덮어쓴 새 객체를 만든다.

 

이렇게 새 객체를 만든 후, setInput 함수에 전달하여 input 상태를 갱신한다. 

 

 

따라서, 이 코드는 input 필드의 값이 변경될 때마다 saveInput 함수가 호출되어 새로운 input 객체를 만들고, 이를 setInput 함수로 전달하여 컴포넌트의 상태를 갱신하는 코드이다.

 

 

완전 새로웠자나...

 

 

 

특히, 

[e.target.name]: e.target.value

이 부분이 이해가 안되었는데, 

 

Computed property names라는 자바스크립트 문법 중 하나였다.

 

 

📌 이 문법을 사용하면 객체의 속성 이름을 동적으로 설정할 수 있다고한다!!!!

 

여기서 e.target.name은 이벤트 객체에서 발생한 요소의 name 속성 값이고,

위의 코드에서는  id input 필드에서 e.target.name은 'id'가 되고, pw input 필드에서는 'pw'가 되는데,

 [e.target.name]은 Computed property names 문법을 사용하여, 이벤트 객체에서 발생한 요소 (e.target.value) 의 name 속성 값을 속성 이름으로 설정하겠다는 뜻이라고 한다. 

 

즉,  e.target.value는 입력된 값을 가져와 해당 속성에 저장하겠다는 뜻이다! 

 

 

따라서

[e.target.name]: e.target.value 구문은 이벤트 객체에서 발생한 요소의 name 속성 값을 속성 이름으로, value 값을 속성 값으로 하는 새 객체를 만들겠다는 뜻이라고 한다.

 

이를 사용하여, 입력된 값이 어떤 input 필드의 값인지에 따라서 해당 필드의 값을 input 상태 객체에 저장할 수 있다!

 

이렇게 정리를 하니 이해가 가는군 👏👏

 

 

 

 

 

3. 

비밀번호 보이게/안보이게

  const toggleShowPw = () => {
    setInput(prevInput => ({ ...prevInput, showPw: !prevInput.showPw }));
  };

toggleShowPw 함수는 비밀번호 입력 필드에서 입력된 값을 보이거나 숨기는 역할을 하게 로직을 구현해 보았다.

 

 

함수 내부에서는 이전 input 객체를 복사한 후(...prevInput을 이용), showPw 값을 반전시켜서 새로운 객체를 생성하고, setInput 함수를 사용하여 상태를 갱신하도록 했다.

 

 

여기서 중요한 부분은, setInput 함수를 호출할 때 함수 인자로 이전 input 객체를 복사한 것인데,

이전 input 객체를 직접 변경하지 않고, 이전 객체를 복사한 후 새로운 값을 덮어쓰는 방식으로 상태를 갱신하면, React에서 상태 변경을 감지하여 컴포넌트를 다시 렌더링할 때 불필요한 렌더링을 방지할 수 있다고 한다.

 

 

여기서도 쓰인, 스프레드 연산자

 { ...prevInput } 구문은 이전 input 객체를 복사한 새 객체를 만드는 것이다.

 

 

마지막으로, showPw 값을 반전시키기 위해서 !prevInput.showPw 를 사용했다.

이전 input 객체의 showPw 속성 값을 불리언 반전 연산자 ! 를 사용하여 반전시키면, showPw 속성 값이 true 이면 false 가 되고, false 이면 true 가 된다.

 

 

 

 


구현했던 코드를 가독성 좋게 구현하고, 쓰면서 복습하니 머리에 좀 들어온것 같다! 

 

다음에는 혼자 할 수 있도록 마스터하쟈 👀🙏🏻

 

 

728x90