-
[위코드 1차 프로젝트 회고(1)] 기능 구현에 대한 회고회고록 2022. 7. 31. 17:22
https://jeongeuni.tistory.com/48
7월 18일 ~ 7월 29일 , 약 2주간 프론트 3명, 백엔드 2명으로 구성된 팀으로
Magazine B라는 웹사이트를 클론코딩하는 프로젝트를 진행했다.
팀명은 '매거진 KILL 🥷🏻' 로 매우 강력해보이는 팀명인데 그만큼 열정을 담아 열심히 하자는 의미로 이렇게 지었다.
이 험한 세상..! 독하게 살아가야 하기 때문에!!
< 우리가 클론 코딩한 Magazine B >
1. Magazine B 웹사이트 소개
Magazine B는 전 세계의 균형 잡힌 브랜드를 한 호에 하나씩 소개하는 광고 없는 월간지이다.
브랜드의 숨은 얘기는 물론 감성과 문화까지 담고 있어 브랜드에 관심 있는 사람이라면 누구나 쉽게 볼 수 있다.
메인 서비스로는 새로운 비즈니스를 구상하는 브랜드 관계자부터 브랜드에 대한 감각을 익히고 싶어 하는 이들까지
브랜드에 관심을 가진 모두를 위해 진지하지만 읽기 쉬운 잡지를 만들어 판매하는 것이다.
2. UI가 깔끔하다.
웹 사이트를 클론 코딩하는 프로젝트를 한다고 했을 때 일단 따라 하고 싶으려면 디자인이 깔끔해야 한다고 생각했다.
그런데 딱 이 웹사이트가 그러해서 2주 동안 재미있게 작업했다. : )
아래의 이미지처럼 전체적으로 깔끔하고 감각적인 웹 사이트이다.
이 감성을 그대로 담고 가고 싶어서 싱크로율 100%를 목표로 scss도 열심히 작업했고
이 목표를 이뤄냈다고 자부할 정도로 비슷하게 클론 코딩했다 : )
(웹 사이트 주소: https://magazine-b.co.kr/ )
2. UX도 깔끔하다.
기능적으로도 깔끔한 사이트이다.
2주라는 제한된 시간 안에 커머스 웹사이트를 구현해야 하는데
Magazine B는 아주 간단한 웹 사이트처럼 보이지만
회원가입/로그인, 장바구니/결제, 배송, 찜하기, 리뷰, Q&A 등
커머스 웹사이트로서의 기능을 다 지니고 있다.
1차 프로젝트는 2차 프로젝트로 가기 위한 준비단계이고
2차 프로젝트는 위코드를 수료하고 본격적으로 취직을 하기 위한 준비단계라고 생각한다.
이에 1차 프로젝트로 Magazine B 웹사이트를 클론 코딩 함으로써
2차 프로젝트로 가기 전에 기초를 잘 다니고 갈 수 있어서 좋았다. : )
< 우리가 구현한 기능 >
회원가입/로그인, 메인페이지, 상품리스트 페이지, 상품상세 페이지, 장바구니 모달, 장바구니 메인
푸터, 내비게이션 바, 검색 기능, 필터 기능, 리뷰 기능, 포인트 결제
이렇게 구현하였다.
이 중에서 나는
메인페이지, 상품상세 페이지, 장바구니 모달, 푸터, 리뷰 기능에 기여하였다!
< 내가 구현한 기능 - 메인페이지 / 상세페이지 / 리뷰기능 / 장바구니 모달/ 푸터>
- 1. 메인페이지
위의 동영상은 내가 구현한 메인페이지이다.
클론 코딩한 Magazine B의 메인페이지와 싱크로율이 거의 100%에 달한다고 자부할 만큼 비슷하게 만드려고 노력했다.
이미지와 동영상이 화면에 꽉꽉 차있는데 이는 css에 object-fit: cover; 속성을 줌으로써 구현해낼 수 있었다.
메인페이지는 이미지 슬라이드(Carousel) , MainSectionMenu , MainSectionVideo로 구성되어있다.
👉 이미지 슬라이드(Carousel)
Carousel을 구현하는데 이렇게 하나하나 수작업을 해야 한다고는 상상도 못 했다. 되게 간단해 보이는데 꽤 복잡하다고 생각한 Carousel이다. 여기서 구현한 기능을 설명하자면
- 3초마다 슬라이드 이미지 자동 변환
- 오른쪽, 왼쪽 누르면 슬라이드 이미지 변환
- 변환된 이미지마다 해당 데이터 가져옴이렇게 설명할 수 있겠다. 더 세세히 설명을 붙이자면
- setinterval 함수 사용하여 3초마다 슬라이드 이미지가 자동 변환되도록 구현했고 useState로 숫자 3이 넘어가면 1부터 다시 시작하도록 설정했다.
- 슬라이드 이미지의 오른쪽을 누르면 앞의 이미지로, 왼쪽을 누르면 뒤의 이미지로 변환하는데 이는 button태그로 오른쪽 반, 왼쪽 반 각각 넓이를 50%씩 주고 opacity: 0으로 안 보이게 처리하였다.
- 또한 const isFirstSlide = slide === 1; const isLastSlide = slide === 3;로 변수를 만들어 1과 3에서는 버튼을 눌러도 안 넘어가도록 disabled에 할당해주었다.
- 슬라이드가 변환될 때 각 이미지에 맞는 데이터가 출력되도록 해야 한다. 이는 데이터에 filter메서드를 걸어 data.id와 slide의 숫자가 같을 때만 리턴하도록 해서 구현할 수 았었다.
이 기능들을 구현하면서 가장 애를 먹었던 부분은 이미지에 맞는 데이터를 출력하는 부분이었다. 일단 이미지는 잘 변환하는데 그에 맞는 데이터를 어떻게 입히느냐가 고민이었다.
"id" : 1,
"img" : "/images/main/mainSlide.1.jpg"이렇게 data에서 id와 img의 src에 일치하는 숫자를 주었고
const sameNumData = data.filter(data => { return data.id === slide; }); setMainSlideData(() => sameNumData);
id와 slide숫자가 같은 것을 걸러내어 이미지에 맞는 데이터를 뽑아낼 수 있었다!
👉 MainSectionMenu
메인페이지의 깔끔하고 모던한 sectionMenu이다.
배열로 되어있는 데이터에 map을 돌려서 코드의 가독성을 높였고
각 이미지를 누르면 해당 상품의 상세페이지로 이동하며 shop을 누르면 상품리스트 페이지로 이동한다.
이동시키기 위해 useNavigate훅을 사용했고 또한 이동했을 시 ScrollUp함수로 인해 페이지의 상단으로 이동된다.
<img className={i === 1 ? 'halfImg' : null} src={img} alt="1" onClick={() => { navigate(`Products/${issue_number}`); scrollUp(); }} />
👉 MainSectionVideo
눈 정화를 시켜주는 것 같은 동영상을 삽입한 MainSectionVideo이다.
이 부분을 구현하면서 처음으로 useRef훅을 사용했다.
스크롤이 동영상에 도달했을 때 자동으로 동영상이 재생되어야 하는데
google 검색 도움을 받았을 때 많은 개발자들이 이것을 구현하기 위해 useRef훅을 사용하고 있음을 알았다.
만약 내가 useRef훅을 몰랐다면 엄청난 고통(?), 노가다(?)를 하였을 것이다.
google 검색의 중요성을 느끼게 해 준 부분이었다.
- 2. 상세페이지
내가 구현한 상세페이지다. 상세페이지는 상단과 하단에 있는 리뷰기능으로 나눠볼 수 있다.
👉 상세페이지 상단
- -, +를 누를 때마다 상품의 개수가 변하며 가격도 함께 변동하는데 이는 useState로 구현했다.
- 상품 리스트 페이지에서 상품을 눌렀을 때 해당 상품의 상세 페이지로 이동할 수 있게 하기 위해 path parameter를 이용하여 backend와 api 통신을 했다.
- ADD TO CART 누르면 장바구니 모달창이 켜지며 -와 +한 만큼의 상품이 추가된다. 이것 또한 path parameter를 이용하여 backend와 api 통신을 했으며 대신 POST로, body에 { quantity: orderQuantity }를 담아 전송했다.
- back에게 받은 데이터가 'SUCCESS' 일 때만 장바구니 모달창이 켜지며 'SUCCESS' 가 아니라면 alert를 띄워준 후 navigate로 로그인 창으로 이동하게 구현했다.
👉 리뷰 기능
리뷰 기능은 내가 제일 애정을 가지고 있는 기능이다.
왜냐하면 원래 magazin B 웹 사이트의 상세페이지에 리뷰기능이 없는데
magazine K에는 리뷰기능이 있었으면 좋겠어서 추가로 구현한 부분이고
무에서 유를 만들어 내는 거라 여러 타 웹사이트를 참고하여 디자인도 정하고
backend랑 어떻게 통신을 주고받을지 많은 소통 끝에 탄생한 기능이기 때문이다.
- 호버, 클릭하면 별점이 채워지며 클릭을 해야지만 state가 변경한다. 이는 [...Array(5)].map으로 빈 별을 채워줬고 클릭하면 rating state가 바뀌어 index와 비교해서 작거나 같을 시 className으로 on을 줘서 별이 채워지도록 했다.
{[...Array(5)].map((star, index) => { index += 1; return ( <button type="button" id={index} key={index} className={index <= (hover || rating) ? 'on' : 'off'} onClick={() => setRating(index)} onMouseEnter={() => setHover(index)} onMouseLeave={() => setHover(rating)} > <span className="star">★</span> </button> ); })}
- '리뷰등록' 버튼을 누르면 선택한 별점, 입력한 댓글, 아이디명이 등록된다. 해당 제품을 구매하지 않았으면 리뷰를 달 수 없게 했고 이는 POST로 사용자가 해당 제품을 구매했는지 토큰으로 인가 후 rating, commentText를 담아 back에게 전송해주었다. 그리고 두 번째 then에서 댓글이 추가되도록 구현했다.
- back에서 주는 rating은 '1.0', '2.0'과 같은 문자, 내가 별점을 누를 때는 rating이 1, 2와 같은 숫자인데 이는 Number(rating)으로 모조리 숫자로 바꿔줌으로 해결할 수 있었다.
- 장바구니 모달
장바구니 모달의 scss와 해당 -, + 를 눌렀을 시 cart의 []에 총수량이 담기는 것을 구현했다.
처음에는 자식요소인데 어떻게 부모요소에게 반영하나 하고 감이 잡히지 않았는데 state 끌어올리기를 해야 하는 부분이었다.
이 기능에서는 Cart.js가 부모요소이고 SelectedPrd.js가 자식요소인데
Cart.js의 state를 SelectedPrd.js에 props로 전달함으로써 구현할 수 있었다.
state 끌어올리기를 제대로 경험해 본 기능이었다.
- 푸터
간단한 html, scss이다. 홈페이지를 참고하여 뚝딱뚝딱 만들어냈다.
푸터가 다른 페이지와 겹치지 않게 하기 위해 position: relative; 와 transform: translateY(-100%);를 적용했다.
'회고록' 카테고리의 다른 글
[기업협업 회고] 기능 구현에 대한 회고 - 실시간 CCTV 영상을 활용한 공정 모니터링 시스템 (2) 2022.09.12 [위코드 2차 프로젝트 회고(2)] 팀 프로젝트에 관한 회고 (JEJUPASS 클론코딩 ) (0) 2022.08.14 [위코드 2차 프로젝트 회고(1)] 기능 구현에 대한 회고 (JEJUPASS 클론코딩) (0) 2022.08.14 [위코드 1차 프로젝트 회고(2)] 팀 프로젝트에 대한 회고 (4) 2022.07.31 "인생은 단 한 번뿐, 대충 살아서는 행복할 수 없어!" 비전공자 개발자 도전기 (2) 2022.06.13