티스토리 뷰
오랜만에 javasript를 쓰게 되어서 재미는 있었는데 헷갈리는 부분들이 있어 정리해보고자 한다.
🍥 html 구성
<form action="/signup_post" method="post">
<div class="direction-row">
<input class="input" type="id" name="id" placeholder="아이디" required>
<button type="button" class="check-btn" id="id-check-btn">중복<br>확인</button>
</div>
<div id="id-check-msg">
</div>
<div class="direction-row margin-bottom">
<input class="input " type="password" name="pw" placeholder="비밀번호(영문, 숫자, 특수기호)" required>
<div class=""></div>
</div>
<div class="direction-row">
<input class="input pw-confirm-input" type="password" placeholder="비밀번호를 한번 더 입력해주세요" required>
<button class="check-btn" id="pw-check-btn">pw<br>확인</button>
</div>
<div id="pw-check-msg">
</div>
<div class="email-container">
<input class="email-input" name="email" type="text" placeholder="이메일">
@
<input class="email-input" name="email-domain" type="text" placeholder="직접 입력">
</div>
<input class="tel-container" name="tel" type="tel" placeholder="휴대폰 번호">
<input class="submit-btn" type="submit" value="회원가입">
</form>
회원가입 시 구성 화면의 form은 아이디, 비밀번호, 이메일, 휴대폰 번호를 받게 해두었다.
css까지 적용한 모습은 이렇다.
일단 전체적인 틀로는 아이디 중복확인 버튼을 눌러서 중복확인이 아닌 것과 pw 확인을 한 것, 두 가지 경우를 성립했을 때 회원가입 폼을 제출할 수 있게 하도록 구상했다.
그래서 구현할 부분은
1. 아이디 중복확인
2. pw 확인
이라고 생각했다...!
🍥 아이디 중복 확인
먼저 Flask로 아이디를 중복 확인 할 수 있는 코드를 작성했다.
@application.route("/check_id", methods=["POST"])
def check_id():
data = request.get_json()
user_id = data.get("id")
if DB.user_duplicate_check(user_id):
return {"exists": False}
else:
return {"exists": True}
/check_id로 접근했을 때 js에서 request한 data를 받고 기존에 database.py에 작성된 user_duplicate_check를 이용하여 존재유무를 리턴해주면 되는 짧은 코드였다.
그래서 js에서는 아래와 같은 코드를 작성했다!!
const idCheckBtn = document.querySelector('#id-check-btn');
const idCheckMsg = document.querySelector('#id-check-msg');
let isIdValid = false;
async function checkId(event){
event.preventDefault(); // 기본 동작 방식
// 사용자가 input에 입력한 id
const idInput = document.querySelector("input[name='id']").value;
try{
const response = await fetch("check_id", {
method: "POST",
headers: {
"Content-Type" : "application/json",
},
body: JSON.stringify({id: idInput}),
});
const result = await response.json();
if(result.exists){
isIdValid = false;
console.log("중목");
idCheckMsg.innerHTML="중복된 아이디입니다."
} else {
isIdValid = true;
idCheckMsg.innerHTML="사용가능한 아이디입니다."
}
} catch(error){
console.error("Error:", error);
alert("아이디 확인 중 문제가 발생했습니다.");
isIdValid = false;
}
}
idCheckBtn.addEventListener("click", checkId);
여기서는 버튼을 누르면 입력한 아이디가 db 내에 중복되어 있는지 확인할 수 있게 isIdValid 변수를 지정했다.
isIdValid가 true면, 중복된 아이디가 아니라는 뜻이다. 그리고 사용자가 이를 확인할 수 있게 isIdValid의 값이 바뀔 때마다 아이디 input 아래에 중복된 아이디인지 사용가능한 아이디인 메시지가 나오게끔 innerHTML을 사용해주었다.
사실 여기서 고쳐야 할 부분이 많은데 그건 아래에서 다시 고쳐보기로 하고 먼저 기본적인 걸 정리 해보겠다!
🍥 async / await
사실 위의 글이나 다른 글들에도 잘 설명되어 있지만 내 방식대로 적어보는 것도 도움이 되니까 정리해보겠다!
async와 await는 비동기 작업을 위해서 사용된다.
동기 작업은 작업들이 순차적으로 진행되는 것이다.
1번 코드 실행 -> 완료-> 2번 코드 실행 -> 완료
비동기 작업은 1번 코드를 실행되고 끝날 때까지 기다릴 필요 없이 2번 코드를 먼저 실행할 수 있는 것이다.
어쨌든 일반적인 웹사이트를 만들 때는 순차적으로 진행이 되어버리면, 페이지 로딩에 굉장한 시간이 들 수 있으니까 비동기 작업을 사용할 수 밖에 없다.
async는 해당 함수가 비동기 작업을 하고 promise를 반환할 수 있게 해준다.
await는 async 함수 내에서 사용하는 문법으로 promise를 반환하는 경우에 붙여주고
이렇게 await을 붙인 경우에는 해당 promise의 상태가 바뀔 때 이후 코드를 실행하게 해준다.
그래서 내가 작성한 코드에서 살펴보자면,
async function checkId(event){
event.preventDefault(); // 기본 동작 방식
// 사용자가 input에 입력한 id
const idInput = document.querySelector("input[name='id']").value;
try{
const response = await fetch("check_id", {
method: "POST",
headers: {
"Content-Type" : "application/json",
},
body: JSON.stringify({id: idInput}),
});
const result = await response.json();
데이터베이스에 무조건 접근을 해야 하고 데이터를 불러오는 작업에서 기다려야하는 작업이 진행되므로 async / await를 쓰게 되었다. 그리고 버튼을 누르면 기본 동작으로 페이지가 리로드가 되는데 이러면 우리가 적은 소중한 개인정보가 날아가버리니까 preventDefault()를 작성했다! idInput에 입력한 id 값을 담고 request를 보낸다. 아까 Flask로 구현한 checkId에서 현재 id를 확인하게 된다! stringfy를 이용해서 json으로 변환하여 request를 보낸다. 그리고 다시 json으로 결과값을 받는다. 보내고 받는 과정에서 시간이 걸리니까 await를 쓴거다.
🍥 비밀번호 확인
const pwCheckBtn = document.querySelector('#pw-check-btn');
const pwCheckMsg = document.querySelector('#pw-check-msg');
let isPwValid = false;
function checkPw(event){
event.preventDefault();
const pwInput = document.querySelector("input[name='pw']").value;
const pwConfirmInput = document.querySelector(".pw-confirm-input").value;
if(pwInput != pwConfirmInput){
pwCheckMsg.innerHTML="일치하지 않는 비밀번호입니다.";
isPwValid = false;
} else {
pwCheckMsg.innerHTML="비밀번호 확인 완료.";
isPwValid = true;
}
}
이건 그냥 진짜 간단하다! 비밀번호 입력 input이랑 확인 input 값이 같으면 해당되는 메시지를 보여주고 변수에 저장만 하면 된다.
🍥 전체적으로!
function handleFormSubmit(event){
if(!isIdValid){
event.preventDefault();
alert("아이디 확인이 필요합니다.");
} else if (!isPwValid){
event.preventDefault();
alert("비밀번호 확인이 필요합니다.");
} else {
alert("이화마켓의 회원이 되셨습니다!");
signupForm.submit();
}
}
isIdValid == true && isPwValid == true 이 두 개의 요건을 충족될 경우에 submit을 허용할 수 있게 작성하였다. 그리고 이걸 form에 이벤트리스너로 달아주었다.
🍥 고쳐야 될 요소를 발견하다...!
아이디 중복 확인을 마치고 isIdValid가 True지만, 다시 input 값을 수정하면 어떻게 될까?
버튼을 누르지 않은 경우엔 그대로 True고 Form을 제출할 수 있다. 다행히 이 부분은 백엔드 단에서 막아두는 코드를 작성해두었지만 비밀번호와 같은 경우에는 isPwValid가 true인 상태에서 버튼을 누르지 않고 pw input을 바꾸어도 form이 제출된다는 문제점이 있었다... 당시에는 생각을 못했는데 하굣길에 생각이 나서 수정해보았다.
중복확인 버튼이나 pw 확인 버튼을 누르고 나서 input 값을 수정하면 isIdValid, isPwValid 가 false가 되고 나타나는 메시지도 초기화하는 방식으로 만들었다.
그래서 추가한 코드는 아래와 같다.
const idInputField = document.querySelector("input[name='id']");
const pwInputField = document.querySelector("input[name='pw']");
const pwConfirmInputField = document.querySelector(".pw-confirm-input");
function resetIdValidity() {
isIdValid = false;
idCheckMsg.innerHTML = "";
}
function resetPwValidity() {
isPwValid = false;
pwCheckMsg.innerHTML = "";
}
idInputField.addEventListener("input", resetIdValidity);
pwInputField.addEventListener("input", resetPwValidity);
pwConfirmInputField.addEventListener("input", resetPwValidity);
그러면 이제 원활하게 작동된다 >,<
사실 여기서 더 수정할 부분이 많기는 하다. email 주소 유효성 검사나 전화번호 유효성 검사도 해야되고 앞으로 아이디 찾기 비밀번호 찾기 이메일을 database에 보낼 때 domain이랑 email id 이어 붙이는 것도 해야 되고 그냥.. 많다 ...
😨🧟♂️ ... 그래도 파이팅 ...
🍥 js 전체 코드
const idCheckBtn = document.querySelector('#id-check-btn');
const signupForm = document.querySelector('form');
const pwCheckBtn = document.querySelector('#pw-check-btn');
const idCheckMsg = document.querySelector('#id-check-msg');
const pwCheckMsg = document.querySelector('#pw-check-msg');
const idInputField = document.querySelector("input[name='id']");
const pwInputField = document.querySelector("input[name='pw']");
const pwConfirmInputField = document.querySelector(".pw-confirm-input");
let isIdValid = false;
let isPwValid = false;
async function checkId(event){
event.preventDefault(); // 기본 동작 방식
// 사용자가 input에 입력한 id
const idInput = document.querySelector("input[name='id']").value;
try{
const response = await fetch("check_id", {
method: "POST",
headers: {
"Content-Type" : "application/json",
},
body: JSON.stringify({id: idInput}),
});
const result = await response.json();
if(result.exists){
isIdValid = false;
console.log("중목");
idCheckMsg.innerHTML="중복된 아이디입니다."
} else {
isIdValid = true;
idCheckMsg.innerHTML="사용가능한 아이디입니다."
}
} catch(error){
console.error("Error:", error);
alert("아이디 확인 중 문제가 발생했습니다.");
isIdValid = false;
}
}
function checkPw(event){
event.preventDefault();
const pwInput = document.querySelector("input[name='pw']").value;
const pwConfirmInput = document.querySelector(".pw-confirm-input").value;
if(pwInput != pwConfirmInput){
pwCheckMsg.innerHTML="일치하지 않는 비밀번호입니다.";
isPwValid = false;
} else {
pwCheckMsg.innerHTML="비밀번호 확인 완료.";
isPwValid = true;
}
}
function resetIdValidity() {
isIdValid = false;
idCheckMsg.innerHTML = "";
}
function resetPwValidity() {
isPwValid = false;
pwCheckMsg.innerHTML = "";
}
function handleFormSubmit(event){
if(!isIdValid){
event.preventDefault();
alert("아이디 확인이 필요합니다.");
} else if (!isPwValid){
event.preventDefault();
alert("비밀번호 확인이 필요합니다.");
} else {
alert("이화마켓의 회원이 되셨습니다!");
signupForm.submit();
}
}
idCheckBtn.addEventListener("click", checkId);
pwCheckBtn.addEventListener("click", checkPw);
idInputField.addEventListener("input", resetIdValidity);
pwInputField.addEventListener("input", resetPwValidity);
pwConfirmInputField.addEventListener("input", resetPwValidity);
signupForm.addEventListener("submit", handleFormSubmit);
'project' 카테고리의 다른 글
[캡스톤디자인 - Adultree] 크롤링해서 얻은 텍스트, 이미지를 파일로 저장하여 google drive api를 이용해 drive에 업로드하기 (0) | 2024.11.25 |
---|