본문 바로가기

프로그래머스 풀스택 데브코스/데브코스 TIL

웹 풀사이클 데브코스 TIL 41일차

jwt 분리

auth.js 파일을 만들어서 jwt 부분을 모듈화 하였다.

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

const ensureAuthorization = (req, res) => {

    try{
        let receivedJwt = req.headers["authorization"];
        console.log("received jwt : ", receivedJwt);

        let decodedJwt = jwt.verify(receivedJwt, process.env.PRIVATE_KEY);
        console.log(decodedJwt);

        return decodedJwt;
    } catch(err) {
        console.log(err.name);
        console.log(err.message);

        return err;
    }

};
module.exports = ensureAuthorization;

다른 컨트롤러들에서 이를 import 해서 사용할 수 있고 반복되는 코드를 줄일 수 있다.

내 장바구니 조회

지금 api에서는 한가지 옥의티가 있는데 장바구니 상품을 조회할때 selected 값이 없으면 조회가 안된다는 것이다. 그냥 사용자 정보만으로 장바구니 상품을 조회할 api도 필요하다.

 let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price 
    FROM cartItems LEFT JOIN books 
    ON cartItems.book_id = books.id
    WHERE user_id = ?`;

    let values = [authorization.id];

    if(selected) { // 주문서 작성시 '선택한 장바구니 목록 조회'
        sql += ' AND cartItems.id IN (?)';
        values.push(selected);
    }

간단하게 selected 가 있느냐 없느냐에 따라 sql 과 values 를 분리해보았다.

로그인 여부에 따라 다른 응답을 주기

BookController의 도서 상세정보의 경우를 예시로 들어보자. 도서 상세정보는 로그인 없이도 볼 수 있다. 하지만 로그인이 되어있을 경우 그 도서를 좋아요 했는지 아닌지 여부를 함께 전송해주어야한다. 이를 구분하기 위해서 auth.js를 변경해주어야한다.

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 must be provided");
        }

    } catch(err) {
        console.log(err.name);
        console.log(err.message);

        return err;
    }

};

만약 클라이언트에서 jwt를 보내지 않으면 receivedJwt에는 undefined 값이 들어가게 된다. 값이 없다면 ReferenceError를 던져주기로 정하였다.

전체 도서 페이징

요구사항을 잘 살펴보면 전체도서 조회를 할 때 전체 도서 수도 함께 전달해 주어야 하는 것을 알 수 있다. 전체 도서의 갯수르 아는 방법은 이전에도 살펴보았다.

SELECT * FROM Bookshop.books LIMIT 4 OFFSET 0;
SELECT count(*) FROM Bookshop.books;

이 방식은 결국 select를 두번해야되는 방식이라 비효율적이다. 더 성능이 좋은 방식이 있다.

SELECT SQL_CALC_FOUND_ROWS * FROM Bookshop.books LIMIT 4 OFFSET 0;
SELECT found_rows();

이렇게 하면 select를 하면서 rows 값을 계산해서 저장해두었다가 불러오는 방식으로 더 성능이 좋게 사용할 수 있다. 디민 mysql 공식 문서에서는 deprecated된 방식이라고 나와있어서 참고해야할 것 같다.

이 명령어로 값을 가져오는데 한가지 문제가 생겼다.

conn.query(sql, (err, results) => {
        if(err) {
            console.log(err);
            return res.status(StatusCodes.INTERNAL_SERVER_ERROR);
        }

        let pagination = {};    
        pagination.currentPage = parseInt(page);
        pagination.totalCount = results.found_rows();

        allBooksRes.pagination = pagination;

        return res.status(StatusCodes.OK).json(allBooksRes);
})

results에서 값을 꺼내오는데 found_rows()로 접근하려고 하니 js에서 이를 함수로 인식한다는 문제가 있다. 이럴 때는 점 표기법이 아니라 괄호 표기법을 사용하면 된다.

let pagination = {};    
pagination.currentPage = parseInt(page);
pagination.totalCount = results[0]["found_rows()"];

후기

jwt 부분을 모듈화하였고, 로그인 여부에 따라 다른 응답을 주는 방법에 대해서도 학습하였다.

키워드: 프로그래머스 데브코스, 국비지원교육, 코딩부트캠프