블로그 본문

[RESTful API 설계] 장바구니 관리(cartView.js)를 위한 HTTP Methods(GET, PUT, DELETE) 엔드포인트 설계 및 실시간 데이터 갱신

📌 목차 바로가기

    지난 포스팅에서는 RDBMS 복합 조인(JOIN) 연산과 산술 평균 평점(AVG) 집계, 별점 HTML 변환 시각화, 그리고 작성자 개인정보 보호 마스킹 기법을 가동하여 상품 상세페이지(prodDetail.js) 라우터를 조립했습니다.

    상세페이지에서 사용자가 원하는 의류의 사이즈와 수량을 선택해 [장바구니 담기]를 완료하면, 해당 상품 데이터는 주문 대기 상태(ord_yn = 'N')로 Carts 테이블에 안전하게 보관됩니다. 오늘 포스팅에서는 수납된 장바구니 자원을 효율적으로 조회, 수정, 삭제하기 위한 RESTful API 설계 사상과 cartView.js 라우터 구현, 그리고 비동기 Fetch 통신 기반의 실시간 결제 예정 금액 합산 연산 기술을 설명해 드리겠습니다.

    1. 자원 중심의 백엔드 설계: RESTful API 및 HTTP Methods 매핑 사상

    전자상거래 웹 애플리케이션에서 장바구니 자원은 사용자의 구매 의사가 담긴 핵심 데이터 엔티티입니다. 행위(Action) 중심의 투박한 URL 설계(예: /cart_update.php, /cart_delete.php)는 시스템이 확장될수록 엔드포인트 파편화를 초래합니다.

    이를 타파하기 위해 명사 형태의 자원 경로(Resource Path)와 행위를 상징하는 HTTP 메서드(HTTP Methods)를 명확히 분리 매핑하는 RESTful API 규격을 채택합니다.

    • GET /cart (장바구니 목록 조회): 로그인된 현재 세션 사용자의 주문 대기 중인 장바구니 목록 및 상품 조인 정보를 수득합니다. 멱등성(Idempotency)과 안전성(Safety)을 지닌 읽기 전용 요청입니다.
    • PUT /cart/:id (수량 동적 변경): 특정 장바구니 일련번호(cart_seq_no)에 해당하는 항목의 수량(ord_qty)을 지정된 값으로 갱신합니다. 동일한 요청을 여러 번 보내도 결과 상태가 동일하게 유지되는 멱등적(Idempotent) 수정 연산입니다.
    • DELETE /cart/:id (개별 항목 삭제): 특정 장바구니 항목을 테이블에서 완전히 제거하거나 소프트 삭제 처리합니다. 역시 멱등성을 보장하는 삭제 연산입니다.

    2. cartView.js 라우터 구현 및 보안 소유권 검증 (Ownership Validation)

    cartView.js 라우터는 Carts 테이블과 Products 테이블을 prod_cd 기반으로 INNER JOIN 결합하여 화면에 필요한 마스터 정보를 수송합니다.

    ① 장바구니 조회 쿼리 (GET /cart)

    SELECT
      C.cart_seq_no, C.cust_id, C.prod_cd, C.prod_size, C.ord_qty, C.ord_yn,
      P.prod_name, P.price, P.prod_img
    FROM Carts C
    INNER JOIN Products P ON C.prod_cd = P.prod_cd
    WHERE C.cust_id = ? AND C.ord_yn = 'N'
    ORDER BY C.cart_seq_no DESC
    

    이 쿼리를 통해 결제가 완료된 과거 항목(ord_yn = 'Y')은 배제하고, 오직 현재 대기 중인 장바구니 물품만을 선별하여 상품명, 단가, S3 이미지 경로와 함께 내려보냅니다.

    ② 엄격한 소유권 검증 (Ownership Validation)

    장바구니 수정(PUT) 및 삭제(DELETE) 라우트 설계 시 가장 치명적인 보안 결함은 URL의 일련번호(cart_seq_no)만 바꾸어 타인의 장바구니 수량을 조작하거나 삭제하는 인가 우회(Bypass Authorization) 공격입니다.

    이를 방어하기 위해 모든 DML 쿼리문의 WHERE 절에 반드시 현재 로그인된 세션의 사용자 아이디(req.session.userid 또는 nickname에서 추출한 식별자)를 이중 검증 바인딩합니다:

    -- 타인의 장바구니 수정을 원천 차단하는 안전한 UPDATE 쿼리
    UPDATE Carts
    SET ord_qty = ?
    WHERE cart_seq_no = ? AND cust_id = ?
    

    이 조건절 덕분에 악의적인 사용자가 타인의 cart_seq_no를 대입하여 요청을 전송하더라도 cust_id 불일치로 인해 0 row(s) affected가 반환되어 타인의 자원이 완벽히 보호됩니다.

    3. 클라이언트 사이드 비동기 연동 및 실시간 결제 예정 금액 합산

    장바구니 화면에서는 사용자가 수량 수치를 1개에서 2개로 올리거나 [삭제] 버튼을 누를 때마다 화면 전체가 껌벅이며 새로고침되는 전통적인 UX는 심각한 사용자 이탈을 유발합니다.

    클라이언트 자바스크립트는 Fetch API를 가동하여 백그라운드에서 백엔드 RESTful 엔드포인트와 통신하고, DOM의 수치 및 전체 합산 금액을 실시간 동적 계산합니다.

    // 프론트엔드 실시간 합산 및 비동기 수량 변경 연동 스크립트 예시
    async function updateCartQuantity(cartSeqNo, newQty) {
      try {
        const response = await fetch(`/cart/${cartSeqNo}`, {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ ord_qty: newQty })
        });
    
        const result = await response.json();
        if (result.success) {
          // 화면 전체 새로고침 없이 실시간 합산 금액 재계산 함수 가동
          calculateTotalCartAmount();
        }
      } catch (err) {
        console.error('장바구니 수량 변경 실패:', err);
      }
    }
    
    // 실시간 총 결제 예정 금액 계산 헬퍼 함수
    function calculateTotalCartAmount() {
      let grandTotal = 0;
      const items = document.querySelectorAll('.cart-item-row');
    
      items.forEach(row => {
        const price = Number(row.dataset.price);
        const qty = Number(row.querySelector('.qty-input').value);
        const itemTotal = price * qty;
    
        // 개별 항목 합산 금액 DOM 업데이트
        row.querySelector('.item-total-price').textContent = `${itemTotal.toLocaleString()}원`;
        grandTotal += itemTotal;
      });
    
      // 최종 결제 예정 총액 DOM 업데이트
      document.getElementById('grand-total-price').textContent = `${grandTotal.toLocaleString()}원`;
    }
    

    4. 장바구니 RESTful API 수송 아키텍처 다이어그램

    클라이언트 브라우저가 장바구니 목록 조회(GET), 수량 동적 업데이트(PUT), 항목 삭제(DELETE) 요청을 RESTful 규격으로 전송하고, cartView.js 라우터가 세션 소유권을 검증하여 RDS MySQL Carts-Products 조인 테이블을 제어하는 전체 수송 구조도입니다.

    클라이언트 브라우저의 비동기 Fetch 요청(GET/PUT/DELETE)을 접수한 cartView.js 라우터가 세션 소유권(cust_id)을 검증하여 RDS MySQL Carts-Products 조인 레코드를 제어하고, 실시간 합산 금액을 DOM에 반영하는 RESTful API 수송 아키텍처 다이어그램

    마치며: 자원 중심의 인터랙션을 완성했습니다!

    오늘 우리는 백엔드 RESTful API 설계 표준에 입각하여 GET, PUT, DELETE HTTP 메서드별 엔드포인트를 수립하고, 세션 소유권 검증(cust_id)을 통한 인가 보안과 클라이언트 비동기 Fetch 통신 기반의 실시간 결제 예정 금액 합산 기능을 갖춘 완벽한 장바구니 라우터(cartView.js)를 구축했습니다!

    "명사 형태의 자원 경로와 HTTP 메서드를 정교하게 매핑하여 RESTful 규격을 수호하고, 소유권 바인딩으로 타인 장바구니 무단 조작을 차단하면서, 화면 깜빡임 없는 실시간 합산 UX를 선사하는 현대적 이커머스 장바구니 시스템을 완성한 것입니다."

    다음 포스팅 [복합 트랜잭션] Orders/Ord_items 다중 삽입 및 Carts 소프트 삭제를 결합한 결제 처리(POST /pay)와 수동 롤백(Rollback) 설계 편에서는 Orders 및 Ord_items 다중 데이터 이관, 장바구니 소프트 삭제(ord_yn = 'Y'), 그리고 connection.beginTransaction() 기반의 ACID 트랜잭션 안전장치 구현법을 소개해 드리겠습니다.

    오늘 장바구니 PUT/DELETE RESTful 엔드포인트 테스트 중 403 권한 에러가 발생했거나, 실시간 합산 금액 계산 스크립트에 대한 궁금증이 있으시다면 주저하지 마시고 운영자 메일로 질문해 주세요. 오늘도 안전하고 똑똑한 클라우딩 라이프 하세요. 감사합니다! 😉

    출처

    • 이현호. 실무 프로젝트로 완성하는 클라우드 환경에서 DB 구축과 웹 개발. 길벗캠퍼스. 2026.04. (9.1장 '장바구니 관리 및 결제 모듈', 228-238페이지 참조)
    • 이현호. "09장. 애플리케이션 개발 - 장바구니_마이페이지_설명오디오.m4a" 설명 오디오 가이드 스크립트 기반 RESTful API 엔드포인트 설계 사상, PUT/DELETE HTTP 메서드 매핑, 세션 cust_id 소유권 검증 및 비동기 Fetch 통신 기반 실시간 합산 연산 기술 비하인드 대화록 완벽 반영.
    • RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - Method Definitions (https://datatracker.ietf.org/doc/html/rfc7231#section-4.3) 및 Express Routing Guide.

    자주 묻는 질문 (FAQ)

    Q. 장바구니 수량 변경 및 개별 삭제 구현 시 전통적인 POST 방식 대신 PUT 및 DELETE HTTP 메서드를 사용하는 RESTful API 설계의 이점은 무엇인가요? 

    A. 자원 경로와 행위의 명확한 분리 및 멱등성 수호입니다. 명사 형태의 단일 자원 URL(/cart/:id)에 HTTP 메서드(PUT/DELETE)를 매핑함으로써 API의 직관성과 가독성을 높이고, 동일 요청 반복 시 시스템 상태가 유일하게 보장되는 멱등적 자원 제어를 실현합니다.

    Q. 장바구니 수량 수정(PUT) 및 삭제(DELETE) 라우트 구현 시 SQL 쿼리의 WHERE 절에 cust_id 조건절을 반드시 추가해야 하는 보안적 이유는 무엇인가요? 

    A. 타인의 장바구니 무단 조작을 차단하는 세션 소유권 인가 검증입니다. URL 파라미터의 일련번호(cart_seq_no)만으로 대상을 지정할 경우 타인의 일련번호 대입 공격에 취약해지므로, 반드시 세션에서 추출한 로그인 유저의 cust_id를 이중 검증 바인딩해야 합니다.

    Q. 장바구니 화면에서 수량 조절 시 페이지 전체 새로고침 없이 실시간 결제 예정 총액을 화면에 반영하는 기술적 원리는 무엇인가요? 

    A. 비동기 Fetch API 연동과 DOM 실시간 동적 계산입니다. 수량 변경 시 백그라운드로 PUT 요청을 보낸 후 성공 응답 수신 즉시, 클라이언트 자바스크립트가 각 항목 행의 단가와 변경 수량을 곱해 소계 및 전체 총액을 재계산하고 DOM 텍스트를 실시간 업데이트합니다.