BookShop 프로젝트의 API들에서, userId를 JWT를 이용해서 가져오기 위하여
다음의 코드를 작성하였었다.
const extractUserId = function (req, res) {
try {
let token = req.headers["authorization"]
if (token == undefined) {
return undefined
} else {
const userId = jwt.verify(token, process.env.PRIVATE_KEY).userId;
return userId
}
} catch (err) {
console.log(err.name);
console.log(err.message);
return err;
}
}
위 코드는, Postman에서 request를 보낼 때, Header에 Authorization의 값이 적절하지 않으면 오류 객체를 돌려주는 함수다.
이 코드는 BookShop 프로젝트의 많은 API들에서 회원을 검증하기 위해 사용하기 때문에, 모듈로 만들어서 require하여 사용하였다.
token이 undefined인 경우는 서점의 웹페이지에서 사용자가 도서별 좋아요를 눌렀는지의 여부를 확인하기 위하여 토큰을 확인하였다. 즉, 토큰이 아무런 값이 없다면 좋아요를 누르지 않은 상태로 도서 정보들을 돌려주고, 토큰에 회원의 값이 들어있다면, 좋아요의 여부와 함께 도서 정보를 돌려준다.
또한, 장바구니 API에서, request에 cartIds 값이 아예 없으면, userId를 이용해서 사용자가 가진 전체 장바구니를 조회하도록 하였고, cartIds key값은 전달되는데, 값이 없을 경우([ ])에는 항목을 선택해달라는 메시지를 보냈고, cartIds에 값이 있으면, 해당 장바구니 데이터를 조회하도록 하였다.
좋아요 API에서는, 좋아요 버튼을 눌렀을 때 좋아요 개수의 변화의 처리에 대해서 고려해보았는데, 다음과 같은 방법들을 생각했다.
좋아요 버튼을 눌렀을 때, 백엔드에서 좋아요 개수를 추가/삭제 후, SELECT count(*) 하여 다시 클라이언트에게 돌려준다.
데이터베이스의 동기화는 나중에 시키고, 일단 프론트엔드에서 사용자에게 좋아요수가 1개 변화한것처럼 보여준다.
(+) 좋아요 추가 / 좋아요 삭제 API를 나누지 않고, 테이블을 조회해서 좋아요가 없을 때 요청하면, 좋아요를 추가하고 좋아요가 있을 때 요청하면 좋아요 취소하기.
이 중에서 2번 방법과 비슷하게, 저번 포스트에서 찾아봤던 Redis를 이용해서 자주 변화가 일어나는 데이터는 한번에 모아뒀다가 , 메인 DB에 한번에 동기화 시키는 것이 성능측에서 좋을 것 같다는 생각을 했다.
1번의 방법은 데이터의 개수가 많을 때 매번 테이블을 조회하는 것은 서버에 부담이 클 것 같다고 생각했다.
마지막으로, 도서 조회 API에서는 프론트엔드가 전체 페이지와 현재 페이지를 respond 받아야 사용자에게 화면을 뿌려줄 수 있기 때문에 이 값을 추가했다.
그래서 도서를 조회할 때 respond된 JSON은 다음과 같은 형태를 가진다.
{
books : [ {책1의정보} , {책2의정보}] ,
pagination : [ totalCount : {전체 상품 개수} , currentPage {현재 페이지 }]
}
프론트엔드에서는 무한 스크롤 이라는 기법을 활용할 수도 있다고 한다.
무한 스크롤이란, 한번에 모든 데이터를 조회하는게 아니라 우리가 페이지를 내리면서 일정량의 데이터를 계속해서 나누어서 뿌려주는 것이다.
또한, 전체 페이지값은 프론트엔드에서 전체 데이터 개수와 LIMIT 값을 이용해서 구할 수 있으므로, 전체 페이지 값을 돌려주는 것보다는 전체 데이터 개수를 돌려주는 것이 프론트엔드에서 다양하게 활용할 수 있기 때문에, 위 코드처럼 전체 상품 개수를 돌려주었다.
그렇다면, 백엔드에서는 mysql2 모듈을 이용하면서 총 개수를 조회해서 돌려줘야한다.
총 개수를 조회하는 대표적인 방법은 2가지가 있다.
SELECT * FROM BookShop.books LIMIT 4 OFFSET 0 ;
SELECT count(*) FROM books AS totalCount;
SQL_CALC_FOUND_ROWS 이용하기SELECT SQL_CALC_FOUND_ROWS * FROM BookShop.books LIMIT 4 OFFSET 0;
SELECT found_rows();
2번의 방법은 asterisk(*) 앞에 SQL_CALC_FOUND_ROWS를 붙여주기만 하면 된다.
이 방법은 전체 테이블을 조회하는 동시에 데이터의 개수를 found_rows()에 저장한다.
따라서 SELECT found_rows(); 쿼리를 수행하면서 간단하게 전체 개수를 얻을 수 있다.
이 방법이 좋은 이유는, 1번 방법은 전체 테이블을 두번 조회해야 하는 반면에 2번 방법은 한 번만 테이블을 조회하면서 개수를 세기 때문에 성능적인 측면에서 유리하다는 점이 있다.
SELECT found_rows() 의 조회결과는
[{"found_rows()" : 11}]
처럼 나온다.
따라서, js에서 key값을 이용해서 값을 호출할 때,
results[0].found_rows()
위와 같이 점 표기법으로 호출하면, 메소드로 인식하여 오류가 발생한다.
따라서,
results[0]["found_rows()"]
위와 같은 방식으로 값을 사용하여야 함에 주의하자.