티스토리 뷰

회고

[팀프로젝트] 프로코더스 회고

2021bong 2022. 9. 16. 17:21

✨프로젝트 소개

프로스펙스 모티프 프로젝트

목적

  • React 활용 능력 향상
  • Styled-Components라는 새로운 기술 사용
  • 이벤트에 따른 애니메이션 구현
  • 예시를 보고 화면을 구현
  • 이커머스 사이트 구조에 대한 이해
  • 서버와 통신 경험
  • 팀프로젝트 경험

 

진행 기간

2022.08.29 - 09.08 (2주)

GitHub repo

프론트

 


 

사용된 기술

  • JavaScript
  • React
  • Vite
  • Styled-components
  • Git, GitHub

CRA보다 서버 실행 속도가 빠른 Vite를 이용해 개발 환경을 구축했으며 JavaScript와 JavaScript기반 라이브러리 React로 프로젝트를 진행했다. 별도로 css파일을 관리하지 않아도 되고 네스팅이 가능하며 클래스명이 겹쳐 레이아웃이 깨질 염려가 적은 Styled-components로 스타일링했다. 협업을 위해 Git과 GitHub을 사용했다.

 

프로젝트 구조

├── .gitignore
├── .github
│   └── pull_request_template.md
├── .prettierrc
├── index.html
├── package-lock.json
├── package.json
├── public
│   ├── data
│   │   └── 목데이터들
│   └── images
│       ├── archive
│       │   └── 이미지 파일들
│       ├── logo-black.svg
│       ├── logo-white.svg
│       └── nav
│           ├── icon
│           │   └── 아이콘들
│           └── img
│               └── 이미지 파일들
├── README.md
├── src
│   ├── App.jsx
│   ├── components
│   │   ├── Footer.jsx
│   │   ├── LoginModal.jsx
│   │   ├── Nav.jsx
│   │   ├── Skeleton
│   │   │   └── 로딩 skeleton들
│   │   ├── Spinner.jsx
│   │   └── TopButton.jsx
│   ├── hooks
│   │   ├── useInfiniteSwiper.js
│   │   ├── useScroll.js
│   │   └── useSwiper.js
│   ├── main.jsx
│   ├── pages
│   │   ├── Shop
│   │   │   ├── Shoes
│   │   │   │   ├── AllShoes.jsx
│   │   │   │   └── sections
│   │   │   │       ├── FilterModal.jsx
│   │   │   │       ├── Item.jsx
│   │   │   │       ├── ItemBox.jsx
│   │   │   │       ├── MdPick.jsx
│   │   │   │       └── Nomination.jsx
│   │   │   ├── ShopPage.jsx
│   │   │   └── sections
│   │   │       ├── FirstSection.jsx
│   │   │       ├── FourthSection.jsx
│   │   │       ├── SecondSection.jsx
│   │   │       └── ThirdSection.jsx
│   │   ├── archive
│   │   │   └── Archive.jsx
│   │   ├── cart
│   │   │   ├── Cart.jsx
│   │   │   └── CartSkeleton.jsx
│   │   ├── event
│   │   │   ├── CardContent.jsx
│   │   │   ├── Event.jsx
│   │   │   └── EventCard.jsx
│   │   ├── main
│   │   │   ├── Header.jsx
│   │   │   ├── Main.jsx
│   │   │   └── Sections
│   │   │       ├── FifthSection.jsx
│   │   │       ├── FirstSection.jsx
│   │   │       ├── FourthSection.jsx
│   │   │       ├── Item.jsx
│   │   │       ├── SecondSection.jsx
│   │   │       └── ThirdSection.jsx
│   │   ├── product
│   │   │   ├── Product.jsx
│   │   │   └── Sections
│   │   │       ├── AccordionCard.jsx
│   │   │       ├── AiFilter.jsx
│   │   │       ├── ProductDetail.jsx
│   │   │       └── ProductOption.jsx
│   │   ├── search
│   │   │   └── Search.jsx
│   │   ├── signUp
│   │   │   └── SignUp.jsx
│   │   ├── smartfit
│   │   │   └── SmartFit.jsx
│   │   └── store
│   │       ├── Map.jsx
│   │       ├── Store.jsx
│   │       └── StoreInfo.jsx
│   └── styles
│       ├── GlobalStyle.jsx
│       └── theme.js
└── vite.config.js

 

 

 


 

역할

프론트엔드 3명의 팀원 중 1명으로 Event, Archive, Store, Smart fit 페이지 구현과 검색 기능을 담당했다.

 

Event

프로스펙스의 이벤트 정보들을 확인할 수 있는 페이지.

 

- fetch를 통해 Event 페이지의 목록을 받아와 UI를 구현

- 카테고리별로 목록이 다르게 보이도록 구현

- 토글 UI 구현

- 로딩 스켈레톤 구현

 


Archive

주제에 따른 룩북을 슬라이드로 보여주는 페이지. 슬라이드 구현을 해본 경험이 없어서 라이브러리를 사용하지 않고 직접 구현했다. 라이브러리를 사용하기 전에 구현 요소의 로직이 어떻게 되는지 한번쯤은 보고 넘어가야 한다고 생각했기 때문이다. 다른 형태의 슬라이드도 도전할 수 있을 것 같은 자신감이 생겼다. 로딩 스켈레톤도 구현했는데 로딩이 빨라서 잘 보이지가 않았다.

 

- 룩북 슬라이드 구현

- 토글 UI 구현 및 기능 구현

 


Store

오프라인 매장 정보들을 보여주는 페이지.

  • 변경한 점 : Sponsorship -> Store
    • Sponsorship페이지가 간단한 마크업뿐이라서 지도 API를 이용해볼 수 있는 Store페이지를 대신 넣기로 했다.

처음에는 매장 정보를 프론트에서 30여 개 정도만 보여주려고 했는데 중후반에 300여 개의 모든 매장 정보를 보여주는 걸로 변경하게 되어서 데이터를 정리한 sql 파일을 백엔드 팀원에게 보냈다. 카카오 맵 API 공식문서는 바닐라 자바스크립트로 되어있어서 React 버전의 코드를 찾느라 계획한 시간보다 오래 걸렸다. 사용하는 state의 개수에 대해서도 고민해보게 되었다.

 

- 매장 리스트 데이터 sql 파일로 정리

- 서버에서 데이터를 받아와 매장 타입별로 리스트를 보여주도록 구현

- 카카오 맵 API를 이용한 지도

- 매장 정보를 누르면 매장의 상세 지도가 보이도록 구현

- 로딩 스켈레톤 구현

 


Smart fit

프로스펙스에서 제공하는 맞춤 제작 서비스에 대한 안내 페이지.

GO를 누르면 로그인 모달이 뜨면서 로그인을 할 수 있도록 되어있어서 팀원이 제작해둔 컴포넌트를 이용해 현재 페이지에서도 로그인이 가능하도록 구현했다. 로그인 중일 때는 로그인 모달이 뜨지 않고 로그인 안내 모달을 띄우도록 했다.

 

- UI 구현

- GO를 눌렀을 때 로그인이 가능하도록 구현

- 로그인 중일 때 로그인 안내 모달 구현

 

 


검색 기능 + 탑버튼

검색을 했을 때 검색 키워드와 일치하는 상품이 검색되도록 했다.

검색했을 때 검색 결과물들이 보이는 Search 컴포넌트를 별도로 만들었다. 검색 기능이 다른 팀원들이 만든 컴포넌트를 재사용하거나 팀원의 코드에 추가해야 하는 부분이 있어서 다른 사람의 코드를 보는 능력이 조금 향상된 것 같다.

 

- 검색 키워드를 서버로 전달하고 그 결과를 화면에 보이도록 구현

- 검색 결과가 없을 때 검색 결과 없음이 보이도록 구현

- 인기 검색어 검색 기능

 

 

 


🎶협업

처음으로 팀 프로젝트를 진행했는데 새롭고 재밌는 경험이었고 많은 것을 배울 수 있었다. 그동안 fetch를 목데이터로만 하다가 직접 서버와 통신하니까 너무 신기하고 재미있었다.

서로 역할을 나누고, 일정을 계획하고, 오해를 해결하며 개발 조직에서 필요한 소통능력에 대해 깨닫는 경험이었다. 처음으로 프론트와 백이 협업하여 진행한 프로젝트여서 프론트엔드와 백엔드간에 어떻게 소통해야 하고 서로 어떤 것들을 미리 알려줘야 하는지에 대해서 배울 수 있었다. DB 모델링은 백엔드의 일이라고 생각했으나 프론트에서 그 데이터들을 사용하기 때문에 함께 참여하면 더 좋은 데이터 테이블 구조가 나올 수 있다는 걸 느꼈다. 또 협업할 때 프론트에서는 컨벤션을 세세하게 정해서 진행하는 게 좋다는 배움을 얻었다.

git 기능들에 익숙해질 수 있었던 시간이었다. 특히 merge와 confilct 해결 능력이 향상됐다. 이전에는 merge 할 때 충돌이 나면 어떻게 해결해야 할지 막막하기만 했었는데 프로젝트를 진행하면서 발생한 충돌들을 해결해나가다 보니 이제는 조금 능숙하게 충돌을 해결할 수 있게 되었다.

 

🥲아쉬운 점

처음에 컨벤션과 사용하는 라이브러리들을 세세하게 정하지 않고 진행했더니 코드나 커밋이 형식이 달라서 통일되지 않은 점이 아쉬웠다. import 할 때도 순서를 정하지 않아서 정리를 하려고 하면 충돌이 나서 정리하지 못해 아쉬웠다.

PR을 보내고 merge를 매우 자주 해서 다른 팀에 비해서 PR내역이 많았는데 PR을 보낼 때 제목 컨벤션이나 라벨을 신경 쓰지 못해 깔끔하게 정리하지 못했다. 다음엔 여기까지 신경 써야겠다.

계획을 세울 때 반응형까지 하고 싶었는데 시간이 부족해 구현하지 못했다. 구현하는데 예상보다 시간이 오래 걸리기도 해서 시간관리를 더 타이트하게 해야겠다고 생각했다.

 

 


 

✅기록하고 싶은 코드

구현을 위해 고군분투한 Map 컴포넌트를 기록해두고 싶다. 매장 정보를 보여주는 기능 구현은 하루정도 걸렸는데 지도 띄우느라 시간을 많이 썼다. 공식문서는 Vanilla JS로 되어있어서 React에서 사용할 수 있도록 검색해보고 적용하느라 긴 시간을 들였다. kakao를 비롯해 옵션, 인포윈도우나 메소드들이 어떻게 작동하는지에 대해 알고 싶었는데 찾지 못해서 적용해보며 대략적으로 파악하느라 오래 걸렸다. 다음에 또 지도를 구현할 일이 생긴다면 참고하기 위해 기록하고 싶다. 카카오맵 API를 써야 하는 동기들 중에는 제일 빨리 끝냈는데 참고할 수 있도록 공유할 수 있어서 뿌듯했다.

import React, { useEffect } from 'react';
import styled from 'styled-components';

const { kakao } = window;

const Main = styled.div`
  width: 50%;
  height: 100%;
  margin-right: 15px;
  z-index: -1;

  .mapDetail {
    width: 100%;
    height: 100%;
    background-color: ${(props) => props.theme.colors.disabledTitle};
  }
`;

const Map = ({ list }) => {
  useEffect(() => {
    if (list && list.length === 1) {
      // 마커 1개 일 때
      const container = document.getElementById('map');
      const markerPosition = new kakao.maps.LatLng(list[0].lat, list[0].lng);
      const marker = new kakao.maps.Marker({
        position: markerPosition,
        title: list[0].name,
      });
      const options = {
        center: new kakao.maps.LatLng(list[0].lat, list[0].lng),
        marker: marker,
        level: 3,
      };
      const kakaoMap = new kakao.maps.Map(container, options);

      const iwPosition = new kakao.maps.LatLng(list[0].lat, list[0].lng);

      const iwContent =
        list[0].name.length >= 10
          ? list[0].name.length >= 12
            ? `<div style="width: 220px; margin: 0 auto; padding: 10px; border-radius: 50%; font-weight: 700;">${list[0].name}</div>`
            : `<div style="width: 180px; margin: 0 auto; padding: 10px; border-radius: 50%; font-weight: 700;">${list[0].name}</div>`
          : `<div style="margin: 0 auto; padding: 10px; border-radius: 50%; font-weight: 700;">${list[0].name}</div>`;

      const infowindow = new kakao.maps.InfoWindow({
        position: iwPosition,
        content: iwContent,
      });

      marker.setMap(kakaoMap);
      infowindow.open(kakaoMap, marker);
    } else {
      // 마커 여러개 일 때
      const container = document.getElementById('map');
      const options = {
        center: new kakao.maps.LatLng(35.624915, 127.151226),
        level: 13,
      };
      const kakaoMap = new kakao.maps.Map(container, options);

      list &&
        list.forEach((el) => {
          new kakao.maps.Marker({
            map: kakaoMap,
            position: new kakao.maps.LatLng(el.lat, el.lng),
            title: el.name,
          });
        });
    }
  }, [list]);

  return (
    <Main>
      <div id='map' className='mapDetail'></div>
    </Main>
  );
};

export default Map;
728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함