Wecode 1차 프로젝트 후기_Beats_Frontend

Yunji·2020년 6월 7일
2

project

목록 보기
2/2
post-thumbnail

프로젝트 소개

위코드에서 진행한 웹사이트 클론 프로젝트로 아이디어를 냈던 BEATS 홈페이지를 만들게 되었다 2주동안 백앤드1명 프론트3명이서 작업을 진행하였고 Trello 와 매일 아침 StandUP Meeting 을 하면서 작업을 이어나갔다

CRA, React Router, Sass, Fetch, Map 등을 사용하였고
Daum map api 와 react-reveal 라이브러리를 활용해서 스크롤 애니메이션을 구현하였다

내가 맡은 역할/ 부분

제품 메인 리스트 부분과 제품의 상세 페이지, 제품 상세에서 장바구니 추가하는 부분, 구매페이지와 구매내역 확인 페이지를 작업하게 되었다

제품 메인 리스트

  • 비츠의 메인 페이지는 총 세개가 있는데 그 중 하나인 각 제품의 상세 페이지로 들어가기 전에 리스트로 볼 수 있는 페이지 이다
    리스트 답게 레이아웃이 똑같아서 하나의 리스트 템플릿을 만들어서 백엔드의 데이터를 받아와 map를 돌려 보여준다
  • 이부분이 처음으로 백앤드와 맞춰본 부분이었는데 확실히 mock data 로 작업할 때와는 다르게 직접 백앤드에서 보내주는 데이터를 받아서 작업하니 재밌었다 내가 짠 코드가 문제없이 실행되는 걸 보니 신기했다

제품 상세 페이지 & ADD TO CART

  • 비츠의 제품 각각의 상세 페이지는 레이아웃이 조금씩 다 달랐다 그래서 초반에는 다 하려고 했는데 작업하다보니 한 페이지 만드는데도 시간이 엄청 걸렸다... 진짜로 눈 빠질뻔... 그래서 두개 정도만 다 작업하고 나머지는 8 페이지는 밑에 보이는 빌리 아일리시 사진 처럼 커버 부분만 작업했다 원 페이지 느낌으로! 이 부분도 백앤드의 데이터를 받아와서 작업했는데 제품별로 다른 페이지로 이동을 해야 했기 때문에 라우터를 이용해서 페이지를 이동했다 개인적으로 이부분이 제일 재밌었다!

  • 버튼을 클릭 했을 때 각 제품의 id 를 가져와서 라우터에 적용해 이동하고 그 id 를 가진 데이터를 상세페이지 레이아웃에 뿌려주고 그 해당 페이지에서 컬러 선택 후 add to cart 를 누르면 컬러와 제품 아이디를 넣어 POST 로 서버에 전송하는 것 까지! 처음에는 너무 플로우가 복잡해서 힘들었지만 하다보니 너무 재밌었다 중간에 약간 멘붕이 오기는 했지만...🤦‍♀️

  • 빌리 아일리시 사진이 너무 이뻐서 작업할 맛 났던 페이지
    이 부분에 원래는 없던 color 선택 버튼을 추가했다 생각보다 잘 어울려서 놀람

  • 전체 다 작업했던 PowerBeats 제품 상세 페이지

  • 컬러 버튼 클릭 시 제품 이미지가 바뀐다 실제로는 제품 이미지가 png 로 되어있고 배경화면 색상이 따로 있는 페이지 이다 color 버튼을 클릭 했을 때 제품 이미지와, 배경색상, 컬러 텍스트, 컬러 체크 부분 까지 총 4가지가 바뀌어야 해서 복잡했던 페이지이다
  • state 에 current 값을 줘서 그 current 값에 따라 변할 수 있도록 코드를 구성했다
state = {
    current: 0,
    view: false,
  };
const selProduct = {
  0: {
    productColor: "white",
    productColorName: "White",
    productColorNameC: "#000",
    src: `${Config.ProductImage}/powerbeats-white.png.large.2x.png.large.2x.png`,
    check: 1,
    color: "rgb(101, 101, 101)",
  },
  1: {
    productColor: "black",
    productColorName: "Black",
    productColorNameC: "#fff",
    src: `${Config.ProductImage}/powerbeats-black.png.large.2x.png.large.2x.png`,
    check: 1,
    color: "#fff",
  },
  2: {
    productColor: "#911827",
    productColorName: "Red",
    productColorNameC: "#fff",
    src: `${Config.ProductImage}/powerbeats-red.png.large.2x.png.large.2x.png`,
    check: 1,
    color: "#fff",
  },
};
// 이렇게 스타일을 리스트로 만들어서 접근했다 
<section
          className="mainContentsSelect"
          id="color"
          style={{
            backgroundColor: selProduct[this.state.current].productColor,
          }}
        >

구매 페이지

order 부분은 우리 서버가 문제가 있어서(오하이오) 수정 중일 때 데이터 없이 만든 페이지 이다 (대충 데이터가 들어왔다고 가정하고) 그렇게 만들고 나서 서버 문제가 해결되고 딱 붙여봤는데 바로 구현되서 놀랐던 기억이 있다ㅎㅎ 뿌듯한 페이지🤩

  • 구매 페이지 부분도 재밌게 작업한 페이지 들 중 하나이다 사실 백앤드와 함께 작업한 부분은 다 재밌었다ㅋㅋㅋ 나는 내가 처음에 레이아웃 잡는 것을 좋아한다고 생각했는데 이번 프로젝트를 하면서 데이터를 받아오는 부분을 더 좋아한다는 것을 알게 되었다 가끔 map 지옥에 빠지기는 했지만ㅋㅋㅋ
  • 장바구니에서 order 버튼을 누르면 order 페이지로 넘어간다 order 페이지가 로드 될 때 서버에서 get으로 장바구니에 담겨있던 데이터를 받아와서 보여준다 총 가격까지, 거기에서 이제 배송비를 추가하고 최종 가격을 보여준다
  • 사용자 정보도 역시 같이 받아와서 보여주고 주소 검색은 다음 지도 api 를 가져와서 사용하였다 지도 api 는 미흡한 부분이 많아서 더 공부해야 할 것 같다😂

구매 내역 확인 페이지

  • order 페이지에서 구매를 누르면 서버로 정보를 보내고 구매내역 확인 페이지로 넘어간다 이때도 서버로 넘겼던 구매 제품 리스트를 페이지를 로드할 때 받아와서 보여준다

기억하고 싶은 코드

제품 리스트 페이지에서 해당 제품의 상세 페이지로 넘어가는 부분

  • 초반에 너무 여러 부분으로 컴포넌트를 나누어서 작업해서 컴포넌트별 이동이 많았다

대충 이런 느낌..
product 를 누르면 리스트 페이지가 뜨고 그 하나하나의 리스트도 하나의 컴포넌트에 데이터를 map 돌려서 정보들을 보여준 것이고 그 안에 상세 페이지로 이동하는 버튼도 컴포넌트화 된 버튼이라 직접적으로 onclick을 넣을 수 없어 함수를 props 로 전달해서 사용했다 그래서 그 버튼을 누르면 각 제품별 api 를 받아와서 라우터 이동을 한다 그리고 나서 그 상세 페이지에서 add to cart 버튼을 누르면 그 정보를 서버로 넘겨주고 서버는 그 데이터를 가지고 있다가 장바구니를 누르면 다시 보내준다... 이 부분이 너무 복잡해서 이해하는데 힘들었고 그만큼 재미있었다

과정이 너무 복잡해서 적으면서 이해한 부분... 너무 인상깊은 부분...(이와중에 저녁 먹겠다고🍕 지아님 OK 콜라는 Zero...🥤)

그러고나서 코드를 치는데 코드 자체는 생각보다 덜 복잡해서ㅋㅋㅋ 마음이 복잡해졌다😂

// Routes.js
// 라우터 이동 코드
<Route exact path="/product/:num" component={ProductDetails} />
// 각 카드에 버튼에 들어갈 함수
 goDetail = () => {
    this.props.history.push(`/product/${this.props.num}`);
  };
// props 로 전달받은 데이터 map 돌려서 DetialCard 컴포넌트에 전달하는 코드
const detailList =
      this.state.list &&
      this.state.list.map((post, idx) => (
        <DetailCard
          key={idx}
          id={post.id}     // 중요한 id 값
          name={post.name}
          price={post.price}
          image={post.imgage_url[0].imgage_url}
          subject={post.subject[0].subject}
          description={post.theme[0].description}
          specLists={post.item_info}
          color={post.colors}
        />
      ));

제품 디테일 페이지에서 컬러 선택후 Add to cart 버튼 눌렀을 때 서버로 데이터를 보내주는 코드

이 부분은 내가 코드를 짰지만 진짜 신기하다고 생각했다 선택한 컬러와 제품을 api 에 넣어서 서버로 전송하는 코드인데 진짜 데이터가 보내지고 저장되서 장바구니에 찍히는 걸 보니 뿌듯했다 다시한 번 고유한 id 값의 중요성?을 느꼈다

class DetailCard extends React.Component {
  state = {
    current: 0,
  };
  // order 버튼 눌렀을 때 각 제품의 아이디 값을 인자로 받아와서 fetch 함수 실행
  sendProduct = (id) => {
    const token = localStorage.getItem("Authorization");
    // api 는 config 파일로 변수화 해서 사용하였고 해당 제품의 아이디와 컬러값을 넣어서 데이터를 전송하는 코드이다 
    fetch(`${API}/product/${id}/${this.state.current}/cart`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: token,
      },
      body: JSON.stringify({
        text: "order",
      }),
    }).then((res) => {
      if (res.status === 200) {
        alert("Add to cart");
      } else {
        alert("try again");
      }
    });
  };
  // color 선택 함수 컬러를 선택했을 때 그 컬러의 id 를 state 의 current 값으로 넣어주었다 
  selectColor = (colorID) => {
    this.setState({ current: colorID });
  };

order 페이지에서 서버로 정보 받아오고 다시 보내주는 코드

장바구니에서 order 버튼을 누르면 서버로 장바구니에 담겨있던 정보를 보내고 order 페이지로 이동 -> 서버에서 다시 그 정보를 받아서 뿌려줌 -> 최종 order 버튼을 누르면 서버로 정보를 전달 -> order confirm 페이지로 이동 -> 서버에서 다시 데이터를 받아와서 뿌려줌!

이런 flow 이다 거의 서버랑 탁구 하는 느낌 티키타카🏓

// 페이지가 처음 로드 될 때 디드 마운트로 정보를 받아오고 state 에 저장한다
componentDidMount() {
    const token = localStorage.getItem("Authorization");
    fetch(`${API}/cart`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        Authorization: token,
      },
    })
      .then((res) => res.json())
      .then((res) =>
        this.setState({
          orderList: res.data[0].cart_data,
          userInfo: res.data[0],
          totalP: res.data[0].total_price,
        })
      );
  }
// 최종 order 버튼 클릭시 서버로 데이터를 보낸다
  orderHandler = () => {
    const token = localStorage.getItem("Authorization");
    fetch(`${API}/order`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: token,
      },
      body: JSON.stringify({
        email: this.state.userInfo.email,
        full_name: this.state.userInfo.full_name,
        address: "address",
      }),
    }).then((res) => {
      if (res.status === 200) {
        alert("Order Completed");
        this.props.history.push(`/order/confirm`);
      } else {
        alert("try again");
      }
    });
  };

아쉬운 부분

필요한 페이지 부족

처음 주제 아이디어를 낼 때 아무래도 계속 디자인을 하던 사람이라 거의 디자인 중심으로 주제를 찾았다ㅠ 그래서 그런지 막상 시작하려고 페이지를 뜯어보니 비츠 페이지가 생각보다 페이지 수가 적었다 심지어 로그인 장바구니 등은 애플 사이트로 넘어가버리고... (팀원들에게 미안해지는 부분..)

그래서 우리는 가능한 한 모든 페이지를 구현기로 했다 원래는 없는 로그인, 회원가입, 장바구니, 주문 페이지를 추가하였다 로그인과 회원가입, 장바구니는 Asoap 페이지의 UI 를 가져와서 작업했고 구매 페이지는 Lush 에서 UI 를 가져왔다 이렇게 기획과 작업을 병행하다보니 프로젝트 시작 1주일은 UI에 잡혀있었다

하지만 우리 팀원들이 속도도 빠르고 시간 투자도 정말 많이 해서(맨날 12시 넘어서까지 남아있었다👽) 거의 일주일 안에 페이지 UI 가 끝나고 기능에 들어갈 수 있었다👏👏👏👏

데이터 소통

  • 백앤드와 같이 작업하는 것은 인스타그램 클론 이후로 처음이라 데이터를 받아오는 것도 어떻게 백앤드에게 필요한 데이터에 대해 논의한는지도 잘 몰랐다 그래서 그부분이 조금 미안했다 우리팀 백앤드분은 워낙 잘하셔서 요청한 데이터는 도라에몽 처럼 척척 내어주셨는데 처음에 필요한 데이터를 정확하게 말하지 못해서 중간에 수정하는 일이 좀 있었다 좀 더 꼼꼼히 확인했어야 했는데 그 부분이 좀 아쉬웠다 2차때는 좀 더 신경써서 작업해야겠다는 생각이 들었다
  • 그리고 오하이오...✈️서버가 오하이오에 있어서 다시 서울에서 만드는 대참사가 있었다ㅋㅋㅋ 심지어 발표 2일 전 있었던 일✈️

데모영상
https://youtu.be/SYwS8Oii69w

0개의 댓글