라로슈포제 Web Cloning Project

i01029407043·2일 전
1

1stProject

목록 보기
3/4
post-thumbnail

ㅤ프로젝트 소개ㅤ

개발 인원 및 기간
개발 기간 : 2020.07.20 - 2020.07.31
개발 인원 : FrontEnd : [ 이지윤, 박민규, 최태희 ] & BackEnd : [ 안솔, 한승엽 ]

적용 기술 (FrontEnd)
JavaScript(ES6)
Sass
React.js (CRA)
AWS(EC2)

Library
Slick & Accordion

구현 기능 (FrontEnd)
로그인 / 로그아웃 및 회원가입 & 찜하기 / 장바구니

ㅤ내가 구현한 부분ㅤ

Pages →

PagesDescription
메인 Main- Slick Library 이용 Slides 구현
상품 목록 ProductList- 백엔드 데이터를 페이지에 Render
- Accordion Library 사용 ProductCategory SideBar 구현
장바구니 Cart- 백엔드 유저 정보 확인하여 장바구니 목록 Render
- forEachMethod로 모든 ItemCard의 총 구매금액과 할인가 계산
찜하기 LikeItemList- 백엔드 유저 정보 확인하여 찜 목록 Render
- Accordion Library 사용 MyPage SideBar 구현

재사용한 Components →

ComponentsDescription
Footer- 모든 페이지에 재사용
FloatBar- 장바구니 / 찜 목록 아이콘 클릭 시 페이지 이동
- 실제 서버에 저장된 제품 목록 바탕으로 아이콘 위에 제품 수량 표시
ItemBox- Main, ProductList, LikeItemList 페이지에서 재사용되는 Component
- 상품 이미지, 해시태그, 상품 라인 및 이름, 가격, 할인정보, 증정 상품 유무 등 표시
- 동적 라우팅을 이용하여 각 ItemBox의 상세보기 클릭 시 상세 페이지 전환
- 상세보기 & 장바구니 (Hover 시 표시) , 찜하기 버튼
- 찜하기 버튼 누를 시 / 장바구니 버튼 누를 시 각각 user 정보와 제품정보를 백엔드로 전달 (POST)
- 이렇게 전달한 데이터가 LikeItemList / Cart Page에 render (GET)
Slides- Slick Library : Arrow & dots Custom
- Main, FloatBar에 사용
Modal- Modal Library 사용하지 않음
- 장바구니, 찜하기 클릭 시 user에게 alert 목적으로 실행

ㅤ기억하고 싶은 코드ㅤ

ㅤCheckList1ㅤㅤfetch API 호출

componentDidMount()에서 바로 fetch를 실행하지 않고 API를 호출하는 showItemList 함수를 따로 만들어둔 이유?

[ItemList.js]
  componentDidMount() {
    this.showItemList();
  }
  showItemList = () => {
    fetch(allAPI)
      .then((res) => res.json())
      .then((res) => {
        this.setState({
          itemTable: res.data,
        });
      });
  };

componentDidUpdate() 등 다른 곳에서 함수 재사용 가능성을 열어두기

ㅤCheckList2ㅤㅤ동적 Routing : path

RenderDescription (FloatBar.js)
장바구니 & 찜하기 버튼을 누르면 각각'/cart' & '/likeitemlist' path로 이동한다.
/path는 Routes.js에서 미리 지정:
ex) <Route exact path="/cart" component={Cart} />
[Routes.js]
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Cart from "./Pages/Cart/Cart";
import LikeItemList from "./Pages/LikeItemList/LikeItemList";
export default class Routes extends Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/cart" component={Cart} />
          <Route exact path="/likeitemlist" component={LikeItemList} />
        </Switch>
      </Router>
    );
  }
}

ㅤCheckList3ㅤㅤmap ⇢ jsx

[ItemList.js]
<ul className="itemTable">
    {itemTable.map((item, idx) => {
      ...
      return (
  	<ItemBox
             key={idx}
             item={item}
	   ...
           />
         );
       })}
</ul>
  1. ItemTable : fetch함수로 API 호출하여 전달받은 데이터를 JavaScript 형식으로 변환한 배열 형태의 자료
  2. ItemBox : 각각의 데이터를 전달받아 화면에 렌더링할 childComponent

ㅤCheckList4ㅤㅤchildComponent → parentComponent

기억하고 싶고 기억해야 하는 코드!
childComponent에서 parentComponent로 state를 전달하는 게 아니라
parentComponent의 state를 변경하는 함수를 childComponent에서 호출 !

[CartItems.js]

import ItemCard from "./ItemCard"; // childComponent
import { userAPI, cartAPI } from "../../config";
import "./CartItems.scss";
class CartItems extends Component {
  constructor() {
    super();
    this.state = {
      CartItemTable: [], // 데이터
      value: 1,		 // childComponent로 전달할 state
    };
  }
/*	당연히 state를 변경할 함수도 부모 Component에	   */
  minusClicked = () => {
    if (this.state.value > 1) {
      this.setState({
        value: this.state.value - 1,
      });
    }
  };
  plusClicked = () => {
    if (this.state.value < 5) {
      this.setState({
        value: this.state.value + 1,
      });
    }
  };
.
.
.
{CartItemTable.map((item, idx) => {
            ...
            return (
              <ItemCard
                item={item}
                id={idx}
                ...
        >>>>>   value={this.state.value}   <<<<<
              />
            );
          })}

[ItemCard.js]

const { ...
  minusClicked,
  plusClicked,
  value,
  ... } = this.props;
.
.
.  
<div className="count">
  <button type="button" onClick={minusClicked}>
  					 - </button>
  <input readOnly value={value} />
  <button type="button" onClick={plusClicked}>
                			+ </button>
</div>

ㅤCodeKata ?ㅤㅤ데이터 가공해서 이용하기

{
    "data": [
        {
            "product": {
                "id": 1,
                "product_line": "에빠끌라",
                "name": "듀오[+] 에센스 트리플 세트",
                "sale_price": "67500.00",
                "price": "75000.00",
                "hash_tag": "#트러블케어에센스,#유럽NO1에센스,#미백에센스,#다크스팟케어,#에빠끌라"
            },
            "images": [
                "'/upload/product/main/2020/07/20200715_1348021_162.png'",
                " '/upload/product/main/2020/07/20200715_1348022_163.png'",
                " '/upload/product/main/2020/07/20200715_1350046_164.png'",
                " '/upload/product/main/2020/07/20200715_1351005_165.png'",
                " '/upload/product/main/2020/07/20200715_1351035_166.png'",
                " ''"
            ],
            "best": true,
            "new": false,
            "gift": false,
            "sale": true
        }

전달받은 데이터. 이 데이터를 활용해서 제품 리스트를 이렇게 보여줘야 한다. 음. 이거 하려고 CodeKata 했구나 싶었다.

[ItemList.js] : API를 호출하는 위치 → ItemBox로 데이터 전달
<ul className="itemTable">
  {itemTable.map((item) => {
  const product = item.product;
  const hash = product.hash_tag.split(",");
   // string으로 전달된 값을 배열로 전환
  return (
    <ItemBox
       ...
       item={item}
       hash={hash}
       price={product.price}
       discountPrice={product.sale_price}
       ...
    /> 
  ); })}
</ul>
[ItemBox.js]
const { hash, price, discountPrice } = this.props;
const { product, images } = this.props.item;
  // data 객체 안의 객체 (product) & 배열 (images)을 이용하기 위한 구조분해 할당
const priceNum = Number(price);
const discountPriceNum = Number(discountPrice);
  // string 형태로 전달된 값을 number로 활용하기 위해 변경한 데이터 타입을 변수에 할당
.
.
.
 <img alt="" src={`https://www.larocheposay.co.kr${images[0].slice(1, images[0].length - 1)}`}/>  
  /* images 배열의 첫번째 요소만 이용하여 url 주소 만들기 : 
     images의 index[0] 요소에서 
     앞뒤에 붙은 필요없는 string을 slice로 제외하고 기존 url과 병합 */
 <p className="itemHash">{hash[0]}</p>
  // ItemListComponent에서 가공하여 전달한 hash 배열의 첫번째 요소만 이용하기  

+CheckList

✔︎ AWS ( 링크 추가 예정! )

ㅤ프로젝트 후기ㅤ

#ProjectManager #개발 6주차 #협업 #좋은개발자

나는 극단적인 내향인이다. 3명 이상 모이는 자리는 부담스럽고 쉽게 지친다. 그런 모임에는 어느 정도 마음의 준비를 하고 나간다. 결코 남을 리드하는 편이 아니고, 조용히 앉아있다 조용히 집에 가고 싶다. 그런데 PM이라니? 물론 이 프로젝트의 PM이 대단한 직책이거나 PM에게 막중한 임무가 주어지는 건 아니다. 팀 구성원 중 누가 맡아도 크게 달라졌을 것 같지는 않다. 하지만 나는 이 자리가 굉장히 낯설었고 새로운 도전으로 느껴졌다. 예전이었다면 누군가에게 책임을 미뤘을 것이다. 비자발적이었다 해도 그것을 받아들인 것은 늘 도피를 택했던 나에게 그동안 작은 변화가 생겼기 때문이라고 생각한다.

비록 성적에 맞춰 진학한 대학이었지만 나는 전공에 진심이었으므로 미래를 그리는 데 큰 어려움이 없었다. 그래서 다른 분야는 쳐다볼 생각조차 하지 않고 전공을 살려 취업을 했다. 학업 포함 약 10년을 같은 분야만 팠다. 그럭저럭 살만은 했으니 현실에 안주했다. 업무강도도 나쁘지 않았고 밤샘은 커녕 18시 00분이 되자마자 회사를 나설 수 있었다. 일을 그만 둔 것은 내 인생 역대급 변화이자 도전이었다. 개발을 배울 거라고 말하면 다들 만류했다. 서른을 앞둔 여자가 다니기 좋은 직장이라고, 그만두지 말고 버티라고 충고인지 조언인지 악마의 꾐인지 모를 소리를 세 달 쯤 듣고 퇴사했다.

head/body도 모르는 채로 시작해 4주 간 HTML, CSS, JavaScript와 React를 배웠다. 그리고 이제 막 기적처럼 마무리된 2주 프로젝트 후기를 쓰고 있다. 아직 개발자라고 부르기도 민망한 개발자 지망생이지만 나는 지금 즐겁다. 살면서 무언가 이렇게 열심히, 그리고 적극적으로 해본 적이 없다. 밤을 새는데도 못해먹겠다 때려치고 싶다는 생각이 들지 않는다. 힘들고 짜증나도 얼른 해결해내고 새로운 걸 해보고 싶다. 배우는 건 늘 어렵지만 도망가고 싶지 않다. 그래서 해보겠다 했다. 언제 이런 걸 해보겠어, 앞으로 10년도 더 걸릴 수 있는데 지금 해보자. 라는 생각으로.

프로젝트를 마친 지금, 되돌아보면 내 책무는 크지 않았는데 스트레스와 성취감은 컸다. 사실 PM으로서 뭘 특별히 잘한 것 같지는 않다. 함께 했던 세심한 민규님이 내가 혼자 힘들 것 같다고 프로젝트 기간 내내 여러모로 굉장히 노력하셨고 솔님께는 어쩌면 무리한 API 구현을 부탁드렸는데 밤까지 새가면서 많이 애써주셨다. 발표일 전 이틀 간 함께 밤샘코딩 하며 만들어낸 결과물이 시작할 때 우려했던 것보다 훨씬 완성도 있어서 스스로도 놀랐다. 2주간 받았던 고통이 사르르 녹는 기분이었다. 그새 과거가 미화된 것인지 어떻게 보면 내가 할 수 있는 선에서 100% 이상을 얻은 것 같기도 하다.

모든 일에 심드렁했던 나를 아는 친구들은 지금의 내가 낯설다 한다. 사실 나도 내가 낯설다. 하지만 낯섦도 계속되면 언젠가 익숙해진다. 그렇게 익숙한 노력과 시간이 쌓여 개발도 커뮤니케이션도 잘하는 협업하고 싶은 개발자가 될 수 있기를, 6주차 새내기는 꿈꾸고 있다.

0개의 댓글