쇼핑몰 장바구니 기능을 구현하며,
각각 카테고리 별 제품을 화면에 띄워주며 자바스크립트를 이용해 배열에 담았다.
이 배열을 Json타입으로 바꿔서 ajax를 이용해 보내는 방법을 정리해보려 한다. ☺️
1. 자바스크립트 배열에 담기
먼저 상품명, 수량, 가격 / 조립여부, 조립가격, 수량/ 견적 이름 을 자바스크립트 배열에 담아야했다.
담기버튼을 클릭하면 addToCart()를 통해 productName과 productPrice를 가져오도록 한다.
그리고 active된 component의 이름을 배열 Name으로 지정한 후,
currentCart[componentName] = {
name: productName,
price: parseInt(productPrice),
quantity: 1, // 기본 수량 :1
};
형식으로 배열에 담아지도록 코드를 짰다.
//견적 담을 장바구니 배열
let currentCart = {};
//조립 신청 서비스 신청 여부
radioButtons.forEach(radio => {
radio.addEventListener('change', () => {
if (radio.value === 'requested' && radio.checked) {
// 조립 신청이 선택되었을 때
if (!isAssemblyRequested) {
isAssemblyRequested = true;
currentCart['assembly'] = { name: '조립 서비스', price: assemblyPrice, quantity: 1 };
}
} else if (radio.value === 'not_requested' && radio.checked) {
// 조립 미신청이 선택되었을 때
if (isAssemblyRequested) {
isAssemblyRequested = false;
delete currentCart['assembly'];
}
}
updateTotalPrice(); // 총 가격 즉시 업데이트
});
});
// 담기 버튼 클릭 시 장바구니에 상품 이름 및 수량 담는 함수
function addToCart(productName, productPrice) {
const activeComponent = document.querySelector('.component.active');
if (activeComponent) {
const productDetail = activeComponent.querySelector('#product-detail');
const productPriceDiv = activeComponent.querySelector('#product-price');
const quantityControls = createQuantityControls(productPrice);
if (productDetail) {
productDetail.innerHTML = `<p>${productName}</p>`; // 제품 이름 출력
}
if (productPriceDiv) {
productPriceDiv.innerHTML = ''; // 기존 가격 제거
productPriceDiv.appendChild(quantityControls); // 수량 조절 추가
}
// 장바구니에 추가
const componentName = activeComponent.dataset.component;
currentCart[componentName] = {
name: productName,
price: parseInt(productPrice),
quantity: 1, // 기본 수량 :1
};
updateTotalPrice(); // 총합 업데이트
}
}
견적 이름과 조립신청여부는 이렇게 배열에 저장했다.
// 견적 이름 및 조립 신청 여부를 currentCart에 추가
currentCart['quoteName'] = quoteName;
currentCart['assemblyStatus'] = isAssemblyRequested ? '조립 신청' : '조립 미신청';
여기까지 실행하면, 화면 상에선 이렇게 카트에 담긴 모습이 된다.
콘솔 창에 찍어보면 배열 형태로 각 component마다 name과 price, quantity가 잘 담아진 것을 확인할 수 있다.
2. 자바스크립트 배열 ➡️ JSON타입 변환하기
ajax를 사용해 컨트롤러에 보내주어야 하기때문에,
배열을 JSON 타입으로 변환해줬다.
* JS배열을 JSON 으로 변환
key, value 및 기본 형태의 배열을 JSON 형태로 변환할 수 있다.
1. JSON.stringify()
: JSON으로 넘어온 데이터를 string형태로 변환한다.
: JSON -> string
2.JSON.parse()
: string 형태 및 각종 형태를 JSON으로 변환한다.
// JSON으로 변환
const jsonCart = JSON.stringify(currentCart);
나는 JSON.stringify()를 통해 currentCart 배열을 JSON형태로 변환해줬다.
확인 차 콘솔창에 찍어보면, JSON형식으로 잘 바뀌어 진 것을 확인할 수 있다.
3. ajax 통해 서버로 전송하기
- URL에 controller에서 mapping해줄 URL를 적어준다.
일단 임시로 mapping URL을 이렇게 설정했다.
'http://localhost:8080/api/items'
'POST방식으로 body에 jsonCart를 담아 보낸다.'
//서버로 전송
fetch('http://localhost:8080/api/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: jsonCart,
})
.then((response) => {
if (!response.ok) {
throw new Error('견적 저장 실패');
}
return response.json();
})
.then((data) => {
alert('견적이 저장되었습니다.');
console.log('서버 응답:', data);
})
.catch((error) => {
console.error('저장 오류:', error);
alert('견적 저장 중 오류가 발생했습니다.');
});
4. controller에서 Map형태로 변환하여 받기
controller를 만들어준 뒤,
@RestController (REST방식으로 사용하겠다.) 어노테이션을 적어준 후, URL도 매핑해준다.
@PostMapping("/items")
HTTP POST방식으로 요청이 들어올 것이고, 이 경우에 ("/items")라는 특정 URL로 매핑되도록 설정해준다.
즉, 클라이언트가 Post 매서드로 /items 라는 URL에 데이터를 보낼 경우, 이 메서드가 실행된다.
public Map<String,Object> receiveItems
: 반환 타입이 Map<String, Object> 이므로, JSON 형태의 데이터를 반환할 수 있게 Map 형태로 반환된다.
따라서 클라이언트가 데이터를 JSON 형식으로 전송하면 이 메서드도 JSON형식으로 응답하게 된다.
@RequestBody Map<String, Object> items
: @RequestBody는 HTTP 요청의 body에 포함된 데이터(이 경우 JSON 형식!)를 Java객체로 변환해주는 어노테이션이다.
: 여기에서 요청 본문을 Map<String, Object> 형태로 변환시킨다.
결과적으로 클라이언트가 보낸 JSON 데이터가 Map 형식으로 매핑되는 것이다!
package com.boot.selftop_web.quote.controller;
import java.util.Map;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class CartController {
@PostMapping("/items")
public Map<String, Object> receiveItems(@RequestBody Map<String, Object> items) {
return items;
}
}
콘솔창을 통해 JSON타입의 견적이 성공적으로 서버로 넘겨져 Map 형식으로 매핑되어 넘겨진 것을 확인할 수 있다.
[2m2025-01-05T00:33:36.182+09:00[0;39m [32mDEBUG[0;39m [35m12516[0;39m [2m---[0;39m [2m[SelfTop_web] [nio-8080-exec-3][0;39m [2m[0;39m[36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m POST "/api/items", parameters={}
[2m2025-01-05T00:33:36.182+09:00[0;39m [32mDEBUG[0;39m [35m12516[0;39m [2m---[0;39m [2m[SelfTop_web] [nio-8080-exec-3][0;39m [2m[0;39m[36ms.w.s.m.m.a.RequestMappingHandlerMapping[0;39m [2m:[0;39m Mapped to com.boot.selftop_web.quote.controller.CartController#receiveItems(Map)
[2m2025-01-05T00:33:36.222+09:00[0;39m [32mDEBUG[0;39m [35m12516[0;39m [2m---[0;39m [2m[SelfTop_web] [nio-8080-exec-3][0;39m [2m[0;39m[36mm.m.a.RequestResponseBodyMethodProcessor[0;39m [2m:[0;39m Read "application/json;charset=UTF-8" to [{CPU={name=AMD 라이젠5-5세대 7500F (라파엘) (멀티팩(정품)), price=1226, quantity=1}, RAM={name=ESSENCORE KLEVV DD (truncated)...]
[2m2025-01-05T00:33:36.224+09:00[0;39m [32mDEBUG[0;39m [35m12516[0;39m [2m---[0;39m [2m[SelfTop_web] [nio-8080-exec-3][0;39m [2m[0;39m[36mm.m.a.RequestResponseBodyMethodProcessor[0;39m [2m:[0;39m Using 'application/json', given [*/*] and supported [application/json, application/*+json]
[2m2025-01-05T00:33:36.224+09:00[0;39m [32mDEBUG[0;39m [35m12516[0;39m [2m---[0;39m [2m[SelfTop_web] [nio-8080-exec-3][0;39m [2m[0;39m[36mm.m.a.RequestResponseBodyMethodProcessor[0;39m [2m:[0;39m Writing [{CPU={name=AMD 라이젠5-5세대 7500F (라파엘) (멀티팩(정품)), price=1226, quantity=1}, RAM={name=ESSENCORE KLEVV DD (truncated)...]
'💻 > Javascript' 카테고리의 다른 글
[JS] 로컬스토리지(LocalStorage) / JSON - Object 타입 변환 (2) | 2025.03.07 |
---|---|
[JS] 자바스크립트 문자열 공백 제거하기 - trim() , replace() (0) | 2025.01.04 |
[JS] querySelector(), querySelectorAll() (0) | 2024.08.11 |
[JS] 속성 선택하기 - .value / .innerHTML / .textContent 비교 (2) | 2024.08.06 |
[JS] 자바스크립트 연산자 우선순위 (0) | 2024.01.09 |