1. 데이터베이스 테이블 만들기 - books
CREATE TABLE `book-shop`.`books` (
`id` INT NOT NULL AUTO_INCREMENT,
`title` VARCHAR(45) NOT NULL,
`category_id` INT NOT NULL,
`form` VARCHAR(45) NOT NULL,
`isbn` VARCHAR(45) NOT NULL,
`summary` VARCHAR(500) NULL,
`detail` LONGTEXT NULL,
`author` VARCHAR(45) NULL,
`pages` INT NOT NULL,
`contents` LONGTEXT NULL,
`price` INT NOT NULL,
`pub_date` DATE NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `isbn_UNIQUE` (`isbn` ASC) VISIBLE);
2. 도서 API 만들기
2.1. books 라우터
const express = require('express');
const router = express.Router();
const {
allBooks,
bookDetail,
booksByCategory
} = require('../controller/bookController');
router.use(express.json());
// 전체 도서 조회
router.get('/', allBooks);
// 개별 도서 조회
router.get('/:id', bookDetail);
// 카테고리별 도서 목록 조회
router.get('/', booksByCategory);
module.exports = router;
2.2. 전체 도서 조회
데이터베이스에 있는 전체 도서 목록을 리스폰스로 다 받으면 된다. 도서들이 json 배열로 리스폰스에 담겨 돌아온다.
const allBooks = (req, res) => {
// (요약된) 전체 도서 리스트
let sql = `SELECT * FROM books`;
conn.query(sql, (err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
res.status(StatusCodes.OK).json(results);
}
)
}
2.3. 개별 도서 조회
id 에 맞는 도서가 없다면 NOT_FOUND, id 에 맞는 도서가 있다면 OK 상태코드와 함께 results[0] 을 돌려준다.
results 는 기본적으로 json 배열 형태이기 때문에 아래의 모양으로 리스폰스에 담겨온다. 그래서 result[0] 으로 배열을 벗기고 내용물만 가져온다.
[
{
"id": 2,
"title": "신데렐라들",
"form": "종이책",
"isbn": "1",
"summary": "유리구두",
"detail": "투명한 유리구두",
"author": "김구두",
"pages": 100,
"contents": "목차입니다",
"price": 20000,
"pub_date": "2022-01-01"
}
// 개별 도서 조회
const bookDetail = (req, res) => {
const {id} = req.params;
let sql = `SELECT * FROM books WHERE id = ?`;
conn.query(sql, id,
(err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
if (results[0])
return res.status(StatusCodes.OK).json(results[0]);
else
return res.status(StatusCodes.NOT_FOUND).end();
}
)
}
2.4. 카테고리별 도서 조회
// 카테고리별 도서 조회
const booksByCategory = (req, res) => {
const {category_id} = req.query;
let sql = `SELECT * FROM books WHERE category_id = ?`;
conn.query(sql, category_id,
(err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
if (results.length)
res.status(StatusCodes.OK).json({results});
else
res.status(StatusCodes.NOT_FOUND).end();
}
)
}
코드를 짜고 포스트맨으로 결과가 잘 날라오나 테스트를 해보았는데, 이상한 리스폰스가 왔다.
쿼리로 보낸 카테고리에 해당하는 결과가 아니라 전체 데이터가 다 들어있는 리스폰스가 돌아온 것이다.
라우터 파일을 보면 전체 도서 조회와 카테고리별 도서 목록 조회가 같은 url 을 사용하고 있는 것을 알 수 있다.
그래서 카테고리별 도서 목록 조회 요청이 날라와도 전체 도서 조회에 걸리기 때문에 발생하는 문제였다.
// books.js -> 라우터 파일
// 전체 도서 조회
router.get('/', allBooks);
// 개별 도서 조회
router.get('/:id', bookDetail);
// 카테고리별 도서 목록 조회
router.get('/', booksByCategory);
그렇다면 카테고리별 도서 목록 조회를 전체 도서 조회보다 위에 위치시키면 문제가 해결되지 않을까 했지만 문제는 해결되지 않았다.
카테고리별 도서 목록 조회는 잘 되었지만, 전체 도서를 조회하려고 했을 때 에러가 catagory_id 쿼리가 없다는 에러가 발생했다.
그렇다면 어떻게 해결할 수 있을까?
-> 전체 도서 조회와 카테고리별 도서 목록 조회 합치기
// books.js -> 라우터 파일
router.get('/', allBooks);
const allBooks = (req, res) => {
const {category_id} = req.query;
if (category_id) { // 쿼리가 있다면 카테고리별 도서 목록 조회
let sql = `SELECT * FROM books WHERE category_id = ?`;
conn.query(sql, catagory_id,
(err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
if (results.length)
res.status(StatusCodes.OK).json({results});
else
res.status(StatusCodes.NOT_FOUND).end();
}
)
} else { // 쿼리가 없다면 전체 도서 조회
let sql = `SELECT * FROM books`;
conn.query(sql, (err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
res.status(StatusCodes.OK).json(results);
}
)
}
}
2.5. 카테고리 테이블 만들기
카테고리별 도서 조회할 때 catagory_id 를 사용해서 카테고리를 구별했다. 근데 상세 페이지에서 보여줄 카테고리는 숫자로 된 id 값이 아니라 동화, 소설과 같은 문자열이다. 그렇기 때문에 따로 카테고리 테이블을 만들어서 매칭 시켜주는 것이 필요하다.
번거롭게 카테고리 테이블을 만들어서 매칭시켜주는 것이 아니라 바로 카테고리 문자열을 넣어주는 것이 더 낫지 않을까? 라고 생각할 수 있는데, 카테고리가 많고 복잡하여 관리가 어렵기 때문에 따로 문자열 대신 숫자를 넣어서 관리하고 카테고리 테이블을 따로 두는 것이 더 낫다.
- 데이터베이스에 카테고리 테이블 만들기
CREATE TABLE `book-shop`.`category` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL);
- 카테고리 API
카테고리 전체 목록 조회
Method | GET |
URI | /catagory |
HTTP status code | 성공 200 |
Request Body | |
Response Body | { { id: 0, name: "동화" }, { id: 1, name: "소설" } ... } |
3. 이미지 경로 추가
3.1. 데이터베이스 테이블에 img 행 추가하기
picsum 이라는 사이트에서 사진을 무료로 쓸 수 있는데, 아래 url 에서 id 문자열 뒤에 값이 사진의 id 값이다.
데이터베이스에 사용할 사진의 id 값만 저장해서 사용하기 위해 img 행을 추가하고 사진의 id 값을 저장해주었다.
https://picsum.photos/id/1/200/300

Lorem Picsum
Lorem Picsum
Lorem Ipsum... but for photos
picsum.photos
'TIL with Programmers' 카테고리의 다른 글
[TIL] 10/7 API 구현, LEFT JOIN, DATE_ADD, DATE_SUB, 페이징 (0) | 2024.10.07 |
---|---|
[회고록] 풀 사이클 개발 데브코스 7주차 회고 (1) | 2024.10.05 |
[TIL] 10/2 http-status-codes, 회원가입, 로그인, 비밀번호 변경, 비밀번호 암호화하기 (1) | 2024.10.02 |
[TIL] 10/1 API 설계 & 수정, ERD 테이블 (1) | 2024.10.01 |
[TIL] 9/30 ERD 테이블, API 설계 및 수정 (1) | 2024.09.30 |