ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [위코드 1차 프로젝트 회고(1)] 기능 구현에 대한 회고
    회고록 2022. 7. 31. 17:22

    https://jeongeuni.tistory.com/48

     

    [위코드 1차 프로젝트 회고(2)] 팀 프로젝트에 대한 회고

    https://jeongeuni.tistory.com/47 [위코드 1차 프로젝트 회고(1)] 기능 구현에 대한 회고 7월 18일 ~ 7월 29일 , 약 2주간 프론트 3명, 백엔드 2명으로 구성된 팀으로 Magazine B라는 웹사이트를 클론코딩하는 프..

    jeongeuni.tistory.com


    7월 18일 ~ 7월 29일 , 약 2주간 프론트 3명, 백엔드 2명으로 구성된 팀으로

    Magazine B라는 웹사이트를 클론코딩하는 프로젝트를 진행했다.

     

    팀명은 '매거진 KILL 🥷🏻' 로 매우 강력해보이는 팀명인데 그만큼 열정을 담아 열심히 하자는 의미로 이렇게 지었다.

    이 험한 세상..! 독하게 살아가야 하기 때문에!!

    ppt 중 한 슬라이드를 첨부합니다-!


    < 우리가 클론 코딩한 Magazine B >

    1. Magazine B 웹사이트 소개

    Magazine B는 전 세계의 균형 잡힌 브랜드를 한 호에 하나씩 소개하는 광고 없는 월간지이다.

    브랜드의 숨은 얘기는 물론 감성과 문화까지 담고 있어 브랜드에 관심 있는 사람이라면 누구나 쉽게 볼 수 있다.

    메인 서비스로는 새로운 비즈니스를 구상하는 브랜드 관계자부터 브랜드에 대한 감각을 익히고 싶어 하는 이들까지

    브랜드에 관심을 가진 모두를 위해 진지하지만 읽기 쉬운 잡지를 만들어 판매하는 것이다.

    2.   UI가 깔끔하다.

    웹 사이트를 클론 코딩하는 프로젝트를 한다고 했을 때 일단 따라 하고 싶으려면 디자인이 깔끔해야 한다고 생각했다.

    그런데 딱 이 웹사이트가 그러해서 2주 동안 재미있게 작업했다.  : )

     

    아래의 이미지처럼 전체적으로 깔끔하고 감각적인 웹 사이트이다.

    이 감성을 그대로 담고 가고 싶어서 싱크로율 100%를 목표로 scss도 열심히 작업했고

    이 목표를 이뤄냈다고 자부할 정도로 비슷하게 클론 코딩했다 : )

     (웹 사이트 주소: https://magazine-b.co.kr/ )

    메거진 B

    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">&#9733;</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%);를 적용했다.

    댓글

Designed by Tistory.