도서 쇼핑몰 API 설계 (14)

차재현·2024년 4월 23일
post-thumbnail

✔️ [변경 사항]

  1. 로그인 상태 여부 확인이 필요한 모든 API 설계에 request HEADER 설명 추가
  2. 장바구니 조회 기능의 request Body 설명 추가
  3. 각 API의 URL params값 명시
  4. 전체 도서 조회 API의 Response값에 pagination JSON 추가
  5. 카테고리 및 신간 별 도서조회에도 pagination 기능 추가하도록 설계 변경
  6. 모든 스네이크 기법의 변수를 카멜 기법으로 전환
  7. 주문 목록, 주문 상세 조회 API에서 사용자 id 별로 조회하도록 조회SQL 추가 필요


1. 회원 API 설계

  • 회원 가입 API
    • Method : POST
    • URL : /users/join
    • Request Body
      • JSON
        {
        	email : "사용자가 입력한 이메일",
        	password : "사용자가 입력한 비밀번호"
        }
    • Response
      • 201 : 로그인 페이지로 이동

  • 로그인 API
    • Method : POST
    • URL : /users/login
    • Request BODY
      • JSON
        {
        	email : "사용자가 입력한 이메일",
        	password : "사용자가 입력한 비밀번호"
        }
    • Response Cookie
      • 200
        • JWT token - PAYLOAD
          {
          	id : 사용자 id,
          	email : 사용자 email	
          }

  • 비밀번호 초기화 요청 API ( = 비밀번호를 잊었을 때 사용하는 기능 = 로그인 하지 않은 상황)
    • Method : POST
    • URL : /users/reset
    • Request Body
      • JSON
        {
        	email : "사용자가 입력한 이메일"
        }
    • Response
      • 200
        • JSON
          {
          	email : "이메일"
          }
          • 인증을 위해 입력했던 이메일을 가지고 비밀번호 초기화 화면으로 이동

  • 비밀번호 초기화 API ( = 수정)
    • Method : PUT
    • URL : /users/reset
    • Request Body
      • JSON
        {
        	email : "이전 페이지에서 입력했던 이메일",
        	password : "사용자가 입력한 새로운 비밀번호"
        }
    • Response
      • 200 :

2. 도서 API 설계

  • 전체 도서 조회 API
    • Method : GET
    • URL : /books?limit={page 당 도서 개수}¤tPage={현재 page}
      • 페이징 기능 구현을 위해 limit, 현재 page 값을 URL로 받아오도록 한다.
      • offset = limit * (currentPage-1) 을 활용한다.
    • Request Body : X
    • Response (이미지 경로, n개씩 응답 → 2가지 고려해야 함.)
      • 200
        • JSON Array
          // 전체 도서 목록에는 도서의 상세 정보를 모두 포함합니다.
          // 필요한 데이터만 선별하여 구현 부탁드립니다.
          {
          books : [
                      {
                          id : 도서 id,
                          title : "도서 제목",
                          img : 이미지 id (picsum image #num),
                          summary : "요약 설명",
                          author : "도서 작가",
                          price : 가격,
                          likes : 좋아요 수,
                          pubDate : 출간일
                      },
                      {
                          id : 도서 id,
                          title : "도서 제목",
                          summary : "요약 설명",
                          author : "도서 작가",
                          price : 가격,
                          likes : 좋아요 수,
                          pubDate : 출간일
                      },
                      ...
                  ],
          pagination : {
                          currentPage : 현재 페이지,
                          totlaCount : 총 도서 수	
                      }
          }
          • 전체 도서 목록에서 개별 도서 조회 URL로 이동하기 위해서 각 도서 JSON마다 도서 id(book_id)를 가지고 있어야 한다.
          • 전체 도서 데이터를 DB에서 가지고 올 때, 도서들의 모든 정보를 가져오는 것으로 설계하였기 때문에 프론트엔드 개발자에게 전체 데이터중에 필요한 데이터만 사용하라고 알려주도록 한다.
          • 서브쿼리를 통해 BookController.js에서 sql을 수정해준것 만으로 좋아요 수도 응답할 수 있게 되었다.
          • (new)프론트엔드 측으로부터의 요구사항에 의해 pagination에 필요한 데이터도 추가로 전달한다.

  • 개별 도서 조회 API
    • Method : GET
    • URL : /books/:id
      • Request params : book_id
    • (new)Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request Body : X
    • Response(이미지 경로 → 고려해야 함)
      • 200
        • JSON
          {
          	id : 도서 id,
          	title : "도서 제목",
          	img : 이미지 id (picsum image #num),
          	format : "포맷",
          	isbn : "isbn",
          	summary : "요약 설명",
          	detail : "상세 설명",
          	author : "도서 작가",
          	pages : 쪽 수,
          	contents : "목차",
          	price : 가격,
          	likes : 좋아요 수,
          	liked : boolean, (<- (new)로그인 상태에만 응답에 넣어준다.)
          	pubDate : 출간일
          }
          • 서브쿼리를 통해 BookController.js에서 sql을 수정해준것 만으로 좋아요 수도 응답할 수 있게 되었다.
          • SELECT EXISTS 쿼리를 통해 likes 테이블에 특정 유저가 특정 책을 좋아요 추가했는지에 대한 데이터가 존재하는지 확인하여 응답할 수 있게 되었다.
          • 특정 유저가 현재 조회중이 도서를 좋아요 했는지에 대한 것을 확인하기 위해 원래 JWT의 데이터를 읽어야 하지만, 현재는 BODY 값으로 전달된다는 전제하에 기능을 먼저 구현중이다.
          • (new)JWT 토큰을 이용해 로그인 여부 확인 및 로그인 상태에 따라 개인의 좋아요 정보 제어 가능

  • 카테고리 별 도서 목록 조회 API
    • Method : GET
    • URL : /books?limit={page 당 도서 개수} & currentPage={현재 page} & category_id = {category_id} & news = {boolean} & limit={page 당 도서 개수} & currentPage={현재 page}
      • news = true 이면 카테고리 별 신간 조회 (기준 : 출간일(pubDate) 한 달 이내)
      • 페이징 기능 구현을 위해 limit, 현재 page 값을 URL로 받아오도록 한다.
      • offset = limit * (currentPage-1) 을 활용한다.
    • Request Body : X
    • Response (이미지 경로, n개씩 응답, 카테고리 아이디..? → 3가지 고려해야 함)
      • 200
        • JSON Array
          // 전체 도서 목록에는 도서의 상세 정보를 모두 포함합니다.
          // 필요한 데이터만 선별하여 구현 부탁드립니다.
          {
          books : [
                      {
                          id : 도서 id,
                          title : "도서 제목",
                          img : 이미지 id (picsum image #num),
                          summary : "요약 설명",
                          author : "도서 작가",
                          price : 가격,
                          likes : 좋아요 수,
                          pubDate : 출간일
                      },
                      {
                          id : 도서 id,
                          title : "도서 제목",
                          summary : "요약 설명",
                          author : "도서 작가",
                          price : 가격,
                          likes : 좋아요 수,
                          pubDate : 출간일
                      },
                      ...
          		],
          pagination : {
                          currentPage : 현재 페이지,
                          totlaCount : 총 도서 수	
          	         }
          }
    • 전체 도서 조회 기능의 코드와 합쳐져있음을 인지하자.
    • 서브쿼리를 통해 BookController.js에서 sql을 수정해준것 만으로 좋아요 수도 응답할 수 있게 되었다.

3. 카테고리 API 설계 (카테고리 테이블 생성)

  • 카테고리 전체 조회 API
    • Method : GET
    • URL : /category
    • Request Body : X
    • Response
      • 200
        • JSON Array
          [
          	{
          		id = 카테고리 id,
          		name = 카테고리 이름
          	},
              {
          		id = 카테고리 id,
          		name = 카테고리 이름
          	},
          	...
          ]

4. 좋아요 API 설계 (좋아요 테이블을 새로 생성하여 관리)

  • 좋아요 추가 API
    • Method : POST
    • URL : /likes/:id
      • Request params : book_id
    • (new)Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request BODY : X
    • Response
      • 200
  • 좋아요 취소 API
    • Method : DELETE
    • URL : /likes/:id
      • (new)Request params : book_id
    • Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request BODY : X
    • Response
      • 200

5. 장바구니 API 설계

  • 장바구니 담기 API
    • Method : POST
    • URL : /carts
    • Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request Body
      • 어떤 회원의 장바구니인지 확인필요
      • JSON
        {
        	bookId : 도서 id,
        	quantity : 구매 수량
        }
    • Response
      • 201 :

  • 나의 장바구니 조회 / (주문 예상 상품) 선택한 장바구니 상품 목록 조회 API ➡️ 선택한 장바구니 상품 목록 조회 기능을 장바구니 전체 조회 기능에 합쳤다.
    • Method : GET
    • URL : /carts
    • Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request Body
      • JSON
        1. (new)나의 장바구니 조회하는 경우 : Request Body 없음

        2. (new)(주문 예상 상품) 선택한 장바구니 상품 목록 조회 하는 경우

          {
          	selected : [ cartItem_id, cartItem_id, ... ]
          }
        • selected 배열에 값이 존재하면 주문 예상 상품들만을 보여주도록 하고,
          만약 selected 배열 값이 없다면 기존의 역할인 장바구니 목록 전체를 보여주도록 한다.
    • Response (이미지 경로 → 고려해야 함)
      • 201
        • JSON Array
          [
          	{
          		id : 장바구니에 담긴 도서 id,
          		bookId : 도서 id,
          		title : "도서 제목",
          		summary : "도서 요약",
          		quantity : 구매 수량,
          		price : 가격
          	},
          	{
          		id : 장바구니에 담긴 도서 id,
          		bookId : 도서 id,
          		title : "도서 제목",
          		summary : "도서 요약",
          		quantity : 구매 수량,
          		price : 가격
          	},
          	...
          ]

  • 장바구니 도서 개별 삭제 API
    • Method : DELETE
    • URL : /carts/:id
      • (new)Request params : cartItems_id
      • book_id를 받는게 아니라 cartItems 테이블의 id를 받는 것이었다. param값 수정함.
    • (new)Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request Body : X
    • Response
      • 200

  • (장바구니에서 선택한) 주문 “예상” 상품 목록 조회 API
    ⇒ 장바구니 목록 전체 조회 기능에 합쳐졌다.
    • Method : GET
    • URL : /carts
    • (new)Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request Body
      • Array
        [ cartItem_id, cartItem_id, ... ]
    • Response (이미지 경로 → 고려해야 함)
      • 200
        • JSON Array
          [
          	{
          		id : 장바구니에 담긴 도서 id,
          		bookId : 도서 id,
          		title : "도서 제목",
          		summary : "도서 요약",
          		quantity : 구매 수량,
          		price : 가격
          	},
          	{
          		id : 장바구니에 담긴 도서 id,
          		bookId : 도서 id,
          		title : "도서 제목",
          		summary : "도서 요약",
          		quantity : 구매 수량,
          		price : 가격
          	},
          	...
          ]
          • 주문 예상 상품 목록 조회 화면에서 상품의 개수를 조절하는 경우에 실제로 결제를 하지 않고 그냥 화면을 나가더라도 장바구니에 담겨진 상품의 개수에 조절한 값이 반영되도록 기능을 결정하였음.
    • 실제로 주문이 완료된게 아니라 주문 하기 전에 장바구니에 있는 물품 중에서 주문할 것들을 선택할 수 있도록 보여주는 것이기 때문에 주문 API에서 장바구니 API로 이동하였다.

6. 결제(주문) API 설계

  • 결제(주문) 하기 API (= 주문 하기 = 주문 등록 = 주문 DB에 INSERT)
    ⇒ 주문이 완료된 장바구니 상품은 DELETE 해야 한다.
    • Method : POST
    • URL : /orders
    • (new)Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request Body
      • JSON
        {
            items : [ 장바구니 도서 id, 장바구니 도서 id, ...],
            delivery : {
        			  address : "주소",
        			  receiver : "이름",
        			  contact : "010-0000-0000"
        		},
        		totalQuantity : 총 수량,
        		totalPrice : 총 금액,
        		firstBookTitle : 대표 도서 제목
        		// 결제방법은 보류
        }
        • BODY로 들어오는 값들을 살펴보자

          • items : orderedBook 테이블로 INSERT
          • delivery : delivery 테이블로 INSERT
          • totalQuantity, totalPrice : orders 테이블로 INSERT
        • 이때 orderedBook 테이블은 orders 테이블의 id를 참조하고 있다.
          그리고 orders 테이블은 delivery 테이블의 id를 참조하고 있다.

          👍 즉, 1️⃣ delivery → 2️⃣ orders → 3️⃣ orderedBook 순서로 테이블에 INSERT 해야 한다.

        • firstBookTitle : 장바구니 API의 주문 예상 목록 조회 시, 도서의 제목도 같이 보내주고 있는것을 이용하여 주문 결제 시, 맨 첫번째 도서의 제목도 같이 받아오기로 설계 변경

        • 기존의 cartItem_id만 있다면 book_id와 quantity를 확인해 볼 수 있으니 BODY값을 더욱 간단하게 변경하였다.
          또한, 주문 완료한 상품 삭제 기능에서 items Array만 있으면 삭제하기가 쉬워진다는 이점이 생긴다.

    • Response
      • 200

  • 주문 목록(내역) 조회 API → (new)사용자 id 별로 조회 필요
    • Method : GET
    • URL : /orders
    • (new)Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request Body : X
    • Response
      • 200
        • JSON Array

          [
              {
                  id : 주문 id,
                  createAt : "주문 일자",
                  address : "주소",
                  receiver : "이름",
                  contact : "전화번호"
                  bookTitle : "대표 책 제목",
                  totalQuantity : 총 수량	,
                  totalPrice : 총 결제 금액
          
              },{
                  id : 주문 id,
                  createAt : "주문 일자",
                  address : "주소",
                  receiver : "이름",
                  contact : "전화번호"
                  bookTitle : "대표 책 제목",
                  totalQuantity : 총 수량	,
                  totalPrice : 총 결제 금액
              },
              ...
          ]
          • 코드 상에서 orders 테이블과 delivery 테이블의 JOIN을 통해 필요한 데이터를 출력할 때, 기존에 설계했던 response값과는 다르게 “delivery”라는 JSON으로 묶어서 조회할수는 없기 때문에 delivery JSON을 해체하는 방향으로 설계 수정함.
          • 프론트엔드가 제시했던 화면대로 출력하기 위해 totalQuantity와 totalPrice 위치를 변경하였음.
          • 코드에서 사용되는 변수명과 API 설계에서 사용한 변수명 통일화 완료

  • 주문 상세 조회 API → (new)사용자 id 별로 조회 필요
    • Method : GET
    • URL : /orders/:id
      • (new)Request params : order_id
    • (new)Request HEADER
      • “Authorization” : 로그인 시 발급된 JWT token(문자열) ⇒ user_id 사용 가능
    • Request Body : X
    • Response
      • 200
        • JSON Array
          [
              {
                  bookId : 도서 id,
                  bookTitle : "도서 제목",
                  author : "작가명",
                  price : 가격,
                  quanity : 수량
              },{
                  bookId : 도서 id,
                  bookTitle : "도서 제목",
                  author : "작가명",
                  price : 가격,
                  quantity : 수량
              },
              ...
          ]
profile
Develop what? and why?

0개의 댓글