

다음과 같은 조건을 만족하여야 한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>로그인</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<div class="login-container">
<h1>로그인</h1>
<form action="/login" method="POST">
<div class="form-group">
<label for="loginId">ID:</label>
<input type="text" id="loginId" name="id" oninput="enableLoginButton()" required>
</div>
<div class="form-group">
<label for="loginPassword">비밀번호:</label>
<input type="password" id="loginPassword" name="password" oninput="enableLoginButton()" required>
</div>
<div class="form-group">
<button type="submit" id="loginBtn" class="inactive" disabled>로그인</button>
</div>
<div class="form-group">
<a href="/register">회원가입</a>
</div>
</form>
</div>
<script src="/scripts.js"></script>
</body>
</html>
<form action="/login" method="POST"> <input type="text" id="loginId" name="id" required>oninput="enableLoginButton()"<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>회원가입</title>
<link rel="stylesheet" href="/styles.css">
<script>
let isDuplicateChecked = false; // 중복 체크 여부 추적
// 페이지 로드 시 기본적으로 회원가입 버튼 비활성화
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('submitBtn').disabled = true; // 기본적으로 비활성화
});
// ID 입력 시 중복 체크 버튼 활성화
function handleIDInput() {
const idInput = document.getElementById('id').value;
const duplicateCheckBtn = document.getElementById('duplicateCheckBtn');
duplicateCheckBtn.disabled = idInput.length < 1; // 한 글자 이상일 때만 활성화
// ID가 변경되면 중복 체크가 필요하므로 플래그 초기화
isDuplicateChecked = false;
enableSubmitButton(); // 버튼 활성화 여부 확인
}
// ID 중복 체크
function checkDuplicateID() {
const id = document.getElementById('id').value;
const checkResult = document.getElementById('checkResult');
const submitBtn = document.getElementById('submitBtn');
if (!id) {
checkResult.innerHTML = 'ID를 입력해주세요';
return;
}
// 서버로 중복 체크 요청
fetch(`/check-id?id=${id}`)
.then(response => response.json())
.then(data => {
if (data.exists) {
checkResult.innerHTML = '이미 사용 중인 ID입니다.';
isDuplicateChecked = false; // 중복된 경우
submitBtn.disabled = true; // ID가 중복되면 회원가입 버튼 비활성화
} else {
checkResult.innerHTML = '사용 가능한 ID입니다.';
isDuplicateChecked = true; // 사용 가능한 경우
}
enableSubmitButton(); // 중복 체크 후 회원가입 버튼 활성화 여부 확인
});
}
// 비밀번호 일치 여부 확인
function checkPasswordMatch() {
const pw1 = document.getElementById('password1').value;
const pw2 = document.getElementById('password2').value;
const pwMatchResult = document.getElementById('pwMatchResult');
if (pw1 && pw2) {
if (pw1 === pw2) {
pwMatchResult.innerHTML = '비밀번호가 일치합니다.';
} else {
pwMatchResult.innerHTML = '비밀번호가 일치하지 않습니다.';
}
} else {
pwMatchResult.innerHTML = ''; // 둘 다 입력하지 않은 경우 메시지 지움
}
enableSubmitButton(); // 비밀번호 확인 후 회원가입 버튼 활성화 여부 확인
}
// 회원가입 버튼 활성화
function enableSubmitButton() {
const pw1 = document.getElementById('password1').value;
const pw2 = document.getElementById('password2').value;
const submitBtn = document.getElementById('submitBtn');
// ID 중복 체크가 완료되고, 비밀번호가 일치하며, 비밀번호가 입력되었을 때만 회원가입 버튼 활성화
if (isDuplicateChecked && pw1 === pw2 && pw1.length > 0 && pw2.length > 0) {
submitBtn.disabled = false; // 활성화
} else {
submitBtn.disabled = true; // 비활성화
}
}
// onblur로 실시간 비밀번호 확인
function handlePasswordBlur() {
checkPasswordMatch();
}
</script>
</head>
<body>
<div class="register-container">
<h1>회원가입</h1>
<form action="/register" method="POST">
<div class="form-group">
<label for="id">ID:</label>
<input type="text" id="id" name="id" oninput="handleIDInput()">
<button type="button" id="duplicateCheckBtn" disabled onclick="checkDuplicateID()">중복 ID 체크</button>
<span id="checkResult" style="color: red;"></span>
</div>
<div class="form-group">
<label for="password1">비밀번호:</label>
<input type="password" id="password1" name="password1" oninput="checkPasswordMatch()" onblur="handlePasswordBlur()">
</div>
<div class="form-group">
<label for="password2">비밀번호 확인:</label>
<input type="password" id="password2" name="password2" oninput="checkPasswordMatch()" onblur="handlePasswordBlur()">
<span id="pwMatchResult" style="color: red;"></span>
</div>
<div class="form-group">
<button type="submit" id="submitBtn" disabled>회원가입</button>
</div>
</form>
</div>
</body>
</html>
let isDuplicateChecked = false; // 중복 체크 여부 추적(기본값 : false)
// 페이지 로드 시 기본적으로 회원가입 버튼 비활성화
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('submitBtn').disabled = true; // 기본적으로 비활성화
});
// ID 입력 시 중복 체크 버튼 활성화
function handleIdInput() {
const idInput = document.getElementById('id').value;
const checkDuplicateBtn = document.getElementById('checkDuplicateBtn');
// ID 입력이 한 글자라도 있으면 중복 체크 버튼 활성화
checkDuplicateBtn.disabled = idInput.length === 0;
// ID가 변경되면 중복 체크가 필요하므로 플래그 초기화
isDuplicateChecked = false;
enableSubmitButton(); // 회원가입 버튼 활성화 여부 확인
}
// ID 중복 체크
function checkDuplicateID() {
const id = document.getElementById('id').value;
const checkResult = document.getElementById('checkResult');
if (!id) {
checkResult.innerHTML = 'ID를 입력해주세요';
isDuplicateChecked = false; // 입력이 없으면 중복 체크를 하지 않는다
enableSubmitButton(); // 버튼 활성화 여부 확인하기
return;
}
// 서버로 중복 체크 요청
fetch(`/check-id?id=${id}`)
.then(response => response.json())
.then(data => {
if (data.exists) {
checkResult.innerHTML = '이미 사용 중인 ID입니다.';
isDuplicateChecked = false; // 중복된 경우
} else {
checkResult.innerHTML = '사용 가능한 ID입니다.';
isDuplicateChecked = true; // 사용 가능한 경우
}
enableSubmitButton(); // 중복 체크 후 회원가입 버튼 활성화 여부 확인
});
}
// 비밀번호 일치 여부 확인
function checkPasswordMatch() {
const pw1 = document.getElementById('password1').value;
const pw2 = document.getElementById('password2').value;
const pwMatchResult = document.getElementById('pwMatchResult');
if (pw1 && pw2) {
if (pw1 === pw2) {
pwMatchResult.innerHTML = '비밀번호가 일치합니다.';
} else {
pwMatchResult.innerHTML = '비밀번호가 일치하지 않습니다.';
}
} else {
pwMatchResult.innerHTML = ''; // 비밀번호가 입력되지 않았을 경우 초기화
}
enableSubmitButton(); // 비밀번호 확인 후 회원가입 버튼 활성화 여부 확인
}
// 회원가입 버튼 활성화
function enableSubmitButton() {
const pw1 = document.getElementById('password1').value;
const pw2 = document.getElementById('password2').value;
const submitBtn = document.getElementById('submitBtn');
// ID 중복 체크가 완료되고, 비밀번호가 일치하며, 비밀번호가 입력되었을 때만 회원가입 버튼 활성화
if (isDuplicateChecked && pw1 === pw2 && pw1.length > 0 && pw2.length > 0) {
submitBtn.disabled = false; // 활성화
submitBtn.classList.add('active'); // 'active' 클래스 추가
} else {
submitBtn.disabled = true; // 비활성화
submitBtn.classList.remove('active'); // 'active' 클래스 제거
}
}
// 로그인 버튼 활성화
function enableLoginButton() {
const idInput = document.getElementById('loginId').value;
const passwordInput = document.getElementById('loginPassword').value;
const loginBtn = document.getElementById('loginBtn');
// ID와 비밀번호가 모두 입력되었을 때만 로그인 버튼 활성화(한 개라도 입력되면 활성화)
if (idInput.length > 0 && passwordInput.length > 0) {
loginBtn.disabled = false;
loginBtn.classList.remove('inactive');
loginBtn.classList.add('active');
} else {
loginBtn.disabled = true;
loginBtn.classList.remove('active');
loginBtn.classList.add('inactive');
}
}
/* 전체 화면 설정 */
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f5f5f5;
}
/* 로그인 컨테이너 스타일 */
.login-container {
background-color: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
text-align: center;
width: 300px;
}
/* 회원가입 컨테이너 스타일 */
.register-container {
background-color: #ffffff;
padding: 40px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 400px;
text-align: center;
}
h1 {
margin-bottom: 30px;
font-size: 24px;
color: #333;
}
.form-group {
margin-bottom: 20px;
text-align: left;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #333;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
input[type="text"]:focus,
input[type="password"]:focus {
outline: none;
border-color: #007bff;
}
button {
width: 100%;
padding: 10px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
/* 비활성화된 상태 */
button.inactive {
background-color: #ccc;
cursor: not-allowed;
}
/* 활성화된 상태 */
button.active {
background-color: #007bff;
cursor: pointer;
}
/* 활성화된 상태에서 마우스를 올렸을 때 */
button.active:hover {
background-color: #0056b3;
}
button:not(.inactive):hover {
background-color: #0056b3;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
/* 활성화된 버튼에 마우스를 올릴 때 */
button:hover:enabled {
background-color: #0056b3;
}
a {
display: block;
margin-top: 1rem;
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const path = require('path'); // 경로 설정을 위해 path 모듈
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
// 정적 파일 경로 설정
app.use(express.static(path.join(__dirname, 'views')));
app.use(session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: true
}));
let users = [];
// 기본 경로로 접속 시 /login으로 리다이렉트
app.get('/', (req, res) => {
res.redirect('/login');
});
// 로그인 페이지
app.get('/login', (req, res) => {
res.sendFile(path.join(__dirname, 'views', 'login.html'));
});
// 회원가입 페이지
app.get('/register', (req, res) => {
res.sendFile(path.join(__dirname, 'views', 'register.html'));
});
app.post('/login', (req, res) => {
const { id, password } = req.body;
const user = users.find(u => u.id === id && u.password === password);
if (user) {
req.session.user = user;
res.redirect('/home');
} else {
res.send('<script>alert("ID 또는 PW가 잘못되었습니다."); window.location="/login";</script>');
}
});
app.post('/register', (req, res) => {
const { id, password1, password2 } = req.body;
if (users.some(u => u.id === id)) {
return res.send('<script>alert("중복된 ID입니다."); window.location="/register";</script>');
}
if (password1 !== password2) {
return res.send('<script>alert("비밀번호가 일치하지 않습니다."); window.location="/register";</script>');
}
users.push({ id, password: password1, name: '박규동 교수' });
res.redirect('/login');
});
// 홈 페이지
app.get('/home', (req, res) => {
if (req.session.user) {
res.send(`
<h1>환영합니다, ${req.session.user.name}님! 오실줄 알 고 있었습니다</h1>
<p>저는 정보융합학부 20학번 정유빈 입니다</p>
`);
} else {
res.redirect('/login');
}
});
// ID 중복 체크
app.get('/check-id', (req, res) => {
const id = req.query.id;
const exists = users.some(u => u.id === id);
res.json({ exists });
});
app.listen(3000, () => {
console.log('서버가 http://localhost:3000 에서 실행 중입니다.');
});


실시간으로 비밀번호 확인(onblur 사용)

중복ID 체크를 하지 않으면 회원가입이 되지 않음

중복 ID 체크 이후 모습


