Home 캡스톤일지 | ~ 11.04(1) 웹 쿠키 장바구니 기능 구현
Post
Cancel

캡스톤일지 | ~ 11.04(1) 웹 쿠키 장바구니 기능 구현

밀린 캡스톤 일지.. 이제서야 쓰다..
이것만 해결하고 써야지 하다가 해결 못해서 며칠 고생하고 드디어 쓴다. 하지만 아직도 해야할게 산더미라는거 ~..~
이제 다시 이프 출근해야되서 짱 바쁠예정


장바구니 기능 구현

선택한 메뉴 정보를 임시로 담고있는 장바구니 정보(메뉴 추가, 수정, 삭제 가능해야함)를 어떻게 유지해야하나 고민했다.
DB에 저장할 데이터도 아니고.. 그냥 인메모리로 들고있자니 페이지 이동되었다가 리로드됐을 때 정보 유지도 안되고..
그렇게 고민하던 중 생각난 방법이 바로 쿠키에 저장하는거!!

자바스크립트에서 쿠키를 이용하는 방법으로는

  1. cookie.js https://github.com/js-cookie/js-cookie)
  2. jQuery cookie (https://github.com/carhartl/jquery-cookie)
  3. document.cookie (https://ko.javascript.info/cookie)

이것저것 해보다가 난 3번 방법(document.cookie)을 선택했다.
어디 구글링하다 봤는데 쿠키로 하니 세션으로 하니, DB에 테이블로 쌓아야 한다느니 말이 많았지만.. 난 그냥 쿠키로.. ^^

내가 작성한 cookie.js

[참고] 자바스크립트 쿠키(Cookie) 저장 및 삭제 예제보기 https://webisfree.com/2015-02-04/[%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8]-%EC%BF%A0%ED%82%A4(cookie)-%EC%A0%80%EC%9E%A5-%EB%B0%8F-%EC%82%AD%EC%A0%9C-%EC%98%88%EC%A0%9C%EB%B3%B4%EA%B8%B0

위의 블로그를 참고하여 쿠키를 생성, 조회, 삭제하는 메서드를 작성하였다.

cookie.js

1
2
3
4
5
6
7
function setCookie (cookie_name, value, minutes) {
    const exdate = new Date();
    exdate.setMinutes(exdate.getMinutes() + minutes);
    // const cookie_value = escape(value) + ((minutes == null) ? '' : '; expires=' + exdate.toUTCString());
    const cookie_value = value + ((minutes == null) ? '' : '; expires=' + exdate.toUTCString()); // 암호화 끔
    document.cookie = cookie_name + '=' + cookie_value;
}

쿠키값 저장 시 저장 기간 단위는 분으로 받음(3분으로 할까 생각중), 인코딩(escape) 과정 생략

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function getCookie(cookie_name) {
    var x, y;
    var val = document.cookie.split(';');
  
    for (var i = 0; i < val.length; i++) {
      x = val[i].substr(0, val[i].indexOf('='));
      y = val[i].substr(val[i].indexOf('=') + 1);
      x = x.replace(/^\s+|\s+$/g, ''); // 앞과 뒤의 공백 제거하기
      if (x == cookie_name) {
        // return unescape(y); // unescape로 디코딩 후 값 리턴
        return y; // 암호화 끔
      }
    }
  }

위에서 인코딩 과정을 생략했기 때문에 디코딩(unescape) 과정도 생략

1
2
3
function deleteCookie(name) {
    document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}

장바구니 기능과 화면 구현

내가 저장할 쿠키의 모양은 dict 형태로 OrderDetails 테이블에 저장할 정보들이다.

1
2
3
4
5
6
7
8
9
shoppingCart = {
    menuNo: {
        "menuNo" : {메뉴번호},
        "menuName" : {메뉴이름},
        "count" : {수량},
        "menuPrice" : {가격},
        "totalPrice" : {수량*가격}
    },
}

장바구니 변수 선언

1
let shoppingCartList = getCookie("shoppingCart") ? JSON.parse((getCookie("shoppingCart"))) : {};

장바구니 쿠키가 존재하면 쿠키를 json형태로 바꿔 변수(인메모리)에 저장, 없으면 {}로 초기화

사용자가 장바구니에 담긴 내역을 추가, 수정, 삭제하는 방법에는 여러가지가 있는데 아래와 같다.

  • 메뉴 선택 후 메뉴div를 클릭하는 경우
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
      function addMenuList(result) {
          $('#menuList').empty();
          $.each(result, function(index, data){
              $('#menuList').append($('<div />', {
                  class: 'menu',
                  id: data.menuNo,
                  click: function () {
                      addShoppingCart(data.menuNo, data.menuName, data.menuPrice);
                  }
              }).
    

    ajax로 카테고리별 메뉴들을 불러와 메뉴 div를 append할때 click 이벤트로 구현

  • 장바구니 목록에서 개수 증가, 감소 버튼을 누르거나 취소버튼을 누르는 경우
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    
      for (key in shoppingCartList) {
          $('#orderList').append($('<div />', {
              class: 'orderMenu',
              id: key // 여기서 shoppingCartList의 key는 menuNo
          }).append($('<div />', {
              class: 'orderMenuName',
              text: shoppingCartList[key]["menuName"]
          })).append($('<div />', {
              class: 'orderMenuPrice',
              text: shoppingCartList[key]["totalPrice"],
              id: 'price' + key
          })).append($('<div />', {
              class: 'orderQuantity',
          }).append($('<div />', {
              text: '',
              class: 'orderMenuQuantityDec',
              click: function() {
                      // 개수 증가                 
              }
          })).append($('<div />', {
              text: shoppingCartList[key]["count"],
              class: 'orderMenuQuantity',
              id: "cntNum" + key
          })).append($('<div />', {
              text: '',
              class: 'orderMenuQuantityInc',
              id: 'orderMenuIc',
              click: function() {
                      // 개수 감소
              }
          }))).append($('<div />', {
              class: 'orderMenuCancel', 
              text: 'CANCEL',
              click: function() {
                      // 해당 메뉴 삭제
              }
          })));
      }
    

    장바구니 영역에 목록을 동적으로 추가하면서 마찬가지로 클릭 이벤트로 해결하였다…

  1. 메뉴 클릭 addShoppingCart()
    1. 장바구니에 이미 담겨있는 메뉴를 추가했을 때
      1
      2
      3
      4
      5
      
       if(menuNo in shoppingCartList) { // 장바구니에 담긴 메뉴일 때
       shoppingCartList[menuNo]["count"]++; // 1개씩 추가
       shoppingCartList[menuNo]["totalPrice"] += shoppingCartList[menuNo]["menuPrice"];
       setCookie("shoppingCart", JSON.stringify(shoppingCartList), 3); // 쿠키에 변경 사항 새로 저장
       }
      

      해당 메뉴의 count와 totalPrice를 증가시켜준 뒤 다시 쿠키값으로 저장
      처음에는 쿠키를 delete하고 set해줬는데 지우지 않고 그냥 set만 해줘도 덮어씌워지는 듯 함!

    2. 메뉴 클릭 > 장바구니에 없는 새로운 메뉴를 추가하였을 때
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
       else { // 장바구니에 담겨있지 않던 메뉴일 때
       shoppingCartList[menuNo] = {
           menuNo: menuNo,
           menuName: menuName,
           count: 1,
           menuPrice: menuPrice,
           totalPrice: menuPrice
       }
       setCookie("shoppingCart", JSON.stringify(shoppingCartList), 3);
       }
      

      사전 형태로 장바구니에 저장할 정보를 만들고 이를 쿠키에 저장

      주의할 점은 인메모리 장바구니 정보는 json형식이지만 쿠키값은 string으로 저장됨으로 JSON.stringfy 해줘야함
      stringify 안하고 바로 저장했을 때 image

  2. 장바구니 영역에서의 조정
    image
    1. 수량 증가
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
       //수량, 가격 증가
       shoppingCartDict[menuNo]["count"] += 1;
       shoppingCartDict[menuNo]["totalPrice"] += shoppingCartDict[menuNo]["menuPrice"];
      
       // 증가된 수량과 가격으로 바꿔줌
       $('#cntNum' + $(this).parent().parent().attr('id')).text(shoppingCartList[$(this).parent().parent().attr('id')]["count"]);
       $('#price' + $(this).parent().parent().attr('id')).text(shoppingCartList[$(this).parent().parent().attr('id')]["totalPrice"]);
      
       // 쿠키 다시 저장
       setCookie("shoppingCart", JSON.stringify(shoppingCartList), 3);
      
    2. 수량 감소
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
       // 감소된 수량이 0 이하일 때
       if (orderMenuDec($(this).parent().parent().attr('id'), shoppingCartList == false)) {
           if (delete shoppingCartList[$(this).parent().parent().attr('id')]) {
               // 쿠키값과 이어지는 메모리변수에서 해당 메뉴 삭제
               $(this).parent().parent().remove(); // 화면에서 삭제
               setCookie("shoppingCart", JSON.stringify(shoppingCartList), 3);
           }
       } else {
           // 보여지는 화면에서 수량과 가격 수정
           $('#cntNum' + $(this).parent().parent().attr('id')).text(shoppingCartList[$(this).parent().parent().attr('id')]["count"]);
           $('#price' + $(this).parent().parent().attr('id')).text(shoppingCartList[$(this).parent().parent().attr('id')]["totalPrice"]);
           // 쿠키 새로 저장
           setCookie("shoppingCart", JSON.stringify(shoppingCartList), 3);    
       }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
       const orderMenuDec = (menuNo, shoppingCartDict) => {
           if (shoppingCartDict[menuNo]["count"] == 1) {
               return false;
           } else {
               shoppingCartDict[menuNo]["count"] -= 1;
               shoppingCartDict[menuNo]["totalPrice"] -= shoppingCartDict[menuNo]["menuPrice"];
               return true;
           }
       }
      

      메뉴의 수량이 현재 1개여서 감소하면 0개로 아예 삭제되어야할 경우를 구별하기 위해 추가해준 내용

      javascript에서 dict 사용하기

      1
      
       delete dictionary[key]
      

      원하는 키값의 요소 삭제 후 삭제되면 true 반환

    3. 취소
      1
      2
      3
      4
      
       if (delete shoppingCartList[$(this).parent().attr('id')]) {
           $(this).parent().remove(); // 해당 메뉴 삭제 후 
           setCookie("shoppingCart", JSON.stringify(shoppingCartList), 3); // 다시 쿠키에 저장
       }
      


계속 menuNo 으로 나타나는 아래 값은

1
2
$(this).parent().parent().attr('id') // 증감버튼의 경우 div 한단계 더 아래임
$(this).parent().attr('id') // 취소 버튼

처음 메뉴 div append할때 각 메뉴 영역의 가장 상단에 아이디로 menuNo값을 설정하였기 때문이다! image

계속 사용자가 수정함에 따라 바뀌어야하는 메뉴별 가격(orderMenuPrice)와 메뉴 수량(orderMenuQuantity)도 각 메뉴마다 아이디로 식별하기 위해 뒤에 menoNo을 달아서 구별해주었다.



동적으로 장바구니 영역에 할당하고 그 동적으로 할당된 곳에서 또 수정이 들어가려니까 복잡하고 꼬여서 조금 해맸다..(사실 며칠..)
근데 나중에 알고보니 내가 아이디를 잘못 매겨서 안되는거였삼 어이업서
코드가 중복되는 부분도 너무 많고 조금 난잡해서 얼른 나머지 기능들 끝내고 크게 수정좀 해야할 것 같다.
근데.. jQuery 이런식으로 쓰는게 맞는건지.. 뭐 됐으면 된거지..~

This post is licensed under CC BY 4.0 by the author.

캡스톤일지 | ~ 10.26 미디어파이프 오류 해결과 socket.io 예제

캡스톤일지 | ~ 11.04(2) NCP 문자 메시지 발송 API