웹
웹페이지 만들기 방명록
148june
2025. 2. 18. 09:34
cursorRequest.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
const listItem = document.createElement('li');
listItem.setAttribute('data-id', cursor.value.id);
listItem.textContent = `${cursor.value.name}: ${cursor.value.message}`;
// 수정 버튼
const editButton = document.createElement('button');
editButton.className = 'edit-btn';
editButton.textContent = '수정';
editButton.onclick = () => editMessage(cursor.value.id, cursor.value.name, cursor.value.message);
listItem.appendChild(editButton);
// 삭제 버튼
const deleteButton = document.createElement('button');
deleteButton.className = 'delete-btn';
deleteButton.textContent = '삭제';
deleteButton.onclick = () => deleteMessage(cursor.value.id);
listItem.appendChild(deleteButton);
messagesList.appendChild(listItem);
cursor.continue();
}
};
};
이부분의 문제 점은
값 캡처 문제(잠재적 문제):
원래 각 버튼의 이벤트 핸들러에서 cursor.value를 직접 참조했기 때문에, 클로저 문제로 인해 의도한 값이 아닌 최신 값만 사용될 가능성이 있었습니다.
즉
ㅁㅁ : ㅁㅁㅁ 수정 삭제
ㅇㅇ: ㅇㅇㅇ 수정 삭제
이렇게 있을시 ㅁㅁ을 수정하고 싶어 ㅁㅁㅁ 옆 수정을 눌렀을시 ㅇㅇ 이 최신 글 일 경우 ㅇㅇ: ㅇㅇㅇ을 수정하는 문제 점이 있었다. 이문제를 해결하기 위해
// 방명록 메시지 수정 (id 유지하면서 내용만 수정)
const editMessage = (id, currentName, currentMessage) => {
const newName = prompt("이름을 수정하세요", currentName);
const newMessage = prompt("내용을 수정하세요", currentMessage);
if (newName && newMessage) {
const transaction = db.transaction('messages', 'readwrite');
const store = transaction.objectStore('messages');
store.get(id).onsuccess = (event) => {
const existingMessage = event.target.result;
if (existingMessage) {
existingMessage.name = newName;
existingMessage.message = newMessage;
store.put(existingMessage); // 기존 ID 유지한 채로 수정
transaction.oncomplete = () => {
loadMessages();
};
}
};
}
};
방명록 기존값을 유지하기위해 고안햇었다.
add 문제인가 싶어 put 으로 변경하기도 하였다.
하지만 진짜 문제는 값을 가져오는 문제에 있었던거였고
기존값
cursorRequest.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
const listItem = document.createElement('li');
listItem.setAttribute('data-id', cursor.value.id);
listItem.textContent = `${cursor.value.name}: ${cursor.value.message}`;
// 수정 버튼
const editButton = document.createElement('button');
editButton.className = 'edit-btn';
editButton.textContent = '수정';
editButton.onclick = () => editMessage(cursor.value.id, cursor.value.name, cursor.value.message);
listItem.appendChild(editButton);
// 삭제 버튼
const deleteButton = document.createElement('button');
deleteButton.className = 'delete-btn';
deleteButton.textContent = '삭제';
deleteButton.onclick = () => deleteMessage(cursor.value.id);
listItem.appendChild(deleteButton);
messagesList.appendChild(listItem);
cursor.continue();
}
};
};
변경후
cursorRequest.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
// 커서의 값을 별도의 변수에 저장
const { id, name, message } = cursor.value;
const listItem = document.createElement('li');
listItem.setAttribute('data-id', id);
// 별도의 요소(예: span)를 사용하면 텍스트와 버튼을 구분하기 쉽습니다.
const textSpan = document.createElement('span');
textSpan.textContent = `${name}: ${message}`;
listItem.appendChild(textSpan);
// 수정 버튼 생성
const editButton = document.createElement('button');
editButton.className = 'edit-btn';
editButton.textContent = '수정';
// 이벤트 핸들러에서 별도의 변수 사용
editButton.onclick = () => editMessage(id, name, message);
listItem.appendChild(editButton);
// 삭제 버튼 생성
const deleteButton = document.createElement('button');
deleteButton.className = 'delete-btn';
deleteButton.textContent = '삭제';
deleteButton.onclick = () => deleteMessage(id);
listItem.appendChild(deleteButton);
messagesList.appendChild(listItem);
cursor.continue();
}
};
전체코드는
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>방명록</title>
<style>
.section {
margin: 20px 0;
padding: 10px;
}
.guest-book ul {
list-style-type: none;
}
.guest-book li {
margin-bottom: 10px;
}
textarea, input[type="text"] {
width: 100%;
padding: 8px;
font-size: 16px;
margin-bottom: 10px;
box-sizing: border-box;
}
button {
margin-top: 10px;
padding: 10px 20px;
background-color: #000000;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #333;
}
.edit-btn {
background-color: #0067A3;
margin-left: 10px;
}
.delete-btn {
background-color: #e74c3c;
margin-left: 10px;
}
</style>
</head>
<body>
<div class="guest-book">
<h3>방명록</h3>
<form id="guestBookForm">
<label for="name">이름:</label>
<input type="text" id="name" name="name" required placeholder="이름을 입력하세요">
<label for="message">내용:</label>
<textarea id="message" name="message" required placeholder="방명록 내용을 입력하세요"></textarea>
<button type="submit">저장</button>
</form>
<h4>방명록 내용</h4>
<ul id="guestMessages"></ul>
</div>
<script>
let db;
// IndexedDB 연결 함수
const openDb = () => {
const request = indexedDB.open('GuestBookDB', 1);
request.onupgradeneeded = (event) => {
db = event.target.result;
if (!db.objectStoreNames.contains('messages')) {
db.createObjectStore('messages', { keyPath: 'id' });
}
};
request.onsuccess = (event) => {
db = event.target.result;
console.log("Database opened successfully.");
loadMessages(); // DB가 완전히 열린 후에 실행
};
request.onerror = (event) => {
console.error("Database error:", event.target.errorCode);
};
};
const loadMessages = () => {
if (!db) {
console.error("Database is not initialized yet.");
return;
}
const transaction = db.transaction('messages', 'readonly');
const store = transaction.objectStore('messages');
const cursorRequest = store.openCursor();
const messagesList = document.getElementById('guestMessages');
messagesList.innerHTML = "";
/*
cursorRequest.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
const listItem = document.createElement('li');
listItem.setAttribute('data-id', cursor.value.id);
listItem.textContent = `${cursor.value.name}: ${cursor.value.message}`;
// 수정 버튼
const editButton = document.createElement('button');
editButton.className = 'edit-btn';
editButton.textContent = '수정';
editButton.onclick = () => editMessage(cursor.value.id, cursor.value.name, cursor.value.message);
listItem.appendChild(editButton);
// 삭제 버튼
const deleteButton = document.createElement('button');
deleteButton.className = 'delete-btn';
deleteButton.textContent = '삭제';
deleteButton.onclick = () => deleteMessage(cursor.value.id);
listItem.appendChild(deleteButton);
messagesList.appendChild(listItem);
cursor.continue();
}
};
};
*/
cursorRequest.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
// 커서의 값을 별도의 변수에 저장
const { id, name, message } = cursor.value;
const listItem = document.createElement('li');
listItem.setAttribute('data-id', id);
// 별도의 요소(예: span)를 사용하면 텍스트와 버튼을 구분하기 쉽습니다.
const textSpan = document.createElement('span');
textSpan.textContent = `${name}: ${message}`;
listItem.appendChild(textSpan);
// 수정 버튼 생성
const editButton = document.createElement('button');
editButton.className = 'edit-btn';
editButton.textContent = '수정';
// 이벤트 핸들러에서 별도의 변수 사용
editButton.onclick = () => editMessage(id, name, message);
listItem.appendChild(editButton);
// 삭제 버튼 생성
const deleteButton = document.createElement('button');
deleteButton.className = 'delete-btn';
deleteButton.textContent = '삭제';
deleteButton.onclick = () => deleteMessage(id);
listItem.appendChild(deleteButton);
messagesList.appendChild(listItem);
cursor.continue();
}
};
// 방명록 메시지 추가 (기존 데이터 덮어쓰지 않도록 add 사용)
const addMessage = (name, message) => {
if (!db) {
console.error("Database not initialized.");
return;
}
const transaction = db.transaction('messages', 'readwrite');
const store = transaction.objectStore('messages');
const newEntry = { id: Date.now(), name, message };
const request = store.add(newEntry);
request.onsuccess = () => {
loadMessages();
};
request.onerror = (event) => {
console.error("Error adding message:", event.target.error);
};
};
// 방명록 메시지 수정 (id 유지하면서 내용만 수정)
const editMessage = (id, currentName, currentMessage) => {
const newName = prompt("이름을 수정하세요", currentName);
const newMessage = prompt("내용을 수정하세요", currentMessage);
if (newName && newMessage) {
const transaction = db.transaction('messages', 'readwrite');
const store = transaction.objectStore('messages');
store.get(id).onsuccess = (event) => {
const existingMessage = event.target.result;
if (existingMessage) {
existingMessage.name = newName;
existingMessage.message = newMessage;
store.put(existingMessage); // 기존 ID 유지한 채로 수정
transaction.oncomplete = () => {
loadMessages();
};
}
};
}
};
// 방명록 메시지 삭제 (id 기준으로 정확한 데이터 삭제)
const deleteMessage = (id) => {
const transaction = db.transaction('messages', 'readwrite');
const store = transaction.objectStore('messages');
store.delete(id);
transaction.oncomplete = () => {
loadMessages();
};
};
// 폼 제출 처리
document.getElementById('guestBookForm').addEventListener('submit', (event) => {
event.preventDefault();
const name = document.getElementById('name').value;
const message = document.getElementById('message').value;
addMessage(name, message);
document.getElementById('name').value = '';
document.getElementById('message').value = '';
});
}
// DB 열기
openDb();
</script>
</body>
</html>
html블럭으로 가동한다면
방명록
방명록 내용
방명록 웹페이지를 만들면 indexedb를 알게되었고
커서값을 직접 가져오는 식으로 하려 햇으나 문제점에 도달하게되었고
대신 값을 저장한것을 가져오는 식으로 변경하여 문제을 해결 할수 있게 되었다.