본문 바로가기

웹 개념

서버와 웹단을 직접 구현하여 게시판 사이트 만들기 - (2)

728x90

 

# 이전에 우리가 무엇을 했을까?

# 이전에 서버단에서 응답을 해줄 server단을 구현했습니다. 이제는 데이터를 요청해줄 웹단을 구현해봅시다.

# 저희가 만들려는 건 게시판 사이트입니다.


#Express.js 를 사용하여 CRUD 요청하기 💫

---

#파일 구조

#  게시판 사이트답게 게시판 게시글 담아줄 html 페이지를 만들어봅시다.

* index.html

# 일단 코드를 쉽게 짜기 위해 헤드 부분에 부트스트랩, 제이쿼리, 개인적으로 적용할 css 등을 import 합니다.

#  <thead> ~ </thead> 컬렉션

# <th> ~ </th> 스키마

# <tbody> 부분에 데이터를 넣으겁니다.

# 그럼 js를 이용해서 tbody의 태그를 찾고

# ajax를 이용해서 get요청을 해서 데이터를 가져온 후 넣는 작업을 하겠습니다.

# 그걸 하기 위해 관련 js파일을 가져오는 건 애라 script태그에

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>index</title>
    <script src="https://code.jquery.com/jquery-3.6.1.js" integrity="sha256-3zlB5s2uwoUzrXK3BT7AX3FyvojsraNFxCc2vC/7pNI=" crossorigin="anonymous"></script>
    <!-- CSS only -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
    <!-- JavaScript Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8" crossorigin="anonymous"></script>
    <link href="./public/css/index.css" rel="stylesheet" type="text/css">
</head>
<body class="container" style="padding: 40px;">
    <!-- http://localhost:7777/post/ get => post의 list를 가져오는 부분 -->
    <table class="table">
        <thead>
          <tr>
            <th scope="col">순서</th>
            <th scope="col">제목</th>
            <th scope="col">업데이트</th>
            <th scope="col">삭제</th>
          </tr>
        </thead>
        <!-- tbody에 게시글들을 넣을 예정 -->
        <tbody id="table-id">
         
        </tbody>
      </table>
      <div class="my-div">
        <button type="button" onclick="location.href='./pages/create.html'" class="btn btn-outline-dark">게시글 작성</button>
      </div>
</body>
<script src="./public/js/index.js"></script>
</html>

 

* index.js

1. getPostList() 함수가 ajax를 이용해서 get 요청을 한 후, 가져온 데이터를 append를 하여 추가하는 함수입니다.

2 - 1. 클라이언트에서 localhost:7777/post로 ajax 요청을 하면 server는 해당 url을 받아서 이전에 exprss로 구현한 라우터 목록을 보고 맞는 곳에 적용하고 server 이제 데이터베이스에 접속해서 해당 구현을 실행 후 다시 클라이언트에게 보내주는 방식입니다.

2. js를 이용해서 해당 태그를 찾는 건 $("#table-id)로 찾았는데 바닐라 자바스크립트로 찾고 싶으면

3. documetnt.getElementById(table-id)라고 하면 마찬가지로 찾을 수 있습니다.

4. 그리고 이전에 말씀드렸다시피 완성한 코드를 복습하는 용도이기 수정 버튼, 삭제 버튼, 그리고 글 클릭 시 상세 내용 관련 이벤트 함수가 아래에 미리 정의돼있습니다.

5. 다음에 수정, 삭제, 상세보기는 아래의 이벤트 함수를 이용해서 구현하 것입니다.

6. 참고로 append 하는 태그들에 data._id가 각각 게시글의 id입니다. 몽구에서 자동으로 제공해주는 id를 사용하는데 그 몽구스 가 자동적으로 _id 형태로 제공하기에에 다음과 같이 가지고 와서 append 하는 것 이죠.

7. 삭제, 상세보기, 수정할 때 다 _id를 식별자로 게시글이 무엇인지 판단하는 코딩을 할 것입니다.

8. 이렇게 구현하면 아래의 그림처럼 게시판이 나옵니다.

$(document).ready(() => {
  getPostList();
});

// post의 리스트를 가져오는 함수
let getPostList = () => {
  $("#table-id").empty();
  // readt() -> index.html이 준비 되면 실행!
  // 1. index.html의 로딩이 되면 post의 list를 전부 가져오는 코드를 작성.
  // 2. 가져온 post의 list를 index.html에 뿌려줌.

  // ajax를 통해서 서버에 posts의 list를 요청하는 부분
  // => 서버의 app.js로 가서 posts의 리스틀를 보내주는 부분에가서 데이터를 받아오는 것.
  $.ajax({
    url: `http://localhost:7777/posts`,
    type: "GET",
    success: (res) => {
      console.log(res);
      res.map((data, idx) => {
        $("#table-id").append(`
                    <tr>
                        <th scope="row">${idx + 1}</th>
                        <td>
                            <p id="dtit" onclick="detailBtn('${data._id}')">${data.title}</p>
                        </td>
                        <td>
                            <button type="button" onclick="updateBtn('${data._id}')" class="btn btn-outline-warning">수정</button>
                        </td>
                        <td>
                            <button type="button" onclick="deletePost('${
                              data._id
                            }')" class="btn btn-outline-danger">삭제</button>
                        </td>
                    </tr>
                `);
      });
    },
    error: (err) => {
      console.log(err);
    },
  });
};

// 수정 이벤트 핸들러
let updateBtn = (id) => {
    localStorage.setItem('post-id', id);
    location.href = './pages/update.html';
}

// 디테일 이벤트 핸들러
let detailBtn = (id) => {
    localStorage.setItem('save-id', id);
    location.href = './pages/detail.html';
}

let deletePost = (id) => {
  if (window.confirm("Do you really want to delete?")) {
    // 확인
    // http:localhost:7777/posts/:id/delete
    $.ajax({
      url: `http://localhost:7777/posts/${id}/delete`,
      type: "GET",
      success: (res) => {
        console.log(res);
        alert(res.message);
        getPostList();
      },
      error: (err) => {
        console.log(err);
      },
    });
  }
};

# 좋습니다. 이제 이미지에서 보이듯 수정, 삭제, 작성, 상세보기 하면 구현하면 됩니다.


# 수정 구현

1. 수정을 구현해봅시다. 노란색 버튼을 누르면 수정이 되는 페이지로 이동하게 할 것입니다.

2. 또한 클릭할 때 해당 글 태그의 id 즉, 아까 _id를 가져와서 저장한 id를 지역 저장소에 저장을 한 후 update페이지로 이동 3할 것입니다.

3. 왜 저장하냐면? 내가 상세보기 페이지로 이동한 후, 해당 id로 데이터베이스에 접속해서 데이터를 가져와야 하기 때문이죠.

4. localStorage.setItem(key, value)이 로컬 저장소에 저장하는 매서드입니다.

5. location.href = ""; 는 해당 "" 안에 절대 경로 or 상대 경로 방식으로 페이지를 이동하게 하는 파일입니다.

6. 이렇게 하면 update.html로 이동합니다.

// 수정 이벤트 핸들러
let updateBtn = (id) => {
    localStorage.setItem('post-id', id);
    location.href = './pages/update.html';
}

 

* update.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>update</title>
    <script src="https://code.jquery.com/jquery-3.6.1.js" integrity="sha256-3zlB5s2uwoUzrXK3BT7AX3FyvojsraNFxCc2vC/7pNI=" crossorigin="anonymous"></script>
    <!-- CSS only -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
    <!-- JavaScript Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8" crossorigin="anonymous"></script>
</head>
<body class="container">
    <form id="update-form">
        <div class="mb-3 mt-3">
            <label for="title" class="form-label">title</label>
            <input type="text" class="form-control" name="title" id="title" placeholder="제목 입력 ㄱ">
        </div>
        <div class="mb-3">
            <label for="content" class="form-label">content</label>
            <textarea class="form-control" name="content" id="content" placeholder="내용 넣어 ㄱ" rows="3"></textarea>
        </div>
        <div>
            <button type="button" id="update-btn" class="btn btn-primary">수정</button>
            <button type="button" class="btn btn-info" onclick="history.back()">취소</button>
        </div>
    </form>
</body>
<script src="./../public/js/update.js"></script>
</html>

 

* update.js를 이용하여 title, content 태그에 이미 입력했던 값을 보여주게끔 해봅시다.

1. 이동하기 전에 저장했던 로컬 저장소에 id를 가져옵니다

2. 마찬가지 서버에 localhost:7777/posts/:id/find로 요청을 해줍니다.

3. 데이터를 가져오는 데 성공하면 

4. title과 content에 가져온 데이터를 넣습니다. title은 바닐라 자바스크립트 방식, content는 제이쿼리 방식입니다.

 

5. 이렇게 가져오고 나서 update버튼을 클릭하면, 제출 전에 비어있는지 여부만 체크하고

6. 이 저 수정하기 위해 post요청을 ajax로 하는 것입니다.

7. 마찬가지로 id를 기반으로 찾아가서 post요청을 하고 성고 하면 success, 실패하면 error가 뜨는 것이죠.

$(document).ready(() => {
    let id = localStorage.getItem("post-id");
    
    // get http://localhost:7777/posts/:id/find
    $.ajax({
        url: `http://localhost:7777/posts/${id}/find`,
        type: "GET",
        success: (res) => {
            console.log(res);
            // $("#title").val(res.title);
            document.getElementById("title").value = res.title;
            $("#content").val(res.content);
        },
        error: (err) => {
            console.log(err);
        }
    })

    // update
    $("#update-btn").on('click', () => {
        if ($("#title").val() === "") {
            alert("제목 입력하라고~");
            return;
        }

        if ($("#content").val() === "") {
            alert("내용 입력하라고~");
            return;
        }
        // serialize는 제이쿼리가 알아서 쿼리스트링을 해준다.
        console.log($("#update-form").serialize());

        // http://localhost:7777/posts/:id/update
        $.ajax({
            url: `http://localhost:7777/posts/${id}/update`,
            type: 'POST',
            data: $("#update-form").serialize(),
            success: (res) => {
                console.log(res);
                alert(res.message);
                location.href = './../index.html';
            },
            error: (err) => {
                console.log(err);
            }
        })
    });
});

 


 


후기

* 이런 식으로 삭제, 생성, 상세페이지를 구현합니다. 로직의 순서는 이런 양상입니다.

* 오늘은 여기까지 포스팅하고 시간이 생기면 다음에 남은 것도 하겠습니다.

728x90