[PROJECT 1] 햄릿증후군을 위한 술자리 결정 웹 서비스 #2 회원가입

세나정·2023년 1월 11일
0
post-thumbnail

사용 데이터베이스 : mongoDB Atlas

디자인 : 부트스트랩 v5.2.2 을 활용하였고 필요시에 CSS를 따로 생성하여 디테일한 작업을 진행하였습니다.

본인은 디자인 외 백, 프론트 풀스택의 작업을 맡았기 때문에 본 코드리뷰엔 CSS는 생략하도록 하겠습니다.


- 회원가입 (Singup.js)

(로그인 form 하단 회원가입 링크)

우선 메인페이지는 로그인을 하지 않았을시(토큰 값 미존재 시) login 페이지로 GNB없이 깔끔히 나오도록 디자인을 하였고 로그인이 되어있는 상태라면 메인페이지는 주류를 선택하는 창이 나오게 됩니다.

회원가입 UI

  • ID 중복시 & 비밀번호 확인 불일치시
  • ID 미중복시 & 비밀번호 확인 일치시

- ID

	<label class="p-3 font-500">ID</label>
    <input type="text" class="form-control form-control-lg mb-3 rounded-pill" 
    placeholder="사용할 아이디를 입력하세요." value={id} onChange={idHandler}></input>

                   
    <div class="d-grid d-md-flex justify-content-md-end">
    	<button class="btn mt-2 gap-2 col-md-4 press_btn"
              onClick={(e) => {
                    e.preventDefault();
                    CHECK_ID();
                    setIdchk(true);}}>
                      중복확인
        </button>
    </div>

-- idHandler

idHandler 같은 경우 미리 선언된 State를 활용하여 onChange를 통해 id값을 변경

  let [id, setId] = useState("");
  
  const idHandler = (e) => {
    e.preventDefault();
    setId(e.target.value);
  };

-- CHECK_ID

[클라이언트]
  async function CHECK_ID() {
    let body = {
      id: id,
    };
    try {
      await axios.post("api/signup/checkID", body).then((res) => {
        console.log("검사여부 : " + res.data);
        {
         res.data === "존재" ? alert("이미 존재하는 아이디입니다.") : alert("아이디가 사용이 가능합니다.");
        }
      });
    } catch (err) {
      console.log(err);
    }
  }

body 변수에 idHandler를 통해 받아온 값을 넣은 후에 axios를 통하여 서버에 비동기처리를 활용한 post요청을 보냅니다.
그 후, 서버는 들어온 body값이 db에 이미 존재하는 ID라면 "존재"라는 값을 전달하고 그게 아니라면 "미존재"라는 값을 전달하여 줍니다.
에러처리를 통하여 에러가 발생시 어떠한 에러인지 확인할 수 있도록 했습니다.

[서버]
// express & node 활용
app.post("/api/Signup/checkID", function (요청, 응답) {
  db.collection("login").findOne({ 아이디: 요청.body.id }, function (에러, 결과) {
    if (결과) {
      응답.json("존재");
    } else {
      응답.json("미존재");
    }
    
    if (에러) return console.log(에러);
  });
});

서버로부터 응답을 받은 후, 3항 연사자를 통하여 alert 경고문을 띄웠고 동시에 catch를 통해 에러처리를 하였습니다.


- NickName

GNB에서 회원정보에 나올 닉네임으로 옵션으로 기입할 수 있습니다. 기입하지 않을시 GNB에는 본인의 아이디가 나오게 되고 기입하면 기입한 닉네임으로 나옵니다.
추후 닉네임이 변경가능하도록 하였기 때문에 건너뛰어도 무방합니다.

  // idHanderl와 동일
  const nameHandler = (e) => {
    e.preventDefault();
    setName(e.target.value);
  };
  <label class="p-3 font-500">Username</label>
  <input type="text" class="form-control form-control-lg mb-3 rounded-pill" 
  placeholder="닉네임을 입력하세요. (추후 변경가능합니다.)" value={name} onChange={nameHandler}></input>

- Password

          <label class="p-3 font-500">Password</label>
          <input
              type="password"
              class="form-control form-control-lg rounded-pill"
              placeholder="사용할 비밀번호를 입력해 주세요."
              value={pw}
              onChange={pwHandler}
              onClick={(e) => {
                 e.preventDefault(e);
              }}></input>
          <input type="password" class="form-control form-control-lg mt-3 rounded-pill" 
          placeholder="다시 비밀번호를 입력하세요."
          onChange={pwConfirm} />
          
          <div id="alert">
              <h6 id="errormessage">{pwmessage}</h6>
          </div>
          
          <div class="d-grid gap-2 col-md-11 mx-auto">
             <button onSubmit={submitHandler} class="btn btn-lg press_btn mt-5 gap-2" 
             type="submit" disabled={ispwconfirm}>
                      회원가입 완료
             </button>
          </div>

-- pwHandler

idHandler, nameHandler와 동일

-- pwConfirm

  // 패스워드 검사 메세지
  let [pwmessage, setPwmessage] = useState("");

  // 검사완료 확인
  let [ispwconfirm, setIspwconfirm] = useState(true);
  
  const pwConfirm = (e) => {
    const passwordConfirm = e.target.value;

    if (pw === passwordConfirm) {
      document.getElementById("alert").setAttribute("class", "mt-4 alert alert-success alert-dismissible fade show");
      setPwmessage("비밀번호가 일치합니다. 😊 회원가입 버튼을 눌러주세요.");
      setIspwconfirm(false);
    } else {
      document.getElementById("alert").setAttribute("class", "mt-4 alert alert-danger alert-dismissible fade show");
      setPwmessage("비밀번호가 일치하지 않습니다. 😢");
      setIspwconfirm(true);
    }
  };

passwordConfirm이라는 변수에 우리가 입력한 값들이 저장되며 위 input (1차 비밀번호)에 입력 했던 값들은 pw에 저장되어 있으므로 pw와 passwordConfirm을 비교합니다.

만약 일치한다면 state를 통하여 pwmessage의 값을 성공여부로 표기합니다.
또한, 만약 일치한다면 state을 통해 ispwconfirm의 값을 불린 값으로 변경하는데
그 이유는 만약 제대로된 회원가입(비밀번호 불일치)이 이루어지지 않았을시엔
회원가입 완료 버튼을 비활성화 하기 위해서입니다.

-- submitHandler

[클라이언트]
  const submitHandler = (e) => {
    e.preventDefault();
    let body = {
      id: id,
      // pw: btoa(pw), base64로 변경시도 
      name: name,
      pw: pw,
    };
    {
      idchk
        ? axios.post("api/signup", body).then((res) => {
            {
              res.data == "존재함요" ? alert("이미 존재하는 아이디이오니 다른 아이디를 사용하여 주세요.") : navigate("/");
            }
          })
        : alert("반드시 ID 중복 확인을 해주세요.");
    }
  };
  
 [서버]
 app.post("/api/Signup", function (요청, 응답) {
  db.collection("login").findOne({ 아이디: 요청.body.id }, function (에러, 결과) {
    if (결과) {
      응답.json("존재함요");
    } else {
      // 소금 + 해시값 동시 생성 및 DB 적재
      bcrypt.hash(요청.body.pw, saltRounds, (err, hash) => {
        db.collection("login").insertOne({ 아이디: 요청.body.id, 패스워드: hash, 닉네임: 요청.body.name }, function (에러, 결과) {
          if (에러) return console.log(에러);
          응답.redirect("/");
        });
      });
    }
  });
});
  

[클라이언트]
최종으로 제출하기 버튼을 클릭 했을 때 axios를 통해 post 요청을 보내기 위해 body에 우리가 입력한 id, name, pw를 전달합니다.
단, 여기서 id 중복확인을 눌렀어서 idchk의 값이 true로 변경 되어있을 때만 post요청을 보냅니다.
(즉, idchk를 눌렀을 때만 idchk의 값이 true로 변경되어 최종 제출 버튼이 나오므로 중복 확인을 해야만 회원가입 버튼을 누를 수 있습니다.)

중복 검사를 마쳐서 회원가입 버튼이 활성화 되어있더라도 중복된 아이디가 있는 채로 로그인을 누를 시 "이미 존재하는 아이디이오니~"라는 경고를 띄우고, 그게 아니라면 pw를 암호화 한 후에 메인 페이지 (로그인)으로 이동을 합니다.

[서버]
body를 통해 들어온 id가 login 데이터베이스에 존재한다면 결과값이 true가 되기 때문에 클라이언트에 응답으로 "존재함요"를 보내어 존재할시에 아이디가 이미 존재한다고 경고창을 띄우며 메인페이지 (로그인)로 이동을 하지 않습니다.

그 경우가 아닌 id가 데이터베이스에 존재하지 않는다면 들어온 pw를
bcrypt를 통해 해시화 + 솔트값을 뿌린 후 login 데이터베이스에 insertOne을 통해 넣어줍니다.

또한, 응답으로 redirect를 보내어 메인 페이지 (로그인)로 이동을 시킵니다.
(중복 검사를 마친 후 & 아이디가 미존재시 일 경우와 동일)

profile
기록, 꺼내 쓸 수 있는 즐거움

0개의 댓글

관련 채용 정보