본문 바로가기

공부/타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js)

프로젝트: Node.js 기반의 REST API 구현(14)- jwt 검증 함수 모듈, SQL_CALC_ROUND_ROWS-fount_rows(), 외부 모듈 faker

❄️jwt 검증하는 ensureAuthorization 함수를 모듈로 빼서 관리하기

utils 폴더로 따로 빼주고 파일을 만들어주었다❗

jwtUtils.js

 

❄️jwt 모듈을 적용한 코드

OrderController.js

 

BookController.js

지금의 jwt코드에서는 모듈내에서 err가 나면 response를 바로 보내주는 방식으로 구현되어있으므로,

authoriztion이 있을때 id값을 user_id에 넣고, qeury문과 params도 있을때에만 넣어주게

삼항연산자를 사용하여 코드를 구현했다❗

 

Headers가 없을 때 (비로그인)

 

Headers가 있을 때(로그인)

 

전체 도서 조회시 현재 페이지와 총 도서의 수를 response로 보내주기

 

 

✨SQL_CALC_FOUND_ROWS

코드 실행으로 COUNT(*)과 다르지 않지만

COUNT(*)가 테이블의 SELECT를 한 번 더 해야하지만

SQL_CALC_FOUND_ROWS는 한 번으로 가능하다

하지만 데이터가 많아질수록 성능 저하의 우려가 있다.

추가적으로 MySQL 8.0 부터는 더 이상 권장되지 않는 기능이라고 한다.

결론: COUNT(*)를 사용하는것이 더 좋다❗

SELECT SQL_CALC_FOUND_ROWS * FROM books;
SELECT found_rows();

 

 

 

✨API 다시 정리하기

도서API

1. 전체 도서 조회

    // 이미지 경로, 조회시 아이템 8개씩 보여주기

    // 카테고리 id 어떻게 알고 보내줄까?

Method GET
URI /books?limit={page 당 도서 수}&currentPage={현재 page}
HTTP status code 성공 200
Request Body  
Response Body {
     book: [
         {
             "book_id" : "도서 id",
             "title" : "도서명",
             "category" : "도서 카테고리",
             "summary" : "요약 설명",
             "author" : "작가명",
             "price" : 가격,
             "likes" : 좋아요 수,
             "pubDate" : "출간일"
         },
         {
             "book_id" : "도서 id",
             "title" : "도서명",
             "category" : "도서 카테고리",
             "summary" : "요약 설명",
             "author" : "작가명",
             "price" : 가격,
             "likes" : 좋아요 수,
             "pubDate" : "출간일"
         },
         ...
    ],
    pagination: {
         "currentPage": 현재 페이지,
         "totalBooks": 총 도서 수

    }
}

2. 개별 도서 조회

    // 이미지 경로

Method GET
URI /books/:{bookId}
HTTP status code 성공 200
Request Body  
Response Body {
    "book_id" : "도서 id",
    "title" : "도서명",
    "category" : "도서 카테고리",
    "format" : "포맷",
    "isbn" : "isbn",
    "summary" : "요약 설명",
    "description" : "상세 설명",
    "author" : "작가명",
    "pages" : 쪽 수,
    "index" : "목차",
    "price" : 가격,
    "likes" : 좋아요 수,
    "liked" : boolean,
    "pubDate" : "출간일"
}

3. 카테고리별 도서 목록 조회

    -new: true=> 신간조회(기준: 출간일 30일 이내)
=>출간일을 설정하면 sql에서 30이내인 것을 계산해 줄 수 있다.

    // 이미지 경로, 조회시 아이템 8개씩 보여주기

    // 카테고리 id 어떻게 알고 보내줄까?

=>id는 숫자로 사용하고 카테고리 테이블을 생성해서 각 숫자별로 장르를 설정해놓는다.

Method GET
URI /books?category={categoryId}&new={boolean}
HTTP status code 성공 200
Request Body  
Response Body [
    {
        "book_id" : "도서 id",
        "title" : "도서명",
        "category" : "도서 카테고리",
        "summary" : "요약 설명",
        "author" : "작가명",
        "price" : 가격,
        "likes" : 좋아요 수 ,
        "pubDate" : "출간일"
    },
    {
        "book_id" : "도서 id",
        "title" : "도서명",
        "category" : "도서 카테고리",
        "summary" : "요약 설명",
        "author" : "작가명",
        "price" : 가격,
        "likes" : 좋아요 수 ,
        "pubDate" : "출간일"
    },
    ...
]

장바구니 API

1. 장바구니 담기

Method POST
URI /cart
HTTP status code 성공 201
Request Headers Authorization - jwt token
Request Body {
    "book_id" : "도서 id",
    "count" : 수량
}
Response Body  

2. 장바구니 조회

Method GET
URI /cart
HTTP status code 성공 200
Request Headers Authorization - jwt token
Request Body  
Response Body [
    {
        "cartItem_id" : 장바구니 도서 id,
        "book_id" : 도서 id,
        "title" : "도서명",
        "category" : "도서 카테고리",
        "summary" : "요약 설명",
        "count" : 수량
        "price" : 가격,
    },
    {
        "cartItem_id" : 장바구니 도서 id,
        "book_id" : 도서 id,
        "title" : "도서명",
        "category" : "도서 카테고리",
        "summary" : "요약 설명",
        "count" : 수량
        "price" : 가격,
    },
    ...
]

3. 장바구니 도서 삭제

Method DELETE
URI /cart/:{bookId}
HTTP status code 성공 200
Request Headers Authorization - jwt token
Request Body  
Response Body  

4. 장바구니에서 선택한 주문 '예상' 상품 목록 조회

Method GET
URI /cart/:{bookId}
HTTP status code 성공 200
Request Headers Authorization - jwt token
Request Body ["cartItem_id", "cartItem_id", ...]
Response Body [
    {
        "cartItem_id" : 장바구니 도서 id,
        "book_id" : "도서 id",
        "title" : "도서명",
        "category" : "도서 카테고리",
        "summary" : "요약 설명",
        "count" : 수량
        "price" : 가격,
    },
    {
        "cartItem_id" : 장바구니 도서 id,
        "book_id" : "도서 id",
        "title" : "도서명",
        "category" : "도서 카테고리",
        "summary" : "요약 설명",
        "count" : 수량
        "price" : 가격,
    },
    ...
]

결제(주문) API

1. 결제하기

= 주문하기 = 주문등록 = 데이터베이스 주문 insert = 장바구니에서 주문된 상품은 delete

Method POST
URI /orders
HTTP status code 성공 200
Request Headers Authorization - jwt token
Request Body {
    "items" : [
        {
            "cartItem_id" : 장바구니 도서 id,
            "book_id" : 도서 id,
            "bookTitle" : "대표 책 제목",
            "count" : 수량
        },
        {
            "cartItem_id" : 장바구니 도서 id,
            "book_id" : 도서 id,
            "bookTitle" : "대표 책 제목",
            "count" : 수량

        },
        ...
    ],
    "delivery" : {
        "address" : "주소",
        "receiver" : "받는 사람",
        "contact" : "010-0000-0000"
    },
    "totalPrice" : 총 금액,
    "totalCount" : "총 수량"

}
Response Body  

2. 결제목록(내역) 조회

Method GET
URI /orders
HTTP status code 성공 200
Request Headers Authorization - jwt token
Request Body  
Response Body [
    {
        "orders_id" : 주문 id,
        "create_at" : "주문일자",
        "delivery" : {
            "address" : "주소",
            "veceiver" : "받는 사람",
            "contact" : "전화번호"
    },
    "bookTitle" : "대표 책 제목",
    "totalPrice" : "총 금액",
    "totalCount" : "총 수량"
]

3. 주문 상세 상품 조회

Method GET
URI /orders/:{orderId}
HTTP status code 성공 200
Request Headers Authorization - jwt token
Request Body  
Response Body [
    {
        "book_id" : 도서 id,
        "bookTitle" : "대표 책 제목",
        "author" : "작가명",
        "price" : 가격,
        "count" : 수량
    },
    {
        "book_id" : 도서 id,
        "bookTitle" : "대표 책 제목",
        "author" : "작가명",
        "price" : 가격,
        "count" : 수량
    },
    ...
]

 

🗝️코드 퀄리티를 올려보자

  • 중복코드 => 모듈화

    ex) UserController.js => User (데이터모듈 = Model) - CRUD

DB 모듈: MySQL => 몽구스, 시퀄라이즈

  • 패키지구조
  1. Router :경로(URI, URL)와 HTTP method로 요청에 따른 경로를 찾아주는 역할
  2. Controller
  3. Service
  4. Model : 데이터베이스와 소통
  • 예외처리 (try...catch)
  • 유효성 검사
  • jwt
    • 로그인 시 access token(30m), refresh token(24h)
  1. access token 인증
  2. refresh token 연장
  • 랜던 데이터(외부) API를 활용해서 isbn 샘플 데이터 채워보기

 

❄️랜덤 데이터 API  사용해보기

개요

  • 랜덤 데이터를 생성해주는 API (외부 API)를 기반으로 가짜 사용자 정보 생성 API

내용

  1. 랜덤 데이터 생성 API (가짜 사용자, 상품, 전화번호 등)
  2. 가짜 사용자 정보를 생성하는 Express 웝/앱 API

랜덤 데이터 생성 API

  • faker

https://fakerjs.dev/

 

Faker

Faker Generate massive amounts of fake (but realistic) data for testing and development.

fakerjs.dev

 

  • mokaroo

https://www.mockaroo.com/

 

Mockaroo - Random Data Generator and API Mocking Tool | JSON / CSV / SQL / Excel

Mock your back-end API and start coding your UI today. It's hard to put together a meaningful UI prototype without making real requests to an API. By making real requests, you'll uncover problems with application flow, timing, and API design early, improvi

www.mockaroo.com

 

❄️faker 사용해보기

yarn add -D @faker-js/faker

npm의 --save-dev 혹은 yanr의 -D나 -dev는 개발의존성 설치로

개발단계에서만 사용하고 배포 후에는 사용하지 않을 것임을 나타내는 것이고

배포 후에도 사용할 것이라면 이 부분은 빼고 외부모듈이름만 적어서 설치하면 된다.