회원가입 + 로그인 예제
오늘의 포스팅은 회원 가입과 로그인 페이지 제작에 관한 것입니다.
원래대로라면 서버를 사용해서 만들어야겠지만 저는 로컬 기반으로 간단하고 심플하게 만들어보려고 합니다.
간단하게 이름과 이메일, 비밀번호를 입력한 후에 회원 가입을 하고, 로그인을 할 수 있도록 만들 계획입니다.
그리고 로그인 유지와 계정 삭제, 최근에 언제 로그인 했는지에 대해서도 표현해 줄 생각입니다.
1. HTML 코드
이번에는 왼쪽 화면과 오른쪽 화면 2개로 나누어서 진행하였습니다.
왼쪽 화면에는 프로젝트 제목과 설명, 로그인 되어 있는지를 표시해주었습니다.
오른쪽 화면에는 이메일과 비밀번호를 입력할 수 있는 영역을 만들었습니다.
또, 로그인 버튼과 회원 가입 버튼, 비밀번호를 볼 수 있는 버튼, 로그인 유지 체크박스를 추가하였습니다.
회원 가입 버튼을 누르면 팝업창을 띄우고, 정보를 입력할 수 있도록 하였습니다.
2. 회원 가입 및 계정 삭제
회원 가입
- 메인 화면에서 회원 가입 버튼을 누르면 정보를 입력할 수 있는 팝업창이 나타납니다.
- 이름, 이메일, 비밀번호 총 3가지 항목에 대해 사용자가 입력을 한 후 가입하기 버튼을 누르면 가입이 됩니다.
- 이름과 이메일 같은 경우에는 띄어쓰기를 없애기 위해 trim()을 활용하였습니다.
- 3가지 항목을 모두 입력하지 않으면 input 태그의 required 기능을 활용하여 메시지를 전달합니다.
- 사용자가 입력한 비밀번호는 암호화를 하여 저장해줍니다.
- 정보를 다 입력했다면 users[email] 배열에 저장합니다.
- 팝업창이 종료되고, 로그인 화면으로 돌아갑니다.
su_form.addEventListener('submit', async (e) => {
e.preventDefault();
su_msg.textContent = '';
const name = $('su_name').value.trim();
const email = ($('su_email').value || '').trim().toLowerCase();
const pw = $('su_pw').value;
if (!name || !email || !pw) {
su_msg.textContent = '모든 항목을 채워주세요.'; return;
}
if (pw.length < 8) {
su_msg.textContent = '비밀번호는 최소 8자 이상이어야 합니다.'; return;
}
const users = loadUsers();
if (users[email]) {
su_msg.textContent = '이미 등록된 이메일입니다.'; return;
}
const hash = await hashPw(pw);
users[email] = { name, hash, createdAt: new Date().toISOString(), lastLogin: null };
saveUsers(users);
hideModal();
alert('회원가입 완료 — 로그인하세요.');
});
deleteBtn.addEventListener('click', () => {
const email = pfEmail.textContent;
if (!email) return;
if (!confirm('계정을 삭제하시겠습니까? (로컬에서만 삭제됩니다)')) return;
const users = loadUsers();
delete users[email];
saveUsers(users);
clearSession();
profileArea.style.display = 'none';
loginFormWrap.style.display = '';
updateStatusLeft(false);
alert('계정이 삭제되었습니다.');
});
계정 삭제
- 로그인 상태에서 계정 삭제 버튼을 누르면 계정 삭제가 이루어집니다.
- 한번 더 삭제가 된다는 경고문을 알림을 통해 사용자가에게 알려줍니다.
- 전체 사용자에 대한 정보를 불러오고, 현재 해당하는 이메일의 사용자의 계정을 삭제합니다.
- 업데이트 된 사용자 정보를 다시 저장합니다.
- 프로필 화면을 없애고, 로그인 화면을 다시 활성화합니다.
3. 로그인 및 로그아웃
li_form.addEventListener('submit', async (e) => {
e.preventDefault();
li_msg.textContent = '';
const email = ($('li_email').value || '').trim().toLowerCase();
const pw = $('li_pw').value;
if (!email || !pw) {
li_msg.textContent = '이메일과 비밀번호를 입력하세요.'; return;
}
const users = loadUsers();
const user = users[email];
if (!user) {
li_msg.textContent = '등록되지 않은 이메일입니다.'; return;
}
const hash = await hashPw(pw);
if (hash !== user.hash) {
li_msg.textContent = '비밀번호가 일치하지 않습니다.'; return;
}
const nowISO = new Date().toISOString();
user.lastLogin = nowISO;
users[email] = user;
saveUsers(users);
saveSession(email, remember.checked);
updateStatusLeft(true, email, nowISO);
showProfileInRight(email);
});
logoutBtn.addEventListener('click', () => {
clearSession();
profileArea.style.display = 'none';
loginFormWrap.style.display = '';
li_form.reset();
updateStatusLeft(false);
$('profileMsg').textContent = '로그아웃 되었습니다.';
});
로그인
사용자가 오른쪽 로그인 화면에서 이메일과 비밀번호를 입력하면 사용자 유무를 검사합니다.
전체 사용자 중에서 입력된 이메일에 해당하는 사용자 정보를 가져옵니다.
사용자가 입력한 비밀번호를 암호화하여 사용자 정보 중 해당 이메일을 가진 사용자의 비밀번호와 비교합니다.
일치하지 않을 경우에는 알림창으로 경고 문구를 보여줍니다.
이메일과 비밀번호가 모두 일치할 경우 현재 시간을 가져와서 사용자 정보에 들어있던 마지막 로그인 시간을 갱신해줍니다.
업데이트 된 사용자 정보를 다시 저장합니다.
오른쪽 화면을 사용자 프로필 화면으로 변경해줍니다.
로그 아웃
사용자가 로그인을 하면 하단에 로그아웃 버튼과 계정 삭제 버튼 2개가 보이도록 합니다.
로그아웃 버튼을 누르게 되면 프로필 화면은 사라지고, 로그인 화면이 다시 나타나도록 합니다.
사용자 정보 입력폼은 reset을 해줍니다.
왼쪽 화면도 업데이트 해줍니다.
4. 모달(팝업)창
function showModal() {
signupModal.style.display = 'flex';
signupModal.setAttribute('aria-hidden', 'false');
document.getElementById('su_name').focus();
}
function hideModal() {
signupModal.style.display = 'none';
signupModal.setAttribute('aria-hidden', 'true');
su_form.reset(); su_msg.textContent = '';
}
signupBtnInline.addEventListener('click', showModal);
closeModal.addEventListener('click', hideModal);
cancelSignup.addEventListener('click', hideModal);
signupModal.addEventListener('click', (e) => {
if (e.target === signupModal)
hideModal();
});
- HTML 코드로 만들어놓았던 signupModal의 display 값을 show(flex), hide(none)으로 변경합니다.
- 해당 하는 버튼을 눌렀을 때 팝업창을 보여주는 함수와 숨기는 함수가 실행되도록 합니다.
디버깅
- 최근 로그인 시간은 사용자가 로그인할 때마다 `users[email].lastLogin`에 ISO 문자열로 저장됩니다.
- 로그인 유지(remember) 체크 시 세션 정보는 `localStorage`에 저장되어 브라우저를 닫아도 유지됩니다.
- 이 예제는 학습용입니다 — 실제 서비스에서는 서버측 인증(해시+salt, HTTPS, 세션관리 등)을 반드시 구현하세요.
Development
- 서버를 사용하여 실제로 운영할 수 있는 웹페이지 만들기
- 이미지 저장 등을 추가하여 사용자에 대한 정보를 다양하게 활용해보기
- 비밀번호 입력 제한 및 재설정 추가해보기
- 카카오, 네이버 등의 API 활용하여 간편 로그인 만들어보기




