[DevCamp] 스프린트 프로젝트 2 - pagination 추가 및 프로젝트 마무리

동건·2025년 3월 24일

DevCamp

목록 보기
34/85

스프린트 프로젝트 2 - pagination 추가 및 프로젝트 마무리

3월 10일에 시작한 도서 구매 플랫폼 프로젝트가 오늘 끝이났다.
오늘은 회원 인증을 모듈화 하였고 모듈화를 기반으로 코드를 정리하고
도서 전체 조회에 pagination 도 정리를 하였다.


auth.js

const jwt = require('jsonwebtoken');
const dotenv = require('dotenv').config();

const ensureAuthorization = (req, res) => {
    try{
        let receivedJWT = req.headers["authorization"];
        console.log("received JWT : ", receivedJWT);

        if(receivedJWT){
            let decodedJWT = jwt.verify(receivedJWT, process.env.PRIVATE_KEY);
            console.log(decodedJWT);

            return decodedJWT;
        }else{
            throw new ReferenceError("JWT not found");
        }
    }catch(err){
        console.log(err.name);
        console.log(err.message);

        return err;
    }
}

module.exports = {
    ensureAuthorization
}

../utils/auth.js 로 따로 ensureAuthorization 모듈을 만들었다.


로그인 여부에 따른 도서 조회 API

const bookDetail = (req, res) => {

    // 로그인 상태가 아니면 liked 빼고 보내주기
    // 로그인 상태이면 liked 추가하고 보내주기
    const {bookId} = req.params;
        
    let authorization = ensureAuthorization(req, res);

    if(authorization instanceof jwt.TokenExpiredError){
        return res.status(StatusCodes.UNAUTHORIZED).json({
            "message" : "로그인 세션이 만료되었습니다. 다시 로그인 해주세요."
        });
    } else if(authorization instanceof jwt.JsonWebTokenError){
        return res.status(StatusCodes.BAD_REQUEST).json({
            "message" : "잘못된 토큰입니다."
        });
    }else{
        let {bookId} = req.params;
        let values = [];
        
        let sql = `SELECT *,
            (SELECT COUNT(*) FROM likes WHERE liked_book_id=books.id) AS likes,
            (SELECT EXISTS(SELECT * FROM likes WHERE likes.user_id=? AND likes.liked_book_id=?)) AS liked`;
        values = [authorization.id, bookId];
        if(authorization instanceof ReferenceError){
            sql = `SELECT *,
            (SELECT COUNT(*) FROM likes WHERE liked_book_id=books.id) AS likes`;
            values = [];
        }
        sql+=` FROM books
            LEFT JOIN category
            ON books.category_id = category.category_id
            WHERE books.id = ?;`;
    
        console.log(sql);
        values.push(bookId);
        conn.query(sql, values, (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();
            }
        });
    }
};

BookController.js 에서 도서 상세 조회에서
사용자가 로그인을 했는지 여부에 따라서 좋아요를 눌렀는지 안눌렀는지 출력되게 수정을 했다.

ensureAuthorization 모듈을 불러오고
분기 처리를 통해 SQL문을 수정해 구현을 했다.

코드의 상세한 내용은 이전 포스트를 참조하면 된다.


Pagination

Pagination 구현을 하면서 수정사항이 생겼다.
전체 도서 개수도 같이 전달해야한다.

처음에는 COUNT() 를 생각했지만
SQL에서 제공하는 SQL_CALC_FOUND_ROWS 를 사용해서 코드를 작성했다.

const { category_id, check_new, limit, currentPage } = req.query;

let offset = limit * (currentPage - 1);

let sql = `SELECT SQL_CALC_FOUND_ROWS * , (SELECT COUNT(*) FROM likes WHERE liked_book_id = books.id) AS likes FROM books`

let values =[];

if (category_id && check_new){
  sql += ` WHERE category_id=? AND pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()`;
  values = [category_id];
}
else if(category_id){
  sql += ` WHERE category_id=?`;
  values = [category_id];
}else if(check_new){
  sql += ` WHERE pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()`;
}
sql += ` LIMIT ? OFFSET ?`

values.push(parseInt(limit) , offset);

🔨 TIL

드디어 길었던 BE 프로젝트를 끝냈다.
다음에는 바로 FE 학습과 프로젝트를 들어가는데
아는 내용들이라 어렵지않게 진행할 수 있을 것 같다.

강사님과 함게 BE 학습을 하였고 멘토링 팀 내에서도 사이드 프로젝트로
BE 역할로 마무리를 해봤는데
이번 기회에 BE의 이해가 쉬워져서 앞으로 어느 역할이든 무리없이
진행 할 수 있는 자신감이 생겼다.

profile
배고픈 개발자

0개의 댓글