1차 프로젝트에서 계획하게 된 프로젝트의 이름은 "SIMPLE" 입니다.
"SIMPLE"은 마음 심(心) 과 Place 의 합성어로 만들어진 이름입니다. 저희는 '가심비' 즉, 돈에 대한 가성비가 아닌, 마음에 대한 가성비를 추구하는 프로젝트를 기획했습니다.
SIMPLE에서는 다양한 캠핑용품을 판매하고 있습니다. 우리가 판매하는 상품을 사용함으로써 EndUser가 있는 곳이 마음의 휴식처가 되길 바랐습니다.
"SIMPLE"의 초기 프로젝트 계획은 '마음이 쉴 수 있고, 위치한 곳에 분위기도 함께 선물하는 숙박'으로 장소대여를 서비스하는 프로젝트를 기획했습니다. 하지만, 1차 프로젝트에서는
'React' 외에 다른 외부 라이브러리를 사용할 수 없다.' 라는 제약이 존재했으며, 날짜를 선택할 수 없는, 장소대여 서비스에서 빠질 수 없는 캘린더 기능을 사용할 수 없었습니다.
이후, 멘토님들과 회의를 통해 프로젝트의 방향을 바꿔, 캠핑 용품을 판매하기로 했습니다.
프로젝트의 취지와 목표를 설정한 뒤엔 각 팀원이 담당할 페이지를 할당하는 시간을 가졌습니다.
페이지의 구성은 로그인, 회원가입, 메인페이지, 상품리스트 페이지, 상세페이지, 장바구니와 결제로 이루어지게 되었습니다. 저희에게 주워진 시간은 '2주'였습니다.
연관성이 있는 페이지별로 구분을 시작하였고, '로그인, 회원가입', '메인페이지, 상품리스트', '상세페이지', '장바구니, 결제'로 구분지었습니다. 저희 팀은 프론트엔드 개발자 4명,
백엔드 개발자 2명으로 구성되어 있었습니다. 그 중 저는 상세페이지를 담당하게 되었습니다. 상세페이지를 담당하겠다고 했던 이유는 다양한 문법을 복습할 수 있으며, 새로운 기술을
배울 수 있는 페이지라고 생각했기 때문입니다. 또한, 상세페이지는 추가기능을 구현할 수 있는 범주가 넓다고 느껴졌습니다. 역할이 정해진 이후엔, convention을 정했습니다.
코드 작성에는 camelCase를 약속하고, 초기세팅으로 StyleLint와 Pritter의 들여쓰기 약속, resetSCSS 등을 작성했습니다. 서로의 할일과 일정에 대해서는 Trello를 사용하여 계획을
구체화 시켰습니다. 또한 프로젝트를 Agile 방식으로 진행하도록 약속하였습니다.
제가 담당한 상세페이지에 대해 기초 레이아웃을 구성한 뒤에
첫 번째 욕심으로 저는 상세페이지에 '옵션' 기능을
언급했습니다. 옵션을 선택하는 기능을 통해, 조건부 렌더링을 복습할 수 있었습니다.
옵션이 있는 상품과 없는상품으로 구분지어, 백엔드개발자 분들이 넘겨주시는 데이터에 옵션에 대한 정보가 있다면 옵션 선택기능이 보이도록, 없다면 수량만 선택할 수 있도록 구성했습니다.
이 과정에서 가장 어려웠던 부분은 데이터가 들어오는 시점은 UseEffect를 사용해 fetch 받아오는 시점이기 때문에, 레이아웃의 렌더링보다 늦어지는 데이터 수입이였습니다.
레이아웃을 구성하는 데이터들이 들어오질않으니, 화면의 렌더링부터 문제가 일어났습니다. 따라서 레이아웃의 렌더링을 조건부 렌더링으로 만들었습니다. 데이터가 들어오면 화면을 렌더링 할 수 있도록
구현했습니다.
▲ 위 사진처럼 item.id가 true면 이후 레이아웃을 렌더링해라!
옵션을 선택했을 때, 선택된 값을 배열 State에 저장하여 컴포넌트를 만들어내고, 또 다른 옵션을 선택했을때 배열 State에 추가하여 옵션 컴포넌트를 늘려가는 방식으로 구성하였습니다.
Detail 부모 컴포넌트에서 배열을 재구성하는 filter매서드를 사용하여 onRemove 함수를 만들고 자식 컴포넌트인 옵션 컴포넌트에 전달했습니다. 매우 중요하고 사용되는 곳이 많으니
꼭 다시한번, 작성해볼 필요가 있는 코드입니다!
자식 컴포넌트인 옵션 컴포넌트에 삭제의 의미로 X 이미지를 넣어 onClick이벤트를 통해 삭제를 진행되도록 구성하였습니다.
반면에 옵션에서 구현하지 못한 기능이 있었는데, 옵션 컴포넌트에서 가격을 늘리면 부모컴포넌트에 totalPrice에 영향을 끼쳐 총 합계금액이 변동되는 것을 구현하지 못했습니다. 이 사안은 시간이
부족해 추가 구현으로 미뤄두었습니다.
두번째 욕심은 useState을 이용해 detail 페이지의 하단부에 있는 '상품정보, 리뷰, 상세정보' 각각의 컴포넌트를 노출하는 것이였습니다.
이 기능을 구현하는 코드를 보게 되면
각각의 컴포넌트를 상수데이터로 구현하여, 겹치는 코드를 맵으로 구현한뒤, 보여지는 컴포넌트는 onClick 이벤트로 id를 수정해가며 보여지도록 하였습니다. 간략하면서 가독성이 좋은 코드로 탄생할 수 있도록 도와주신 명성멘토님께 감사드립니다.
위 컴포넌트는 '상품설명', '리뷰', '상세정보'로 구성된 컴포넌트 입니다. 위 컴포넌트에 있는 onClick 이벤트로 CurrentTap State값을 변경하며 원하는 컴포넌트의 내용을 보여주는 것입니다.
map method를 통해 반복적인 코드를 줄이고 코드의 가독성을 취할 수 있었습니다.
아쉬운 점은, 선택에 의한 부각효과로 선택되지않은 컴포넌트와 선택된 컴포넌트에 각각에 다른 SCSS 효과를 부여하고 싶었지만, 이 또한 시간제약에 의해 추가구현으로 미루게 되었습니다.
상품설명 컴포넌트에서는 Fetch를 통해 들어오는 정보를 띄우고, 간단한 토글기능을 추가하여 상품의 배송, 환불 및 교환에 대한 정보를 나타냈습니다. 토글에 대한 코드 또한 State 값으로
관리 하기 때문에 가독성이 뛰어나도록 작성되었습니다.
위 토글에 대한 코드에서 중요하게 볼 점은, 46번째 줄, title={info.name} 입니다. div 태그에는 title 이라는 속성이 없기 때문에 info.title이 아닌 info.name으로 작성해야합니다.
위와 같이 각 태그들은 서로 다른 속성 값들을 가지고 있기때문에, 관련 요류가 발생했을 땐, 해당 태그가 읽지 못하는 속성은 아닌지 확인해야합니다.
다음으로, 리뷰 카테고리를 보겠습니다. 리뷰 카테고리에서는 MockData로 구성된 정보들로 구성되어 있습니다.
리뷰 카테고리에서는 'SCSS'와 Map 함수의 매서드인 Child 매서드에 대해 자세히 알 수 있었습니다. map 함수를 사용하면 동일한 정보들과 스타일이 부여되지만, Child 매서드를 사용하면
특성 순서에 있는 요소들에 접근하여 스타일을 변경할 수 있습니다. 위 GIF파일을 보면 "아주 좋아요" 부터 "별로에요" 까지 Map을 돌려 출력했지만, 아주 좋아요만 부각되도록 글씨의 색깔과
굵기를 조절해두었습니다. Child 매서드를 사용하면 이렇게 자유도 높은 Map함수를 구성할 수 있습니다. 리뷰에서는 발전시킬 수 있는 추가기능이 다양해보입니다. '도움돼요, 도움안돼요'
토글기능, 리뷰 추가 기능, 점수에 따라 그래프와 별점 조절기능 등, 다양한 발전 가능성이 보이는 카테고리입니다.
또한, Fetch를 받아올 때, 저장할 State와 받아오는 Data를 콘솔을 찍어보며 확인해보기도 중요했습니다. 들어오는 Data의 형식을 확인하고 State에 어떻게 저장할지 파악하는 것이 중요했습니다.
위 처럼 data형식에 따라 State에 저장할때 SetItem(data.data[0]) 으로 저장하면 item이 사용되는 곳의 코드가 깔끔하게 작성될 수 있는 것입니다.
위 코드는 기존의 장바구니에 있는 상품을 파악하고, 현재 장바구니에 담는 상품이 장바구니에 있는지 확인한 뒤, 없는 상품이라면 POST 매서드로, 이미 있는 상품이라면 PETCH
매서드로 보내도록 구현한 함수 입니다.
▲ 백엔드에서 보내주는 데이터 형태
https://github.com/wecode-bootcamp-korea/41-1st-DCB-frontend
▲ 완성 Github!
SIMPLE을 제작하면서 전반적인 e-commerce 웹사이트의 구성과 Service의 Flow를 알 수 있었습니다. 회원가입부터 로그인, 상품을 골라보고 찾아보고 원하는 물품을
장바구니에 담아보는 등 유저로써 할 수 있는 상호작용을 구현했습니다.
개인의 코드의 아쉬운 점은, 코드에 대한 숙련도와 이해도가 부족했으며, 적재적소에 알맞은 코드를 구상하지 못했다는 점이 있습니다.
함수 로직 구현, 수많은 State와 SetState의 사용, 어떤 역할을 하는 변,함수인지 알 수 있는 변,함수명 짓기 등 많은 아쉬움이 있습니다.
수 많은 함수의 로직과 State들로 가득찬 VScode는 제가 담당한 details 페이지의 개발자인 저도 알아 볼 수 없었습니다.
적절한 컴포넌트를 나누는 것도 중요하다는 것을 알았습니다.
컴포넌트를 나누는 기준을 기능별로 나누도록 해야하고, depth의 깊이를 줄이고, 코드의 가독성을 챙겨야한다는 것을 배웠습니다.
현재 제 코드를 다른 사람이 유지보수 한다고 생각한다면, 함수의 로직을 파악하는데 하루, State들의 역할과 변경점에 대해 파악하는 데 하루가 걸릴 것 같습니다.
질 높은 코드, 가독성이 좋고 이해하기 쉬운 코드로 제작해야하려면 개인의 코드 구성 능력을 키워야한다는 점, 그 능력은 꼭 필요하다는 것을 배웠습니다.
유저의 행동을 예측하는 것은 무척이나 어렵다는 것을 배웠습니다. 에러핸들러의 중요성도 느껴볼 수 있었습니다. 저희가 구현하고 의도한 서비스 이용의 순서는
회원가입 -> 로그인 -> 메인페이지 -> 상품리스트 -> 상세페이지 -> 장바구니 / 결제 였지만, 로그인을 하지 않은 상태로 장바구니로 들어가본다던지, 상품을 담아본다던지,
메인페이지에서 똑같은 상품을 여러번 장바구니로 담았을 때, 수량이 더해지는 것이 아니라, 새로운 상품처럼 장바구니에 담기는 등, 다양한 오류와 버그가 있었습니다.
저희가 원하는 대로 이용자가 움직여주고, 서비스를 이용해준다는 것은 어렵다는 것을 알았고, 의도하지 않은 루트의 접근은 에러핸들러를 만들어 대처해야하는 것을
알았습니다. 로그인을 하지않은 상태로 장바구니에 들어가려하면 알림을 통해 로그인이 필요하다는 것도, 상세페이지에서 상품의 갯수가 음수로 내려간다던지, 같은 상품을
다른 상품으로 인식해 장바구니에 들어가는 등. 유지보수의 필요성과 유저의 루트를 새로운 각도에서 볼 수 있다는 점을 배웠습니다.
소통의 아쉬운 점은 프론트엔드와 백엔드의 소통을 이야기해볼 수 있을 것 같습니다.
백엔드에서 전해준 데이터의 구조(객체, 배열 등), key값과 value의 형태(String, Number 등)를 파악하고 코드를 작성해야하는 점을 간과했었고, 백엔드에서는 바뀐 Key값을
프론트에 얘기해주지 못했다던지, 중간중간 확인을 위한 소통이 필요했지만, 서로의 일에 집중하며 앞만보고 갔다는 점이 잘못되었다는 것을 늦게서야알게 되었습니다.
프론트엔드끼리의 소통도 부족했습니다. 프론트끼리의 className중복, z-index의 충돌, 루트의 중복 등 다양한 에러가 발생하였고 서로의 완성품을 매치하는 부분에서
다양한 에러와 complite가 발생하였고, 해결을 위한 시간이 또 발생하였기 때문에 비효율적이고 아쉬운 소통의 부재를 느낄 수 있습니다.
프론트엔드와 백엔드의 소통, 프론트엔드와 프론트엔드의 소통이 자주 필요하고 중요하다는 점을 알게 되었습니다.