E-book (11) 도서등록

이율곡·2023년 1월 31일
0

Project

목록 보기
13/15
post-thumbnail

서두

이번에는 도서 등록을 완료했다. 이로써 등록에 관한 모든 API는 완성이다. 도서 등록 코드를 차근차근 정리해야겠다.


Routes

routes.get('/bookRegist', bookController.getBookRegist);

routes.get('/authorPopup', bookController.getPopup);

routes.post('/searchAuthor', bookController.postPopup);

routes.post('/bookRegistAction', multer({ storage: fileStorage, fileFilter: fileFilter }).fields([{ name: 'image' }, { name: 'content' }]), bookController.bookRegistAction);

adminRoutes파일에 설정한 코드다. 페이지 이동은 get형식으로 모델에 접근해야 되는 파일들을 post형식으로 설정했다.

Controller

exports.getBookRegist = (req, res, next) => {
  res.render("admin/regist/book", {
    pageTitle: "E-Book Book Regist",
    member: req.session.user,
    admin: req.session.admin,
  });
};

exports.getPopup = (req, res, next) => {
  res.render("admin/authorPopup", {
    pageTitle: "Search Author Popup",
    admin: req.session.admin,
    results: "",
  });
};

exports.postPopup = (req, res, next) => {
  let authorName = req.body.authorName;

  Book.searchAuthor(authorName, (result) => {
    if (!result) {
      console.log("값을 확인해주세요 : " + result);
    } else {
      res.render("admin/authorPopup", {
        pageTitle: "Search Author Popup",
        admin: req.session.admin,
        results: result,
      });
    }
  });
};

첫 번째 컨트롤러는 도서 등록 페이지로 이동시켜주는 컨트롤러다. 그리고 두 번째와 세 번째 컨트롤러는 작가 검색을 위해 만든 컨트롤러이다. 따로 팝업창을 띄워 작가를 검색한 후 검색한 값을 원래의 페이지에 보내주는 역할을 한다.

let bookNumber = (bookClass, cb) => {
  if (bookClass === "0") {
    number = (Math.random() * 99).toFixed(2);
    if (number < 10) {
      number = String(number).padStart(6, "0");
    } else if (number < 100) {
      number = String(number).padStart(6, "0");
    }
    return (cb = number);
  } else if (bookClass === "1") {
    return (cb = (Math.random() * (199 - 100) + 100).toFixed(2).toString());
  } else if (bookClass === "2") {
    return (cb = (Math.random() * (299 - 200) + 200).toFixed(2).toString());
  } else if (bookClass === "3") {
    return (cb = (Math.random() * (399 - 300) + 300).toFixed(2).toString());
  } else if (bookClass === "4") {
    return (cb = (Math.random() * (499 - 400) + 400).toFixed(2).toString());
  } else if (bookClass === "5") {
    return (cb = (Math.random() * (599 - 500) + 500).toFixed(2).toString());
  } else if (bookClass === "6") {
    return (cb = (Math.random() * (699 - 600) + 600).toFixed(2).toString());
  } else if (bookClass === "7") {
    return (cb = (Math.random() * (799 - 700) + 700).toFixed(2).toString());
  } else if (bookClass === "8") {
    return (cb = (Math.random() * (899 - 800) + 800).toFixed(2).toString());
  } else if (bookClass === "9") {
    return (cb = (Math.random() * (999 - 900) + 900).toFixed(2).toString());
  }
};

exports.bookRegistAction = (req, res, next) => {
  let number = "";

  let bookClass = req.body.bookClass;
  let bookName = req.body.bookName;
  let authorNumber = req.body.author_number;
  let bookInf = req.body.bookInf;
  let released = req.body.released;
  let adminNumber = req.session.admin.admin_number;
  let book_number = bookNumber(bookClass, number);

  console.log(book_number);

  let image = req.files.image;
  let content = req.files.content;

  Book.bookRegistAction(
    book_number,
    bookClass,
    bookName,
    authorNumber,
    bookInf,
    released,
    adminNumber,
    image,
    content,
    (err) => {
      if (err) {
        console.log("도서 등록 오류를 확인해주세요 : " + err);
      } else {
        res.render("admin/adminIndex", {
          pageTitle: "Welcome E-book Admin Page",
          member: req.session.user,
          admin: req.session.admin,
        })
      }
    }
  );
};

위의 코드는 책을 등록하기 위한 코드들이다. 2가지로 나누어 볼 수 있는데 첫 번째 bookNumber 함수는 책 번호를 만들기 위한 코드이다. 책 분류에 맞는 번호를 설정하는 코드이다. 두 번째는 모델과 연결되어 있는 컨트롤러이다. View에서 받은 값들을 모델로 보낸다.

Model

static searchAuthor(authorName, cb) {
    if (authorName) {
      var sql =
        "SELECT * FROM author WHERE author_name LIKE '%" + authorName + "%'";
      connection.query(sql, (err, row, fields) => {
        if (err) {
          console.log("쿼리 1 에러 : " + err);
        } else {
          if (!row) {
            console.log("작가명을 확인해주세요.");
          } else {
            console.log("작가검색 성공!!");
            cb(searchAuthors(row));
          }
        }
      });
    } else {
      console.log("작가명을 입력해주세요.");
    }
  }

book 모델에는 기본적인 구성을 설정하고 위의 코드가 일단 있다. 작가를 검색하는 코드로 DB에서 작가의 이름을 가지고 값을 다시 컨트롤러로 보낸다.

static bookRegistAction(
    bookNumber,
    bookClass,
    bookName,
    authorNumber,
    bookInf,
    released,
    adminNumber,
    image,
    content,
    cb
  ) {
    
    let imageName = image[0].originalname;
    let imagePath = image[0].path;

    let contentName = content[0].originalname;
    let contentPath = content[0].path;

    if (bookName && released && bookInf) {
      var bookSql =
        "INSERT INTO book (book_number, book_class, book_name, author_number, book_inf, released, admin_number) VALUES (?, ?, ?, ?, ?, ?, ?)";
      var param = [
        bookNumber,
        bookClass,
        bookName,
        authorNumber,
        bookInf,
        released,
        adminNumber
      ];

      var bookPlusSql = "INSERT INTO book_plus (book_number) VALUES ('" + bookNumber + "')";

      var imageSQL =
        "INSERT INTO book_image (book_number, image_name, image_path, admin_number) VALUES (?, ?, ?, ?)";
      var param2 = [bookNumber, imageName, imagePath, adminNumber];

      var contentSQL =
        "INSERT INTO book_content (book_number, content_name, content_path, admin_number) VALUES (?, ?, ?, ?)";
      var param3 = [bookNumber, contentName, contentPath, adminNumber];

      connection.beginTransaction((err) => {
        if (err) {
          console.log("관리자 트랜잭션 에러 :" + err);
        } else {
          connection.query(bookSql, param, (err, row, fields) => {
            if (err) {
              console.log("book INSERT 구문 오류 : " + err);
              connection.rollback();
            } else {
              connection.query(bookPlusSql, (err, row, fields) => {
                if (err) {
                  console.log("book_plus INSERT 구문 오류 : " + err);
                  connection.rollback();
                } else {
                  connection.query(imageSQL, param2, (err, row, fields) => {
                    if (err) {
                      console.log("imageSQL INSERT 구문 오류 : " + err);
                      connection.rollback();
                    } else {
                      connection.query(contentSQL, param3, (err, row, fields) => {
                        if (err) {
                          console.log("contentSQL INSERT 구문 오류 : " + err);
                          connection.rollback();
                        } else {
                          console.log("도서 등록 성공!!");
                          connection.commit();
                          cb();
                          connection.end();
                        }
                      });
                    }
                  });
                }
              });
            }
          });
        }
      });
    } else {
      console.log("입력된 값을 확인해주세요.");
    }
  }

두 번째로 DB에 도서를 등록하는 코드인데 query를 네 번이나 쓴다. 이 구문을 쓰면서 다르게 설정하는 방법도 나중에 배워야겠다고 느꼈다. 어려운 것은 없고 4개의 테이블에 값을 넣는 역할이다.

View

<%- include('../../admin/includes/admin-head-nav.ejs')%>
    <div class="container px-4 px-lg-5">
        <div class="row gx-4 gx-lg-5 align-items-center my-5 ">
            <form action="/bookRegistAction" method="POST" enctype="multipart/form-data">
                <label for="bookClass">책분류</label>
                    <select name="bookClass" id="bookClass">
                        <option value="">'종류를 선택해주세요'</option>
                        <option value="0">총류</option>
                        <option value="1">철학</option>
                        <option value="2">종교</option>
                        <option value="3">사회과학</option>
                        <option value="4">자연과학</option>
                        <option value="5">기술과학</option>
                        <option value="6">예술</option>
                        <option value="7">언어</option>
                        <option value="8">문학</option>
                        <option value="9">역사</option>
                    </select><br>
                <label for="bookName">책이름</label>
                <input type="text" name="bookName" id="bookName"><br>
                <label for="author">작가</label>    
                <input type="text" name="author" id="author" readonly><input type="button" onclick="popup()" value="찾기"><br>
                <input type="hidden" name="author_number" id="author_number" value="">
                <label for="image">이미지</label>    
                <input type="file" name="image" id="image"><br>
                <label for="content">내용</label>    
                <input type="file" name="content" id="content" multiple><br>
                <label for="released">출판년도</label>
                <input type="text" name="released" id="released" placeholder="예시) 2023"><br>
                <label for="bookInf">책소개</label>
                <textarea name="bookInf" id="bookInf" cols="30" rows="10"></textarea><br>
                <button type="submit" class="btn btn-primary">등록하기</button>
            </form>
        </div>
    </div>
<%- include('../../admin/includes/admin-footer.ejs')%>        

책 등록하는 화면이다. 특히 어려운 점은 없고 파일을 각각 다른 이름과 형식을 사용하는 정도이다.

<%- include('../admin/includes/admin-head-nav.ejs')%>
    <div class="container px-4 px-lg-5">
        <div class="row gx-4 gx-lg-5 align-items-center my-5 ">
            <form action="searchAuthor" method="post">
                <label for="authorName">작가명</label>
                <input type="text" name="authorName" id="authorName" placeholder="작가 이름을 입력해주세요.">
                <button type="submit" class="btn btn-primary">검색</button>
            </form>
            <% if(results) {%>
                <table>
                    <tr>
                        <th>작가번호</th>
                        <th>이름</th>
                        <th>생년월일</th>
                        <th>대표작</th>
                        <th>등록</th>
                    </tr>
                    <% for (result in results) { %>
                        <form name="author" method="POST">
                            <tr>
                                <input type="hidden" name="author_number" id="author_number" value="<%= results[result].author_number %>">
                                <input type="hidden" name="author" id="author" value="<%= results[result].author_name %>">
                                <td><%= results[result].author_number %></td>
                                <td><%= results[result].author_name %></td>
                                <td><%= results[result].birth %></td>
                                <td><%= results[result].best_book %></td>
                                <td>
                                    <input type="button" onclick="getAuthor()" value="등록">
                                </td>
                            </tr>
                        </form>
                    <% } %>
                </table>
            <% } %>
        </div>
    </div>
<%- include('../admin/includes/admin-footer.ejs')%>        

위 코드는 작가 검색을 위한 팝업 페이지이다. 여기서 검색하고 나온 값을 부모 페이지는 도서 등록 페이지로 값을 보낸다. 그렇기 때문에 작가이름 적는 부분은 readonly로 설정했다.

정리하기

이번에는 도서 등록을 했다. 기존의 파일을 지우고 다시 설정하는 과정에서 헷갈리기는 했지만 그래도 무난하게 잘 넘어간 것 같다. 중요한 것은 multer모듈로 각각 다른 형식의 파일들을 어떻게 넣는지 이해하는 것이었다. 지금은 버전 1이기 때문에 얼추 마무리가 된 다음 버전 2단계로 넘어가고 싶다.

profile
음악을 좋아하는 사람이 음악을 만들 듯, 개발을 좋아하게 될 사람이 쓰는 개발이야기

0개의 댓글