
지난 시간에 이어서 계속 진행해보겠습니다.
👉🏻 지난시간 확인하기
도서 테이블을 생성해보겠습니다.
CREATE TABLE `books` (
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(45) NOT NULL,
`format` VARCHAR(45) NOT NULL,
isbn VARCHAR(45) NOT NULL,
summary VARCHAR(500) NULL,
`description` LONGTEXT NULL,
author VARCHAR(45) NOT NULL,
pages INT NOT NULL,
`index` LONGTEXT NULL,
price INT NOT NULL,
pub_date DATE NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `isbn_UNIQUE` (`isbn` ASC)
);
방금 위에서 만들 테이블에서 format, description, index에는 백팁을 사용한 이유가 무엇을까? 그 이유는 format, description, index는 mysql에서 사용하고 있는 예약어이기 때문이다.
데이터베이스 시스템이 자기만의 특수한 목적을 위해 이미 '찜'해놓은 단어들을 말한다.
MySQL에서 사용하는 예약어
index
"데이터를 빨리 찾기 위해 색인(Index)을 만들어라"라는 아주 중요한 명령어이다. 그래서 이걸 컬럼명으로 쓰면 DB는 "색인을 만들라는 거야, 아니면 컬럼 이름이라는 거야?"라며 헷갈려서 에러를 낸다.
format
특정 데이터의 형식을 바꾸는 함수 이름으로 예약되어 있다.
description
특정 데이터의 상세 구조를 보여달라는 명령(DESC)과 비슷하여 혼동을 줄 수 있다.
그래서 해당 컬럼명을 바꿔주도록 하겠습니다.
format -> form
description -> detail
index -> contents
ALTER TABLE books CHANGE COLUMN `format` form VARCHAR(45) NOT NULL;
ALTER TABLE books CHANGE COLUMN `description` detail LONGTEXT NULL;
ALTER TABLE books CHANGE COLUMN `index` contents LONGTEXT NULL;
만들어둔 도서 테이블에 데이터를 집어넣어줄겁니다.
자세한건 👉🏻 데이터 삽입 SQL문 해당 링크를 통해서 확인해주시면 되겠습니다.
우선 전체 도서 조회 api 구현하고 postman을 통해 확인해보겠습니다.
export const getAllbooks = (req, res) => {
const sql = `SELECT * FROM books`;
conn.query(sql, (err, results) => {
if (err) {
console.error("도서 전체 조회 요청 DB 에러:", err);
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json(err);
}
return res.status(StatusCodes.OK).json(results);
});
};
import express from "express";
import { getAllbooks, getBookById } from "../controller/bookController.js";
const router = express.Router();
router
.get("/", getAllbooks)
export default router;

// getAllBooks() 아래에 작성하면 됩니다.
export const getBookById = (req, res) => {
const { id } = req.params;
const sql = `SELECT * FROM books WHERE id = ?`;
conn.query(sql, [id], (err, results) => {
if (err) {
console.error("도서 개별 조회 요청 DB 에러:", err);
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json(err);
}
if (results[0]) {
return res.status(StatusCodes.OK).json(results[0]);
} else {
return res.status(StatusCodes.NOT_FOUND).json({
message: "존재하지 않는 도서입니다.",
});
}
});
};
router
.get("/", getAllbooks)
.get("/:id", getBookById);

piksum
웹사이트 레이아웃을 잡거나 테스트를 할 때, 실제 이미지가 준비되기 전 임시로 사용하는 플레이스홀더(Placeholder) 이미지 서비스입니다.
특징
별도의 API 키나 가입 없이 URL 주소만으로 이미지를 불러올 수 있습니다.
URL 끝에 가로/세로 해상도를 적으면 원하는 크기로 이미지를 생성해 줍니다.
매번 다른 이미지를 보여주거나, 특정 ID 값을 지정해 고정된 이미지를 가져올 수 있습니다.
ALTER TABLE books ADD COLUMN img INT NULL AFTER title;
ALTER TABLE books ADD COLUMN category_id INT NULL AFTER img;
export const getAllbooks = (req, res) => {
const { category_id } = req.query;
if (category_id) {
const sql = `SELECT * FROM books WHERE category_id=?`;
conn.query(sql, [caategory_id], (err, results) => {
if (err) {
console.error("카테고리별 조회 요청 DB 에러:", err);
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json(err);
}
return res.status(StatusCodes.OK).json(results);
});
} else {
const sql = `SELECT * FROM books`;
conn.query(sql, (err, results) => {
if (err) {
console.error("도서 전체 조회 요청 DB 에러:", err);
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json(err);
}
return res.status(StatusCodes.OK).json(results);
});
}
};

CREATE TABLE category (
id INT NOT NULL,
name VARCHAR(100) NOT NULL,
PRIMARY KEY(id)
);
INSERT INTO category (id, name)
VALUES
(0, '동화'),
(1, '소설'),
(2, '사회');
import conn from "../db/mysql_connect.js";
import { StatusCodes } from "http-status-codes";
export const getAllCategory = (req, res) => {
const sql = `SELECT * FROM category`;
conn.query(sql, (err, results) => {
if (err) {
console.error("카테고리 전체 조회 요청 DB 에러:", err);
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json(err);
}
return res.status(StatusCodes.OK).json(results);
});
};
import express from "express";
import { getAllCategory } from "../controller/categoryController.js";
const router = express.Router();
router.get("/", getAllCategory);
export default router;
import categoryRouter from "./routes/category.js";
app.use("/category", categoryRouter);

다음 시간에 카테고리별 도서 조회할 때 0,1,2 값이 아닌 category 테이블에 name (동화,소설,사회)처럼 나오도록 구현해볼 예정입니다.