게시판만들기

HTML, CSS, JavaScript + Spring Boot + MyBatis + MySQL 으로 게시판 만들기 (6)

지니★ 2024. 7. 11. 16:54
728x90
728x90
SMALL

HTML, CSS, JavaScript + Spring Boot + MyBatis + MySQL 으로 게시판 만들기 (6)

안녕하세요! 이번 포스트에서는 게시판 애플리케이션에 추가적인 기능을 구현하고 최적화를 다루겠습니다.

1. 게시글 검색 기능 추가

게시글을 검색할 수 있는 기능을 추가하여 사용자가 원하는 게시글을 쉽게 찾을 수 있도록 하겠습니다.

1.1 index.html 수정

검색 입력 필드를 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MyBoard</title>
    <link rel="stylesheet" href="/css/styles.css">
</head>
<body>
    <div class="container">
        <h1>게시판</h1>
        <form id="postForm">
            <input type="text" id="title" placeholder="제목" required>
            <textarea id="content" placeholder="내용" required></textarea>
            <button type="submit">게시글 작성</button>
        </form>
        <input type="text" id="search" placeholder="검색어를 입력하세요">
        <button onclick="searchPosts()">검색</button>
        <div id="posts"></div>
    </div>
    <script src="/js/scripts.js"></script>
</body>
</html>
  

1.2 scripts.js 수정

검색 기능을 구현합니다.

document.addEventListener("DOMContentLoaded", function() {
    const postForm = document.getElementById("postForm");
    const postsDiv = document.getElementById("posts");

    postForm.addEventListener("submit", function(event) {
        event.preventDefault();

        const title = document.getElementById("title").value;
        const content = document.getElementById("content").value;

        fetch("/api/posts", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({ title: title, content: content })
        })
        .then(response => response.json())
        .then(data => {
            fetchPosts();
            alert("게시글이 작성되었습니다.");
        })
        .catch(error => {
            console.error("Error:", error);
            alert("게시글 작성 중 오류가 발생했습니다.");
        });
    });

    function fetchPosts() {
        fetch("/api/posts")
            .then(response => response.json())
            .then(posts => {
                postsDiv.innerHTML = "";
                posts.forEach(post => {
                    const postDiv = document.createElement("div");
                    postDiv.classList.add("post");
                    postDiv.innerHTML = `
                        <h3>${post.title}</h3>
                        <p>${post.content}</p>
                        <button class="edit" onclick="editPost(${post.id}, '${post.title}', '${post.content}')">수정</button>
                        <button class="delete" onclick="deletePost(${post.id})">삭제</button>
                    `;
                    postsDiv.appendChild(postDiv);
                });
            })
            .catch(error => console.error("Error:", error));
    }

    window.editPost = function(id, title, content) {
        if (confirm("이 게시글을 수정하시겠습니까?")) {
            document.getElementById("title").value = title;
            document.getElementById("content").value = content;

            postForm.onsubmit = function(event) {
                event.preventDefault();
                fetch(`/api/posts/${id}`, {
                    method: "PUT",
                    headers: {
                        "Content-Type": "application/json"
                    },
                    body: JSON.stringify({
                        title: document.getElementById("title").value,
                        content: document.getElementById("content").value
                    })
                })
                .then(response => response.json())
                .then(data => {
                    fetchPosts();
                    postForm.reset();
                    postForm.onsubmit = postFormSubmitHandler;
                    alert("게시글이 수정되었습니다.");
                })
                .catch(error => {
                    console.error("Error:", error);
                    alert("게시글 수정 중 오류가 발생했습니다.");
                });
            }
        }
    }

    window.deletePost = function(id) {
        if (confirm("이 게시글을 삭제하시겠습니까?")) {
            fetch(`/api/posts/${id}`, {
                method: "DELETE"
            })
            .then(response => {
                fetchPosts();
                alert("게시글이 삭제되었습니다.");
            })
            .catch(error => {
                console.error("Error:", error);
                alert("게시글 삭제 중 오류가 발생했습니다.");
            });
        }
    }

    window.searchPosts = function() {
        const query = document.getElementById("search").value.toLowerCase();
        fetch("/api/posts")
            .then(response => response.json())
            .then(posts => {
                postsDiv.innerHTML = "";
                posts.filter(post => post.title.toLowerCase().includes(query) || post.content.toLowerCase().includes(query))
                     .forEach(post => {
                         const postDiv = document.createElement("div");
                         postDiv.classList.add("post");
                         postDiv.innerHTML = `
                             <h3>${post.title}</h3>
                             <p>${post.content}</p>
                             <button class="edit" onclick="editPost(${post.id}, '${post.title}', '${post.content}')">수정</button>
                             <button class="delete" onclick="deletePost(${post.id})">삭제</button>
                         `;
                         postsDiv.appendChild(postDiv);
                     });
            })
            .catch(error => console.error("Error:", error));
    }

    const postFormSubmitHandler = postForm.onsubmit;
    fetchPosts();
});

2. 페이지네이션 기능 추가

게시글이 많아질 경우 페이지네이션을 통해 게시글을 나누어 볼 수 있도록 합니다.

2.1 index.html 수정

페이지네이션을 위한 버튼을 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MyBoard</title>
    <link rel="stylesheet" href="/css/styles.css">
</head>
<body>
    <div class="container">
        <h1>게시판</h1>
        <form id="postForm">
            <input type="text" id="title" placeholder="제목" required>
            <textarea id="content" placeholder="내용" required></textarea>
            <button type="submit">게시글 작성</button>
        </form>
        <input type="text" id="search" placeholder="검색어를 입력하세요">
        <button onclick="searchPosts()">검색</button>
        <div id="posts"></div>
        <div id="pagination"></div>
    </div>
    <script src="/js/scripts.js"></script>
</body>
</html>
  

2.2 scripts.js 수정

페이지네이션 기능을 구현합니다.

document.addEventListener("DOMContentLoaded", function() {
    const postForm = document.getElementById("postForm");
    const postsDiv = document.getElementById("posts");
    const paginationDiv = document.getElementById("pagination");
    let currentPage = 1;
    const postsPerPage = 5;

    postForm.addEventListener("submit", function(event) {
        event.preventDefault();

        const title = document.getElementById("title").value;
        const content = document.getElementById("content").value;

        fetch("/api/posts", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({ title: title, content: content })
        })
        .then(response => response.json())
        .then(data => {
            fetchPosts();
            alert("게시글이 작성되었습니다.");
        })
        .catch(error => {
            console.error("Error:", error);
            alert("게시글 작성 중 오류가 발생했습니다.");
        });
    });

    function fetchPosts(page = 1) {
        fetch("/api/posts")
            .then(response => response.json())
            .then(posts => {
                postsDiv.innerHTML = "";
                const start = (page - 1) * postsPerPage;
                const end = start + postsPerPage;
                posts.slice(start, end).forEach(post => {
                    const postDiv = document.createElement("div");
                    postDiv.classList.add("post");
                    postDiv.innerHTML = `
                        <h3>${post.title}</h3>
                        <p>${post.content}</p>
                        <button class="edit" onclick="editPost(${post.id}, '${post.title}', '${post.content}')">수정</button>
                        <button class="delete" onclick="deletePost(${post.id})">삭제</button>
                    `;
                    postsDiv.appendChild(postDiv);
                });
                renderPagination(posts.length, page);
            })
            .catch(error => console.error("Error:", error));
    }

    function renderPagination(totalPosts, currentPage) {
        paginationDiv.innerHTML = "";
        const totalPages = Math.ceil(totalPosts / postsPerPage);
        for (let i = 1; i <= totalPages; i++) {
            const pageButton = document.createElement("button");
            pageButton.innerText = i;
            pageButton.classList.add(i === currentPage ? "active" : "");
            pageButton.onclick = () => fetchPosts(i);
            paginationDiv.appendChild(pageButton);
        }
    }

    window.editPost = function(id, title, content) {
        if (confirm("이 게시글을 수정하시겠습니까?")) {
            document.getElementById("title").value = title;
            document.getElementById("content").value = content;

            postForm.onsubmit = function(event) {
                event.preventDefault();
                fetch(`/api/posts/${id}`, {
                    method: "PUT",
                    headers: {
                        "Content-Type": "application/json"
                    },
                    body: JSON.stringify({
                        title: document.getElementById("title").value,
                        content: document.getElementById("content").value
                    })
                })
                .then(response => response.json())
                .then(data => {
                    fetchPosts();
                    postForm.reset();
                    postForm.onsubmit = postFormSubmitHandler;
                    alert("게시글이 수정되었습니다.");
                })
                .catch(error => {
                    console.error("Error:", error);
                    alert("게시글 수정 중 오류가 발생했습니다.");
                });
            }
        }
    }

    window.deletePost = function(id) {
        if (confirm("이 게시글을 삭제하시겠습니까?")) {
            fetch(`/api/posts/${id}`, {
                method: "DELETE"
            })
            .then(response => {
                fetchPosts();
                alert("게시글이 삭제되었습니다.");
            })
            .catch(error => {
                console.error("Error:", error);
                alert("게시글 삭제 중 오류가 발생했습니다.");
            });
        }
    }

    window.searchPosts = function() {
        const query = document.getElementById("search").value.toLowerCase();
        fetch("/api/posts")
            .then(response => response.json())
            .then(posts => {
                postsDiv.innerHTML = "";
                posts.filter(post => post.title.toLowerCase().includes(query) || post.content.toLowerCase().includes(query))
                     .forEach(post => {
                         const postDiv = document.createElement("div");
                         postDiv.classList.add("post");
                         postDiv.innerHTML = `
                             <h3>${post.title}</h3>
                             <p>${post.content}</p>
                             <button class="edit" onclick="editPost(${post.id}, '${post.title}', '${post.content}')">수정</button>
                             <button class="delete" onclick="deletePost(${post.id})">삭제</button>
                         `;
                         postsDiv.appendChild(postDiv);
                     });
                renderPagination(posts.length, 1);
            })
            .catch(error => console.error("Error:", error));
    }

    const postFormSubmitHandler = postForm.onsubmit;
    fetchPosts();
});
  

3. 마무리

이제 게시판 애플리케이션에 검색 및 페이지네이션 기능을 추가하여 사용자 경험을 향상시켰습니다. 다음 포스트에서는 더 많은 최적화와 추가 기능을 다뤄보겠습니다. 많은 기대 부탁드립니다!

블로그 포스트에 대한 의견이나 질문이 있으시면 댓글로 남겨주세요!

728x90
728x90
LIST