🚀
HTML, CSS, JavaScript를 이용해서 간단한 회원가입 폼을 만들어 보았습니다. 폼을 제작하고 자바스크립트로 형식 체크라던가, 커서이동, 에러표시, 문자인증 토큰발행과 인증확인, 버튼의 활성화, 비활성화와 같은 DOM조작을 하였습니다.
🔗 아래의 페이지에서 회원가입 창을 실제로 테스트 해보실 수 있습니다
https://k-junyyy.github.io/SIGN-UP-PAGE/signup.html
🔨 구현한 기능
✔️ 맨 처음 disabled 속성을 주어 인증번호 전송, 인증 확인, 가입하기 버튼 클릭 방지
✔️ 지역 선택란에서 초기값은 "지역을 선택하세요"로 하며, "지역을 선택하세요"는 선택 불가
✔️ 성별은 남성, 여성 둘 중 하나만 선택 가능
✔️ 휴대폰 번호 입력 시 3자리, 4자리, 4자리로 입력할 수 있도록 구현
✔️ 첫째 칸 3자리 입력 시 둘째 칸으로 포커스(커서) 이동
✔️ 둘째 칸 4자리 입력 시 셋째 칸으로 포커스(커서) 이동
✔️ 셋째 칸 4자리 입력 시 인증번호 전송 버튼 활성화
✔️ 인증번호 전송 버튼 클릭 시 토큰 생성 및 타이머 실행, 인증 확인 버튼 활성화
✔️ 3분 이내 인증 확인 버튼 클릭 시 "인증이 완료되었습니다" 알림 띄우기
✔️ 3분 동안 버튼을 누르지 않는 경우 인증번호 전송 버튼과 인증 확인 버튼 비활성화
✔️ 문자인증 후 토큰 정보를 "000000", 시간을 "03:00"으로 초기화
✔️ 인증 확인 시 인증 확인 버튼을 "인증 완료"로 변경, 가입하기 버튼 활성화
✔️ 가입하기 버튼 클릭 시 이메일, 이름, 비밀번호, 비밀번호 확인, 지역, 성별 확인
✔️ 가입 시 이메일 형식("아이디"+@+"서버")을 준수하는지 판별
✔️ 가입 시 비밀번호와 비밀번호 확인이 일치하는지 비교
✔️ 가입 시 각 입력창에서 조건에 맞지 않는다면 입력창 아랫부분에 빨간 글씨로 에러 표시
✔️ 조건을 모두 만족시키고 가입하기 버튼 클릭 시 입력창 아래 에러 제거 후 가입 확인 메시지 띄우기
전화번호 부분(3자리, 4자리, 4자리) 입력 시 인증번호 전송 버튼이 활성화됩니다.
인증번호 전송 버튼 클릭 시 토큰이 발행되고 3분의 제한시간이 주어집니다.
(아래의 코드에선 빠르게 테스트해보기 위해 1초를 50ms로 설정하였습니다.)
인증확인 버튼을 클릭하면 인증번호전송 버튼과 인증확인 버튼이 비활성화 되고
인증확인 버튼의 값이 "인증완료"로 바뀌게 됩니다.
가입하기 클릭 시 위와같이 이메일 형식이 맞지 않는다거나 이름 누락, 비밀번호와 비밀번호확인이 일치하지 않음, 지역 미선택, 성별 미선택 등등 입력이 올바르지 않다면 빨간 글씨로 에러를 표시해줍니다.
형식을 올바르게 입력하고 가입하기 버튼을 클릭하면 가입이 완료되었다는 메시지를 표시하도록 하였습니다.
📋 코드
<signup.html>
<!DOCTYPE html>
<html lang="ko">
<head>
<title>회원가입 페이지</title>
<link href="signup.css" rel="stylesheet" />
<script src="signup.js"></script>
</head>
<body>
<div class="wrapper">
<div class="title"><h1 style="font-size: 21px;">회원가입</h1></div>
<div class="email">
<input id="email" type="text" placeholder="이메일을 입력해 주세요.">
<div id="emailError" class="error"></div>
</div>
<div class="name">
<input id="name" type="text" placeholder="이름을 입력해 주세요.">
<div id="nameError" class="error"></div>
</div>
<div class="password">
<input id="password" type="password" placeholder="비밀번호를 입력해 주세요.">
<div id="passwordError" class="error"></div>
</div>
<div class="passwordCheck">
<input id="passwordCheck" type="password" placeholder="비밀번호를 다시 입력해 주세요.">
<div id="passwordCheckError" class="error"></div>
</div>
<div class="phone">
<input id="phone1" type="text" size="1" maxlength="3" oninput="changePhone1()"> -
<input id="phone2" type="text" size="3" maxlength="4" oninput="changePhone2()"> -
<input id="phone3" type="text" size="3" maxlength="4" oninput="changePhone3()">
</div>
<div class="auth">
<div id="certificationNumber">000000</div>
<button disabled id="sendMessage" onclick="getToken()">인증번호 전송</button>
</div>
<div class="timer">
<div id="timeLimit">03:00</div>
<button disabled id="completion" onclick="checkCompletion()">인증확인</button>
</div>
<div class="area">
<select id="area">
<option selected disabled>지역을 선택하세요.</option>
<option>서울</option>
<option>인천</option>
<option>경기</option>
</select>
<div id="areaError" class="error"></div>
</div>
<div class="gender">
<input id="gender_man" type="radio" name="gender">남성
<input id="gender_woman" type="radio" name="gender">여성
<div id="genderError" class="error"></div>
</div>
<div class="line">
<hr>
</div>
<div class="signUp">
<button id="signUpButton" disabled onclick="signUpCheck()">가입하기</button>
</div>
</div>
</body>
</html>
<signup.js>
// 휴대폰 번호 입력 부분
function changePhone1(){
const phone1 = document.getElementById("phone1").value // 010
if(phone1.length === 3){
document.getElementById("phone2").focus();
}
}
function changePhone2(){
const phone2 = document.getElementById("phone2").value // 010
if(phone2.length === 4){
document.getElementById("phone3").focus();
}
}
function changePhone3(){
const phone3 = document.getElementById("phone3").value // 010
if(phone3.length === 4){
document.getElementById("sendMessage").focus();
document.getElementById("sendMessage").setAttribute("style","background-color:yellow;")
document.getElementById("sendMessage").disabled = false;
}
}
// 문자인증+타이머 부분
function initButton(){
document.getElementById("sendMessage").disabled = true;
document.getElementById("completion").disabled = true;
document.getElementById("certificationNumber").innerHTML = "000000";
document.getElementById("timeLimit").innerHTML = "03:00";
document.getElementById("sendMessage").setAttribute("style","background-color:none;")
document.getElementById("completion").setAttribute("style","background-color:none;")
}
let processID = -1;
const getToken = () => {
// 인증확인 버튼 활성화
document.getElementById("completion").setAttribute("style","background-color:yellow;")
document.getElementById("completion").disabled = false;
if (processID != -1) clearInterval(processID);
const token = String(Math.floor(Math.random() * 1000000)).padStart(6, "0");
document.getElementById("certificationNumber").innerText = token;
let time = 180;
processID = setInterval(function () {
if (time < 0 || document.getElementById("sendMessage").disabled) {
clearInterval(processID);
initButton();
return;
}
let mm = String(Math.floor(time / 60)).padStart(2, "0");
let ss = String(time % 60).padStart(2, "0");
let result = mm + ":" + ss;
document.getElementById("timeLimit").innerText = result;
time--;
}, 50);
};
function checkCompletion(){
alert("문자 인증이 완료되었습니다.")
initButton();
document.getElementById("completion").innerHTML="인증완료"
document.getElementById("signUpButton").disabled = false;
document.getElementById("signUpButton").setAttribute("style","background-color:yellow;")
}
// 가입부분 체크
function signUpCheck(){
let email = document.getElementById("email").value
let name = document.getElementById("name").value
let password = document.getElementById("password").value
let passwordCheck = document.getElementById("passwordCheck").value
let area = document.getElementById("area").value
let gender_man = document.getElementById("gender_man").checked
let gender_woman = document.getElementById("gender_woman").checked
let check = true;
// 이메일확인
if(email.includes('@')){
let emailId = email.split('@')[0]
let emailServer = email.split('@')[1]
if(emailId === "" || emailServer === ""){
document.getElementById("emailError").innerHTML="이메일이 올바르지 않습니다."
check = false
}
else{
document.getElementById("emailError").innerHTML=""
}
}else{
document.getElementById("emailError").innerHTML="이메일이 올바르지 않습니다."
check = false
}
// 이름확인
if(name===""){
document.getElementById("nameError").innerHTML="이름이 올바르지 않습니다."
check = false
}else{
document.getElementById("nameError").innerHTML=""
}
// 비밀번호 확인
if(password !== passwordCheck){
document.getElementById("passwordError").innerHTML=""
document.getElementById("passwordCheckError").innerHTML="비밀번호가 동일하지 않습니다."
check = false
}else{
document.getElementById("passwordError").innerHTML=""
document.getElementById("passwordCheckError").innerHTML=""
}
if(password===""){
document.getElementById("passwordError").innerHTML="비밀번호를 입력해주세요."
check = false
}else{
//document.getElementById("passwordError").innerHTML=""
}
if(passwordCheck===""){
document.getElementById("passwordCheckError").innerHTML="비밀번호를 다시 입력해주세요."
check = false
}else{
//document.getElementById("passwordCheckError").innerHTML=""
}
// 지역선택 확인
if(area === "지역을 선택하세요."){
document.getElementById("areaError").innerHTML="지역을 선택해주세요."
check = false
}else{
document.getElementById("areaError").innerHTML=""
}
// 성별체크확인
if(!gender_man && !gender_woman){
document.getElementById("genderError").innerHTML="성별을 선택해주세요."
check = false
}else{
document.getElementById("genderError").innerHTML=""
}
if(check){
document.getElementById("emailError").innerHTML=""
document.getElementById("nameError").innerHTML=""
document.getElementById("passwordError").innerHTML=""
document.getElementById("passwordCheckError").innerHTML=""
document.getElementById("areaError").innerHTML=""
document.getElementById("genderError").innerHTML=""
//비동기 처리이벤트
setTimeout(function() {
alert("가입이 완료되었습니다.")
},0);
}
}
<signup.css>
* {
margin: 0px;
box-sizing: border-box;
font-size: 11px;
}
html {
width: 100%;
display: flex;
justify-content: center;
padding-top: 20px;
padding-bottom: 20px;
}
body {
width: 45%;
border: 1px solid black;
}
input{
border: 1px solid black;
border-radius: 3px;
line-height: 35px;
font-size: 12px;
padding-left: 10px;
padding-right: 10px;
}
.wrapper {
padding: 10px;
}
div {
padding-top: 3px;
padding-bottom: 8px;
}
.title {
text-align: center;
font-weight: 700;
}
.email input {
width: 100%;
}
.name input {
width: 100%;
}
.password input {
width: 100%;
}
.passwordCheck input {
width: 100%;
}
.phone {
display: flex;
justify-content: space-between;
line-height: 35px;
}
#phone1 {
width: 18%;
}
#phone2 {
width: 30%;
}
#phone3 {
width: 30%;
}
.auth {
display: flex;
justify-content: space-between;
}
.timer {
display: flex;
justify-content: space-between;
}
.auth div {
width: 30%;
text-align: center;
font-weight: 700;
font-size: 15px;
}
.auth button {
width: 70%;
}
.timer div {
width: 30%;
text-align: center;
font-weight: 700;
font-size: 15px;
}
.timer button {
width: 70%;
}
.area select {
width: 100%;
height: 40px;
}
.gender {
text-align: center;
}
.signUp button {
width: 100%;
cursor:pointer;
}
button{
cursor: pointer;
height: 30px;
}
.error{
font-size: 1px;
height: 20px;
color:red;
font-weight: 700;
}
🔗 GitHub 저장소 링크
https://github.com/K-Junyyy/SIGN-UP-PAGE
'🌐WEB' 카테고리의 다른 글
[CSS] 선택자에서 꺽쇠 > 의 의미는? (자식 선택자, 하위 선택자) (4) | 2022.02.10 |
---|---|
[CSS] 하단바, 하단영역 고정하는 방법 (1) | 2022.01.31 |
[CSS3] CSS 포지션(position) 잡기 - static, absolute, fixed, relative (0) | 2021.10.11 |
[CSS3] 텍스트가 영역을 벗어날 때 해결법 (overflow 속성) (0) | 2021.10.11 |
[CSS3] 텍스트를 꾸미는 CSS 요소들 정리 (0) | 2021.10.11 |