이번 1차 프로젝트에서 메인, 장바구니 페이지를 맡았다. 구현하기까지 여러 우여곡절이 있었지만, 결론적으론 여러 REST API (GET, PATCH, DELETE) 를 모두 활용해 볼 수 있어서 좋은 경험이었다.
기획 초기 레이아웃
최종 레이아웃
이솝 사이트 레이아웃을 따라가서 드롭다운 형식으로 기획하였다. 드롭다운 형식의 레이아웃은 화면 공간을 효율적으로 활용하고 따로 페이지 이동이 필요없어, 사용자가 쉽고 편리하게 접근할 수 있다는 장점이 있다.
첫 프로젝트의 본격적인 백엔드와의 통신이라 걱정이 좀 있었던 부분이었다.
장바구니 목록을 받고 또 그 안에서 수량 조절 또는 삭제를 했을 때 백엔드를 통해 데이터를 보내주고 업데이트 되는 로직이다. 원래 수량 조절, 그러니까 patch 할때 +/- 부분을 클릭할때마다 수량변화를 전달하려고 했는데 결국에는 수량 조절 옆에 확인 버튼을 새로 만들어 수량 변경 후 버튼을 클릭해서 변한 값을 보내주는 것으로 결정하였다.
GET
서버에 GET 메서드를 통한 회원 장바구니 목록 불러오기
기존에는 화면에 보여지기만 하는 mock data로 관리하고 이를 map을 통해 렌더링하던 cartList 컴포넌트에서 fetch 함수를 통해 서버에 데이터를 요청하였다.
useEffect(() => {
fetch(`${API_ADDRESS_ORDERS}carts`, {
method: "GET",
headers: {
Authorization: token,
},
})
.then(res => {
return res.json();
})
.then(data => {
return setItems(data);
});
}, []);
PATCH
장바구니 아이템 수량을 수정하면 PATCH를 통해 서버 내부에 저장 된 데이터를 업데이트 하는 기능을 구현해보았다.
GET, POST 만 알고 PATCH는 처음 사용해보는데, PUT 과 PATCH 가 헷갈렸었다. 그래서 찾아본 바로는 PATCH는 PUT과 비교해서 리소스의 일부를 업데이트 한다. 예를들어 수량을 변경할 때, cart data의 구조가 cart.id, cart.quantity, cart.count, cart.sum 이라고 한다면, 장바구니 수량 수정시 PATCH는 해당 부분만을 업데이트 한다.
이때, 변경 사항은 fetch 함수의 body 부분에 JSON.stringify()로 전달 하였다.
const handleCount = id => {
const url = `${API_ADDRESS_ORDERS}carts/${items[id].id}`;
fetch(url, {
method: "PATCH",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: token,
},
body: JSON.stringify({ count: items[id].count }),
})
.then(response => response.json())
.then(data => data)
.catch(error => error);
};
DELETE
특정 아이템을 삭제버튼을 클릭 할 시 DELETE 메서드로 서버와 통신하고 이 변경사항을 다시 받아오는 로직이다.
const deleteItem = id => {
fetch(`${API_ADDRESS_ORDERS}carts/${items[id].id}`, {
method: "DELETE",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: token,
},
});
const newItems = items.filter((_, i) => i !== id);
setItems(newItems);
};
사용자가 수량을 바꾼 후 수량확인 버튼을 누를 수 있도록 유도하기 위해 수량 바꾸는 부분에 밑의 이미지 처럼 마우스를 호버할때만
수량 확인
버튼이 나타나게 하였다.
const [showChangeButton, setShowChangeButton] = useState();
const handleMouseEnter = id => {
setShowChangeButton(id);
};
const handleMouseLeave = () => {
setShowChangeButton(false);
};
<div
className="itemQuantity"
onMouseEnter={() => handleMouseEnter(id)}
onMouseLeave={handleMouseLeave}
>
<button className="minus" onClick={() => decrement(id)}>
-
</button>
{item.count}
<button className="plus" onClick={() => increment(id)}>
+
</button>
{showChangeButton === id && (
<button className="check" onClick={() => handleCount(id)}>
수량변경
</button>
)}
</div>
장바구니가 비었을때, 그리고 아이템을 전부 삭제했을 때 빈 장바구니 페이지를 보여줘야했다.
조건부 렌더링으로 해당 조건일때 페이지를 보여주고 빈 장바구니 알람이 일정 시간 뒤에는 다시 사라지게 구현하였다.