저번 회차 때 디자인을 끝내 놓았으니 이제 기능 할 수 있도록 유효성 검사를 해야겠다.
어제 밤까지만 해도 유효성 검사를 백엔드 단에서 해야하나 .. 프론트 단에서 해야하나 .. 고민했는데
프론트 단에서 하는게 좋은 것 같다.
그 이유를 서칭을 통해 알 수 있었는데
POST
요청만 보냄으로서 서버 부하 감소 등에 이유로 클라이언트 사이드 유효성 검사를 하기로 마음 먹었다.
어제 밤에 이런 고민을 했던 것은
"아니 회원 가입 할 때 유효성 검사 해서 가입 시켜두면, 그냥 날리는POST
요청마다 데이터베이스에서 찾기만 하면 되는거 아닌가 .. ?"
이런 생각을 했었다.근데 시간 지나고 생각해보니 모든 요청마다 데이터베이스에서 해당 회원이 존재하는지 확인하는 것 자체가 비용이니까 프론트단에서 해결하는게 맞는 것 같다.
이메일과 비밀번호에 대한 유효성 검사를 하기 위해 기준을 세워보자
이메일의 유효성 검사 표준이 있더라 !
하지만 해당 페이지만 보고 뭘 의미하는지 정확히 알 수 없어 웹에서 서칭해왔다.
정규식(Regex)으로 이메일 주소를 확인하는 방법. 샘플 HTML5, PHP, C#, Python 및 Java 코드.
인터넷 메시지 형식은 로컬 부분 과 도메인 부분 으로 나뉜다.
example123@naver.com
이란 이메일 주소가 있을 때 example123
은 로컬 부분 , naver.com
은 도메인 부분이다.
로컬 부분은 영숫자 문자, 마침표, 하이픈, 더하기 기호 및 밑줄의 조합이 포함 될 수 있으며 도메인 부분은 도메인 이름 (naver
) 과 최상위 도메인 (TLD (Top-Level-Domain)
, 여기서는com
) 으로 구성되어 있다.
TLD
는 일반적인 목적으로 사용되는 도메인인 gTLDs (Generic-Top-Level-Domains)
와 ccTLDs(Country Code Top-Level Domains)
로 나뉜다.
TLD Type | Examples |
---|---|
Generic Top-Level Domains (gTLDs) | .com, .org, .net, .edu, .gov, .mil, .int |
Country Code Top-Level Domains (ccTLDs) | .us, .uk, .de, .jp, .kr, .cn |
이메일 주소 표준화는 생각보다 훨씬 복잡하다
([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\"\(\[\]!#-[^-~ \t]|(\\[\t -~]))+\")
@
([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\[[\t -Z^-~]*])
우웨에에엑
이 부분을 해석해서 해보려고 했는데 아직 정규표현식 짬이 부족하다.
일단 이대로 쓰고 넘어가는걸로 하자
RFC5322
에 정의되어 99.9% 의 이메일들을 모두 잡을 수 있다고 한다.
const regex = new RegExp(
"([!#-'*+/-9=?A-Z^-~-]+(\\.[!#-'*+/-9=?A-Z^-~-]+)*|\"\\(\\[\\]!#-[^-~ \\t]|(\\\\[\\t -~]))+@([!#-'*+/-9=?A-Z^-~-]+(\\.[!#-'*+/-9=?A-Z^-~-]+)*|\\[[\\t -Z^-~]*])",
);
const emails = ['wrong.email', 'example1@naver.com', 'example2@korea.co.kr'];
emails.forEach((e) => {
console.log(`${e} : ${regex.test(e)}`);
});
/**
wrong.email : false
example1@naver.com : true
example2@korea.co.kr : true
*/
해당 정규표현식을 정규표현식 객체를 만들 때 \
기호를 인식시키기 위해 정규표현식의 실제\
앞에 \
를 하나 더 붙여주었다.
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,10}/;
기준은 하나 이상의 영어 대문자 , 하나 이상의 특수기호 , 하나 이상의 숫자가 들어가며 8글자와 13글자 사이의 비밀번호를 검증하는 정규 표현식을 가져왔다.
테스트 해보자
const regex =
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,13}/;
const passwords = ['wrongpassword', 'Password1!', 'pASSWORD@!1'];
passwords.forEach((p) => {
console.log(`${p} : ${regex.test(p)}`);
});
/**
wrongpassword : false
Password1! : true
pASSWORD@!1 : true
*/
구우우웃
아 정규표현식 너무 어렵다
아직 백엔드 하시는분은 존재하지 않지만 가상의 백엔드 팀원을 상상하면서 코드를 작성해봤다.
백엔드 팀원님 : "프론트님 , 로그인 요청 보내기 전에 클라이언트 단에서 유효성 검사 해주시고 맞지 않으면
POST
보내지 말아주세요 , 아 그리고 맞지 않을 시 로그인 화면이 동적으로 변했으면 좋겠어요"
호다닥 호다닥
class Validator {
constructor() {
this.emailRegex = new RegExp(
"^([!#-'*+/-9=?A-Z^-~-]+(\\.[!#-'*+/-9=?A-Z^-~-]+)*|\"\\(\\[\\]!#-[^-~ \\t]|(\\\\[\\t -~]))+@([!#-'*+/-9=?A-Z^-~-]+(\\.[!#-'*+/-9=?A-Z^-~-]+)*|\\[[\\t -Z^-~]*])$",
);
this.passwordRegex = new RegExp(
'^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,13}$',
);
}
checkEmpty(email, password) {
return email.length + password.length !== 0;
}
checkEmail(email) {
return this.emailRegex.test(email);
}
checkPassword(password) {
return this.passwordRegex.test(password);
}
}
이메일과 비밀번호를 검사하는 정규표현식 객체와 검사하는 메소드들이 담긴 Validator
생성자를 생성해준다.
원래는 경고창을
alert
으로 띄우려고 했는데 진짜 너무 못생김
가장 보편적으로 오류가 났음을 나타낼 수 있는 방법은 로그인창이 흔들리는 거라 생각했다.
근데 흔들리기만 하면 재미없으니까 저번 회차에서 배웠던 backdrop-filter
를 사용해보자
.wrong {
backdrop-filter: blur(20px) contrast(200%);
animation: horiznotalMove 0.1s 5 alternate;
}
@keyframes horiznotalMove {
from {
left: -10px;
}
to {
left: 10px;
}
}
wrong
이란 클래스를 가진 태그는 배경색이 투명해지는 것 뿐이 아니라 contrast
값을 올려줘서 강조해주도록 하자
그리고 흔들리기만 하면 뭐가 문제인지 모르니까 텍스트로 문제점을 넣어주도록 하자
.
.
type="password"
autocomplete="off"
required
/>
</div>
<div class="custom-checkbox">
<input type="checkbox" name="remember" id="remember" />
<label for="remember">Remember me</label>
</div>
</form>
<button id="login-button">Login</button>
<div class="footer-text">
Don't have an account? <a href="">Create One</a>
</div>
<div class="error hidden">비밀번호를 확인해주세요</div>
</div>
.
.
.
.error {
text-align: center;
font-size: 20px;
color: red;
opacity: 1;
transition: all 0.2s ease;
}
.hidden {
opacity: 0;
}
가장 하단 부위에 div
태그를 생성해주고 클래스로 error
와 hidden
을 넣어준다.
이후 유효성 검사에 통과하지 못했을 경우 로그인 창에는 wrong
이란 클래스를 추가해줬다가 빼고 error
태그에는 문제점을 적고 hidden
이란 클래스를 제거했다가 넣어주는 함수를 만들자
const Tags = {
$container: document.querySelector('.container'),
$error: document.querySelector('.error'),
};
const wrongInput = (text) => {
const DELAY = 1000;
const { $container, $error } = Tags;
setTimeout(() => {
$container.classList.remove('wrong');
$error.classList.add('hidden');
}, DELAY);
$container.classList.add('wrong');
$error.textContent = text;
$error.classList.remove('hidden');
};
setTImeout
을 이용해서 DELAY
시간 이후에는 원상 복구 시키고 DELAY
시간 전까지는 로그인 박스가 흔들리도록 하는 클래스, 에러창이 눈에 보이게 만들어주었다.
const formChild = {
$email: document.querySelector('#email'),
$password: document.querySelector('#password'),
$remember: document.querySelector('#remember'),
};
const validator = new Validator();
const $loginButton = document.querySelector('#login-button');
$loginButton.addEventListener('click', () => {
const { $email, $password, $remember } = formChild;
const [email, password, remember] = [
$email.value,
$password.value,
$remember.checked,
];
if (!validator.checkEmpty(email, password)) {
wrongInput('아이디와 비밀번호를 모두 입력해주세요');
return;
}
if (!validator.checkEmail(email)) {
wrongInput('이메일 형식을 다시 확인해주세요');
return;
}
if (!validator.checkPassword(password)) {
wrongInput('비밀번호 형식을 다시 확인해주세요');
return;
}
console.log('POST 요청을 보내는중~');
console.log(email, password, remember);
});
그래서 조건에 따라 클래스명과 에러 텍스트를 변경해나가도록 만들었다.
잘 되나 확인해보자
구우우웃~~~
아 참
이전 포스트에서는 Login
버튼을 input type = "submit"
으로 했었는데 button
으로 변경해버렸다.
그 이유는 input type=submit
으로 해버리면 form
의 기본 이벤트인 제출 시 폼이 초기화 되는 문제가 있었다.
그래서 preventDefault
를 써보려고 요리조리 만져보다가 그냥 버튼으로 만들어버렸다.
express
를 이용해서 서버를 만들어서 POST
를 이용해 로그인을 하기 위한 소통까지는 구현했었다.
그런데 이렇게 하다보니 로그인 이후의 페이지를 어떻게 렌더링 시킬지 ?
를 생각하다보니 세션과 쿠키에 대한 공부를 하게 되고
그렇게 하다 답이 안나와 다른 사람들의 코드들을 깃허브에서 엄청 둘러보았다.
보다보니 느낀 점은
내가 혼자 독학으로 하는 것보다 웰메이드 된 코드들을 봐야겠다!!! 라고 생각이 들었다.
내 혼자 스스로 생각한 컴포넌트라는 개념은 실제로 달랐다.
아~ 나는 리액트가 아니라 그래 ~!
이렇게 생각했는데 어떤 분이 바닐라 자바스크립트로 컴포넌트들을 구성한걸 보았다.
와우
m's blog
그래서 일단 로그인 페이지 공부는 여기까지만 하고
다른 사람들의 웰메이드 코드들도 공부하고
어떻게 백엔드와 협업하여 API 를 이용하여 렌더링 하는지 , 세션과 토큰은 어떻게 하고 헤더는 어떻게 날리는지에 대해 더 공부해봐야겠다고 생각했다.
코드만 주구장창 쓰는 것보다 시간을 줄여서 다른 사람들이 이미 개척해나간 길들을 따라
공부해야겠다.
바퀴를 두 번 발명하지 말라는 말이 있었으니까 ..
그리고 느낀점은 많은 모듈들을 다뤄봐야 할 것 같다. 기술 블로그들을 보니 사용하는 모듈들이 최소 5개씩은 넘더라