Programmers

[24일차]API 설계 보고서

PARKpatchnotes 2025. 10. 14. 15:02

1. 개요

본 문서는 '북스토어' 프로젝트의 백엔드 API 명세를 정의합니다. Express.js 기반의 백엔드 서버와 Next.js 기반의 프론트엔드 클라이언트 간의 데이터 통신을 위한 모든 엔드포인트(Endpoint)를 기술하여 원활한 협업을 지원하는 것을 목표로 합니다.

  • Base URL: http://localhost:3001
  • 인증 방식: JWT (JSON Web Token)를 사용합니다.
    • Access Token: API 접근 시 HTTP 헤더의 Authorization 필드에 Bearer <token> 형식으로 포함해야 합니다. (유효기간: 1시간)
    • Refresh Token: Access Token 재발급에 사용되며, httpOnly 쿠키를 통해 안전하게 관리됩니다. (유효기간: 7일)

2. 공통 응답 형식 및 상태 코드

2.1. 응답 형식

모든 API 응답은 아래와 같은 일관된 JSON 형식을 따릅니다.

  • 성공 시:
    { "status": "success", "data": { ... } }
  • 실패 시:
    { "status": "error", "message": "오류에 대한 구체적인 설명" }

2.2. HTTP 상태 코드

코드 설명
200 OK 요청이 성공적으로 처리됨.
201 Created 리소스가 성공적으로 생성됨.
204 No Content 요청은 성공했지만, 응답으로 보낼 데이터가 없음.
400 Bad Request 클라이언트의 요청이 잘못됨 (유효성 검사 실패 등).
401 Unauthorized 인증되지 않은 사용자의 요청임 (토큰 부재 또는 만료).
403 Forbidden 인증은 되었으나 해당 리소스에 접근할 권한이 없음.
404 Not Found 요청한 리소스를 찾을 수 없음.
500 Internal Server Error 서버 내부에서 예상치 못한 오류가 발생함.

3. API 명세

3.1. 사용자 및 인증 (Users & Auth)

3.1.1. 회원가입

  • Description: 새로운 사용자를 시스템에 등록합니다.
  • Method: POST
  • URI: /api/users/join
  • Request Body:
    {
      "email": "newuser@example.com",
      "password": "securePassword123!",
      "name": "김철수",
      "address": "서울시 마포구 월드컵북로 21",
      "phone_number": "010-9876-5432"
    }
  • Response 201 Created:
    {
      "status": "success",
      "data": { "message": "회원가입이 성공적으로 완료되었습니다." }
    }

3.1.2. 로그인

  • Description: 사용자를 인증하고 Access Token과 Refresh Token을 발급합니다.
  • Method: POST
  • URI: /api/users/login
  • 백엔드 SQL 쿼리 예시:
    -- 1. 사용자 확인
    SELECT id, email, password FROM users WHERE email = ? AND deleted_at IS NULL;
    -- 2. 리프레시 토큰 저장 (refresh_tokens 테이블 필요)
    INSERT INTO refresh_tokens (user_id, token, expires_at) VALUES (?, ?, ?)
    ON DUPLICATE KEY UPDATE token = VALUES(token), expires_at = VALUES(expires_at);
  • Request Body:
    { "email": "user@example.com", "password": "password123" }
  • Response 200 OK:
    • Body:
      {
        "status": "success",
        "data": { "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }
      }
    • Set-Cookie Header: refreshToken=...; HttpOnly; Secure; SameSite=Strict; Max-Age=604800

3.1.3. 로그아웃

  • Description: 사용자의 Refresh Token을 무효화하고 로그아웃 처리합니다.
  • Method: POST
  • URI: /api/users/logout
  • 백엔드 SQL 쿼리 예시:
    DELETE FROM refresh_tokens WHERE token = ?;
  • Response 200 OK:
    • Body:
      { "status": "success", "data": { "message": "성공적으로 로그아웃되었습니다." } }
    • Set-Cookie Header: refreshToken=; Max-Age=0; ... (쿠키 삭제)

3.1.4. 토큰 재발급

  • Description: 유효한 Refresh Token을 사용하여 새로운 Access Token을 발급받습니다.
  • Method: POST
  • URI: /api/users/refresh
  • Response 200 OK:
    {
      "status": "success",
      "data": { "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.new..." }
    }

3.1.5. 내 정보 조회

  • Description: 현재 로그인된 사용자의 상세 정보를 조회합니다. (인증 필요)
  • Method: GET
  • URI: /api/users/me
  • 백엔드 SQL 쿼리 예시:
    SELECT id, email, name, address, phone_number FROM users WHERE id = ? AND deleted_at IS NULL;
  • Response 200 OK:
    {
      "status": "success",
      "data": {
        "id": 1,
        "email": "user@example.com",
        "name": "김철수",
        "address": "서울시 마포구 월드컵북로 21",
        "phone_number": "010-9876-5432"
      }
    }

3.1.6. 내 정보 수정

  • Description: 현재 로그인된 사용자의 정보를 수정합니다. (인증 필요)
  • Method: PUT
  • URI: /api/users/me
  • 백엔드 SQL 쿼리 예시:
    UPDATE users SET name = ?, address = ? WHERE id = ? AND deleted_at IS NULL;
  • Request Body:
    {
      "name": "김영희",
      "address": "서울시 강남구 테헤란로 123"
    }
  • Response 200 OK:
    {
      "status": "success",
      "data": { "message": "사용자 정보가 성공적으로 수정되었습니다." }
    }

3.1.7. 회원 탈퇴 (소프트 삭제)

  • Description: 현재 로그인된 사용자의 계정을 비활성화합니다. (인증 필요)
  • Method: DELETE
  • URI: /api/users/me
  • 백엔드 SQL 쿼리 예시:
    UPDATE users SET deleted_at = CURRENT_TIMESTAMP WHERE id = ? AND deleted_at IS NULL;
  • Response 200 OK:
    {
      "status": "success",
      "data": { "message": "회원 탈퇴가 성공적으로 처리되었습니다." }
    }
  • Note: 비밀번호 재설정 기능은 현재 DB 스키마에 reset_token 관련 컬럼이 없어 명세에서 제외되었습니다. 구현을 위해서는 users 테이블에 reset_token(VARCHAR), reset_token_expires(TIMESTAMP) 컬럼 추가가 필요합니다.*

3.2. 도서 (Books) & 카테고리 (Categories)

3.2.1. 카테고리 목록 조회

  • Description: 모든 도서 카테고리 목록을 조회합니다.
  • Method: GET
  • URI: /api/categories
  • Response 200 OK:
    {
      "status": "success",
      "data": [
        { "id": 1, "name": "프로그래밍" },
        { "id": 2, "name": "소설" }
      ]
    }

3.2.2. 도서 목록 조회

  • Description: 조건에 맞는 도서 목록을 페이지네이션과 함께 조회합니다.
  • Method: GET
  • URI: /api/books?category_id=1&new=true&page=1&limit=10
  • Query Params: category_id(int), new(boolean, 신간 여부), page(int), limit(int)
  • 백엔드 SQL 쿼리 예시:
    SELECT id, title, author, image_url, price, summary FROM books WHERE category_id = ? AND deleted_at IS NULL ORDER BY created_at DESC LIMIT ? OFFSET ?;
  • Response 200 OK:
    {
      "status": "success",
      "data": {
        "books": [ { "id": 1, "title": "모던 자바스크립트 Deep Dive", ... } ],
        "pagination": { "currentPage": 1, "totalPages": 25 }
      }
    }

3.2.3. 도서 상세 조회

  • Description: 특정 도서의 상세 정보와 현재 사용자의 '좋아요' 여부를 함께 조회합니다.
  • Method: GET
  • URI: /api/books/{bookId}
  • 백엔드 SQL 쿼리 예시:
    SELECT b.*, c.name AS category_name, EXISTS(SELECT 1 FROM book_likes bl WHERE bl.book_id = b.id AND bl.user_id = ?) AS isLiked
    FROM books b
    JOIN categories c ON b.category_id = c.id
    WHERE b.id = ? AND b.deleted_at IS NULL;
  • Response 200 OK:
    {
      "status": "success",
      "data": { "id": 1, "title": "...", "author": "...", "price": 45000, "isLiked": true, ... }
    }

3.2.4. 도서 '좋아요' 추가/취소

  • Description: 특정 도서에 대한 '좋아요' 상태를 토글합니다. (인증 필요)
  • Method: POST
  • URI: /api/books/{bookId}/like
  • 백엔드 SQL 쿼리 예시:
    • 좋아요 추가 시: INSERT IGNORE INTO book_likes (user_id, book_id) VALUES (?, ?);
    • 좋아요 취소 시: DELETE FROM book_likes WHERE user_id = ? AND book_id = ?;
  • Response 200 OK:
    { "status": "success", "data": { "isLiked": true } }

3.3. 장바구니 (Carts)

3.3.1. 장바구니에 상품 추가

  • Description: 장바구니에 상품을 추가합니다. 이미 있는 상품이면 수량을 더합니다. (인증 필요)
  • Method: POST
  • URI: /api/carts
  • 백엔드 SQL 쿼리 예시 (UPSERT):
    INSERT INTO carts (user_id, book_id, quantity) VALUES (?, ?, ?)
    ON DUPLICATE KEY UPDATE quantity = quantity + VALUES(quantity);
  • Request Body:
    { "book_id": 1, "quantity": 2 }
  • Response 201 Created:
    { "status": "success", "data": { "message": "장바구니에 상품을 담았습니다." } }

3.3.2. 내 장바구니 조회

  • Description: 현재 사용자의 장바구니 목록 전체를 조회합니다. (인증 필요)
  • Method: GET
  • URI: /api/carts
  • Response 200 OK:
    {
      "status": "success",
      "data": [ { "cart_id": 101, "book_id": 1, "title": "...", "price": 45000, "quantity": 2 } ]
    }

3.3.3. 장바구니 상품 수량 변경

  • Description: 장바구니에 있는 특정 상품의 수량을 변경합니다. (인증 필요)
  • Method: PUT
  • URI: /api/carts/{cartItemId}
  • Request Body:
    { "quantity": 3 }
  • Response 200 OK:
    { "status": "success", "data": { "message": "상품 수량이 변경되었습니다." } }

3.3.4. 장바구니 상품 삭제

  • Description: 장바구니에 있는 특정 상품을 삭제합니다. (인증 필요)
  • Method: DELETE
  • URI: /api/carts/{cartItemId}
  • Response 204 No Content

3.4. 주문 (Orders)

3.4.1. 주문하기

  • Description: 장바구니에서 선택한 상품들로 새로운 주문을 생성합니다. (트랜잭션 처리 필요)
  • Method: POST
  • URI: /api/orders
  • Request Body:
    {
      "delivery_info": { "address": "서울시 마포구", "receiver": "김철수", "contact": "010-1234-5678" },
      "cart_item_ids": [101, 102]
    }
  • Response 201 Created:
    { "status": "success", "data": { "order_id": 20251016001, "message": "주문이 성공적으로 완료되었습니다." } }

3.4.2. 내 주문 목록 조회

  • Description: 현재 사용자의 주문 내역 목록을 조회합니다. (인증 필요)
  • Method: GET
  • URI: /api/orders
  • Response 200 OK:
    {
      "status": "success",
      "data": [
        { "order_id": 20251016001, "total_price": 75000, "status": "배송준비중", ... }
      ]
    }

3.4.3. 내 주문 상세 조회

  • Description: 특정 주문의 상세 정보를 조회합니다. (인증 필요)
  • Method: GET
  • URI: /api/orders/{orderId}
  • Response 200 OK:
    {
      "status": "success",
      "data": { "order_id": 20251016001, "delivery_info": {...}, "books": [ ... ], ... }
    }

3.5. 리뷰 (Reviews)

3.5.1. 리뷰 작성

  • Description: 특정 도서에 대해 리뷰와 평점을 남깁니다. (인증 및 도서 구매 이력 확인 필요)
  • Method: POST
  • URI: /api/books/{bookId}/reviews
  • Request Body:
    { "content": "정말 좋은 책입니다.", "rating": 5 }
  • Response 201 Created:
    { "status": "success", "data": { "review_id": 55, "message": "리뷰가 성공적으로 등록되었습니다." } }

3.5.2. 도서별 리뷰 목록 조회

  • Description: 특정 도서에 대한 모든 리뷰를 조회합니다.
  • Method: GET
  • URI: /api/books/{bookId}/reviews
  • Response 200 OK:
    {
      "status": "success",
      "data": [ { "id": 55, "userName": "김*", "content": "...", "rating": 5, ... } ]
    }

3.5.3. 리뷰 수정/삭제

  • Description: 본인이 작성한 리뷰를 수정하거나 삭제합니다. (인증 필요)
  • Method: PUT, DELETE
  • URI: /api/reviews/{reviewId}
  • Response 200 OK or 204 No Content