[Project] WCF SHOP 회고록

SuJeong·2022년 12월 21일
1

Project

목록 보기
2/4
post-thumbnail

대장정의 1차 프로젝트가 끝이났따✌️
다사다난하고 우당탕탕이었지만 좋은 팀원들과 함께 기획부터 회고까지 무사히 끝마칠 수 있었다 :)

🥰 좋았던 점(Liked)

우리 팀원 분위기가 너무 좋았다.... 진짜 여기서 2달전에 만났던 사람들 맞나 싶을정도로 프로젝트 하는동안 같이 울고 웃었던 기억들이 많다..!
나의 리드하에 팀원들의 코로나 격리로 원격으로 소통하고 애자일 스크럼에 맞게 1주단위의 Sprint로 팀 프로젝트를 진행했다.
Notion을 통해 daily standup metting기록과 Plan을 계획했고 Trello를 통해 전반적인 스프린트 개발일정을 공유하여 진척도를 조절하였다.

Scrum Process
애자일방법론에 따라 Weekly Sprint로 총 2번의 Sprint를 진행하였다.

Planning Meeting
하나의 Sprint가 시작되는 매주 월요일마다 Trello를 사용하여 해당 Sprint때의 목표를 설정하였다.
Daily Standup Meeting
아침 10시마다 전날의 개발진척도와 오늘의 목표, blocker들을 공유하였다.
Retrospective Meeting
최종발표 날 두번의 Sprint동안의 KPT회고를 통한 회고를 진행하였다.

Gitbook


gitbook을 통해 백엔드와의 소통도 원만하게 진행되었다.
백엔드, 프론트엔드 페이지 담당자끼리 API Data 형식이나 무엇을 넘겨줄건지 고민하면서 미리 협의해두었다.
그럼에도 중간에 필요하거나 수정할 부분이 생기면 그때그때 소통하여 조율하여 개발을 진행하면서 큰 변화가 없이 진행할 수 있었다.


✏️ 배웠던 점(Learned)

탭 별 조건부 렌더링

리스트페이지에서 처음에는 브랜드를 클릭했을 경우 Brand 컴포넌트를 return하게끔 switch case로 구현했었다. 멘토님의 피드백으로 객체를 사용해서 클릭한 탭의 id를 저장해서 해당하는 id의 content로 등록되어있는 컴포넌트를 불러오게끔 조건부 렌더링을 리팩토링 하였다.

👇 ProductList.js

const TABS = [
    {
      id: 0,
      title: '브랜드',
      content: <Brand />,
    },
    {
      id: 1,
      title: '가격',
      content: <Price />,
    },
    {
      id: 2,
      title: '사이즈',
      content: <Size />,
    },
  ];

            <div className="left-filter">
              <ul className="filter-list">
                {TABS.map(filter => {
                  const isCurrent = currentTab === filter.id;
                  return (
                    <li key={filter.id}>
                      <button
                        onClick={() =>
                          setCurrentTab(isCurrent ? '' : filter.id)
                        }
                        className={isCurrent ? 'current' : ''}
                      >
                        {filter.title}
                      </button>
                    </li>
                  );
                })}
              </ul>
            </div>
          {TABS.find(({ id }) => id === currentTab)?.content}
  • TAB객체를 활용하여 id, content를 매칭하여 조건부 렌더링 구현
  • map을 돌려 title을 불러와 필터링 버튼을 생성하고 click시 현재 tab의 id값을 설정한다.
  • 현재 tab의 id를 TAB객체에서 찾아 해당하는 id의 content인 컴포넌트를 불러온다.
  • 옵셔널체이닝을 통해 TAB객체에서 현재 tab의 id가 없는 경우, 즉 tab이 다 닫혀있는 경우 content를 불러올 수 없기 때문에 예외처리를 해주었다.
    ** 현재 열려있는 tab을 한번 더 click시 현재 tab의 id와 TAB객체의 id가 같은 지 판별하여 현재 tab의 id를 reset하여 toggle기능 구현

querystring

브랜드, 가격, 사이즈의 정보를 state에 저장하였더니 새로고침이나 재접속 시 체크한 필터값이 날아가는 이슈가 발생했다.
검색 결과 상태로 저장하지 않고 url에 저장하는 querystring으로 리팩토링 하였다 !

👇 Brand.js

const [searchParams, setSearchParams] = useSearchParams();

  //TODO: 브랜드 검색기능
  const searchBrand = e => {
    const filterBrand = BRAND.filter(brand =>
      brand.name.includes(e.target.value)
    );
    setFilterList(filterBrand);
  };

  //TODO: querystring 생성
  const prevQuery = searchParams.getAll('brandId');
  const handleCheckbox = e => {
    const { checked, value } = e.target;
    if (checked) {
      searchParams.append('brandId', value);
      setSearchParams(searchParams);
    } else {
      searchParams.delete('brandId');
      prevQuery
        .filter(query => query !== value)
        .forEach(query => searchParams.append('brandId', query));
      setSearchParams(searchParams);
    }
  };
  • checkbox에 check가 되었으면 searchparams에 append()를 통해 추가한다.
  • check가 해제되었으면 해당 param key의 value들을 모두 삭제하고 이전에 모든 value들을 담아놓은 prevQuery변수에서 e.target.value인 것들을 제외한 value들을 다시 searchparams에 담는다.

path parameter를 통한 동적라우팅


상세페이지를 하나씩 다 만들어야하나 고민하다가 동적라우팅을 알게 되었다!

👇 Product.js

    <li>
      <Link to={`/product-detail/${id}`}>
        <img src={imgurl} alt="상품이미지" />
        <div className="like" />
        <div className="info">
          <span className="brand">{brand}</span>
          <span className="name">{name}</span>
          <span className="price">{Number(price).toLocaleString()}</span>
          <span className="heart">
            <i className="fa-regular fa-heart" />
            <em>999+</em>
          </span>
        </div>
      </Link>
    </li>

👇 Router.js

    <BrowserRouter>
      <Nav />
      <Routes>
        <Route path="/" element={<Main />} />
        <Route path="/product-detail/:productId" element={<ProductDetail />} />
        <Route path="/product-list" element={<ProductList />} />
      </Routes>
      <Footer />
    </BrowserRouter>
  • Router.js의 path prop에 :productId로 이름을 지정한다.
  • 상품리스트페이지에서 어떠한 품목을 선택해도 상품 상세페이지로 이동하게된다.

💡 더 자세한 코드들이 궁금하시다면?


🥲 부족했던 점(Leaked)

첫 프로젝트였던만큼 부족한 점이 많을 수 밖에 없었던 것 같다.

기획의 부실

  • 프로젝트를 본격적으로 들어가기 전 기획회의를 시작할 때 이것저것 하고 싶은게 너무 많았다.
    이것만큼은 꼭 하자던 동기들의 옷 데이터를 수집하여 이미지를 대체하자는 기획빼고는 다른건 실행할 수 없었다...

프론트엔드끼리의 부실

  • 컨벤션이 잘 지켜지지 못했다. 나만 잘한다고 되는게 아니었고 다른 페이지의 부분을 commit만으로 무엇을 진행했는지 파악하면 소스를 다 뒤집어까지 않았어도 될텐데..아쉽다.
  • 결제 페이지를 해내지 못했다. 장바구니 기능이 발표 당일 새벽 끝마쳐지지 못해서 결제 페이지를 만들었지만 사용할 수 없었다.

백엔드끼리의 부실

  • 백엔드 개발자 인원이 2명이었는데 한 명이 일신상의 이유(?)로 팀원 1명이 독박이 씌워져버린 상황이 되었다...그러한 상황은 오롯이 프론트엔드의 피해로까지 이어졌고 시간과 경험이 절대적으로 부족하였다..

시간의 부실 !!!!
역시 데드라인은 죽음뿐...버릴건 버리고 일정관리의 중요성을 느꼈다..


🙏 바라는 점(Longed for)

Trello 티켓을 세분화 하여 진행하기

  • 페이지를 하나의 티켓으로 했더니 Done 카테고리에 위치해있는게 아무것도 없어서 성취감도 없고 진척도 파악에도 어려움을 겪었다. 한 페이지의 조금 더 세분화하여 진행해보자.
    프론트엔드끼리 지식 및 인사이트 공유하기
  • 그래도 우리 같은 프론트엔드 개발자끼리 사이트도 공유하고 이럴 땐 이런 기술을 사용하면 더 좋을 것 같다라는 PR리뷰도 적극적으로 해보자.

📌 느낀 점

코드를 지울 줄 아는 개발자가 되자..!
이번에 리팩토링을 하면서 다 지우고 처음부터 다시 짠 코드도 있었고 부분적으로 다시 수정한 코드도 있었다. 내가 짠 코드가 정답이 아니다. 물론 코드에 정답은 없다고는 하지만 내가 짠 코드에 고집을 부려서는 안된다.
리팩토링이던 협업 내에 컨벤션이 수정되었던 내 코드에 집착하지말고 과감히 지울 줄 아는 개발자가 되어야겠다고 생각했다.

profile
Front-End Developer

0개의 댓글