pgms

[6주차] - [9기] 타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js) 10회차 - 29

Ejah 2026. 2. 15. 21:11

도서 API 구현

 

도서 테이블 생성

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;

 

 

도서 전체 조회 구현

우선 전체 도서 조회 api 구현하고 postman을 통해 확인해보겠습니다.

bookController

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);
  });
};

 

books.js

import express from "express";
import { getAllbooks, getBookById } from "../controller/bookController.js";

const router = express.Router();

router
  .get("/", getAllbooks)

export default router;

 

 

개별 도서 조회 구현

bookController

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: "존재하지 않는 도서입니다.",
      });
    }
  });
};

books.js

router
  .get("/", getAllbooks)
  .get("/:id", getBookById);

books 테이블에 이미지 컬럼 추가

ALTER TABLE books ADD COLUMN img INT NULL AFTER title;

 

카테고리별 도서 목록 조회

books 테이블에 category_id 컬럼 추가

ALTER TABLE books ADD COLUMN category_id INT NULL AFTER img;

 

bookController getAllBooks 수정

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);
    });
  }
};

결과

카테고리 API 구현

카테고리 테이블 생성

CREATE TABLE category (
  id INT NOT NULL,
  name VARCHAR(100) NOT NULL,
  PRIMARY KEY(id)
);

 

데이터 삽입

INSERT INTO category (id, name) 
VALUES 
  (0, '동화'),
  (1, '소설'),
  (2, '사회');

 

구현

categoryController

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);
  });
};

 

category.js

import express from "express";
import { getAllCategory } from "../controller/categoryController.js";

const router = express.Router();

router.get("/", getAllCategory);

export default router;

 

app.js 라우터 추가

import categoryRouter from "./routes/category.js";

app.use("/category", categoryRouter);

 

결과