Skip to content

pre-onboarding-frontend-7-team-3/pre-onboarding-7th-2-2-3

Repository files navigation

원티드 프리온보딩 프론트엔드 3팀 - Assignment #3

목적 : 광고 관리 간편화 서비스 사이트 구축

프로젝트 기간 : 2022년 11월 5일 ~ 2022년 11월 7일

✨주요기능

1. 반응형 Layout

  • 반응형으로 사이드 바를 구현했습니다. useOnClickOutside 훅 사용하여, 목록 버튼으로 사이드 바 연 상태일 경우, 사이드 바 바깥 클릭하면 닫히도록 UX에 신경썼습니다.

2. datePicker

  • KPI 변화를 확인하고자 하는 기간을 설정합니다. 데이터가 존재하는 기간 동안만 영역 선택이 가능하게 해두었습니다.

3. KPIGraph

  • 일간/주간 filter에 따라, 일간에는 선택 기간 시작일의 데이터를 보여주고, 주간 에는 선택 기간의 변화 추세를 보여줍니다. 설정한 filter는 recoil로 관리하여, 페이지 이동 시에도 상태가 유지되게 하였습니다.
  • 좌측 dropbox에서의 선택에 따라, 2가지 지표를 동시에 확인할 수 있습니다.

4. 광고 관리

  • 광고 데이터를 확인 및 수정할 수 있습니다. 마찬가지로 Filter는 recoil로 관리되어, 상태가 유지됩니다.

📖 목차


⌨️ 실행 방법

$ git clone <https://github.com/pre-onboarding-frontend-7-team-3/pre-onboarding-7th-2-1-3.git>
$ npm install
$ npm run start

📃 협업 과정

  1. 우선 노션에서 프로젝트를 페이지 별로 나누고 또 다시 페이지 별로 필요한 컴포넌트를 나열하여 작업을 최대한 세분화 하려고 했습니다.
  2. 본 프로젝트는 동료학습에 최적화된 과정을 찾아가며 진행했습니다. VSC Live Code extension을 활용해서 라이브 코드 리뷰를 진행하고 각자 구현한 코드에 대한 피드백 및 리팩토링 후 페어 프로그래밍 방식으로 Best Practice를 채택했습니다.
  3. 게더타운에 모여 화면공유를 하며 실시간으로 피드백을 주고 받았습니다.

☑️ Best Practice 및 채택 근거

1. barrel 방식의 폴더구조

각 컴포넌트에 해당되는 폴더를 만들고 그 안에 index.js를 만듭니다.

예를 들어 index.js안에 export { default } from './Header' 라고 해두면 VS CODE상에서 해당 파일을 링크하여 열었을때(ctrl를 누른상태로 클릭) vs code 에디터 상단에 Header.jsx 라고 뜹니다.

이는 여러개의 파일을 link로 열었을때 index.jsx 라는 이름이 여러개가 떠서 헷갈리는 상황을 막아줍니다.

https://user-images.githubusercontent.com/65995664/199855960-df2b2f70-3668-4777-8c57-4bedece6d857.gif


2. recoil

저희 팀은 상태 관리를 위해 recoil을 사용했습니다. recoil은 주로 페이지 간 이동 후에도 filter나 날짜 같은 선택사항들의 상태 저장을 위해 사용했습니다.

앱을 실행 하면, atom에서 get요청을 하여 json 데이터를 store에 저장하게 하였고, select를 이용해, component에는 필요한 데이터만 전달 될 수 있도록 하였습니다.

export const adListState = selector({
  key: "adListState",
  get: async ({ get }) => {
    const { data } = await axios.get(`${process.env.REACT_APP_BASE_URL}/ad_list_data`);
    return data.ads;
  },
});

export const adListFilterQuery = selector({
  key: "adListFilterQuery",
  get: ({ get }) => {
    const filter = get(adListFilterState);
    const adList = get(adListState);

    switch (filter) {
      case "전체": {
        return adList;
      }
      case "진행중": {
        return adList.filter((ad) => ad.status === "active");
      }
      case "중단됨": {
        return adList.filter((ad) => ad.status === "ended");
      }
      default:
        throw new Error("Error finding adList");
    }
  },
});

또, Suspense 대신, recoil에서 제공하는 비동기 처리를 돕기 위한 Loadable이라는 객체를 이용해, 데이터를 받아오는 동안, Loading 상태를 처리하였습니다.

const { state, contents } = useRecoilValueLoadable(trendDataQuery);

return (
	<>
      {state === "loading" && (
        <LoadingWrapper>
          <Spinner />
        </LoadingWrapper>
      )}
      {state === "hasValue" && kpiValues && (
        <Container>
          <ROAS value={kpiValues[0]?.roas} exValue={kpiValues[1]?.roas} />
          <Cost value={kpiValues[0]?.cost} exValue={kpiValues[1]?.cost} />
          <Imp value={kpiValues[0]?.imp} exValue={kpiValues[1]?.imp} />
          <Click value={kpiValues[0]?.click} exValue={kpiValues[1]?.click} />
          <Conv value={kpiValues[0]?.conv} exValue={kpiValues[1]?.conv} />
          <Revenue value={kpiValues[0]?.revenue} exValue={kpiValues[0]?.revenue} />
        </Container>
      )}
	</>);

3. api함수를 oop 캡슐화

황연욱 멘토님이 알려주신 oop를 이용해서 이번에 api 함수에 적용해보았습니다.

그 결과 관심분리가 잘 적용되어 재사용성이 올라갔습니다.

import { AdvertisementService } from "apis/AdvertisementService";
import { AxiosHttpClient } from "apis/request";
const httpClient = new AxiosHttpClient(process.env.REACT_APP_BASE_URL);
const advertisementService = new AdvertisementService(httpClient);
export { advertisementService };

apis 폴더에 잘 정리해 두었으니 참고바랍니다. /src/apis


4. lodash를 통한 반응형 nav

  1. 정해진 범위 안쪽으로 화면이 축소되는 상황에서 사이드바가 숨겨지도록 처리 했습니다.
  2. 화면이 축소되어 사이드바가 숨겨지면 햄버거 버튼을 통해 숨겨진 사이드바를 열 수 있습니다.
  3. useOnClickOutside hook을 통해, sideNav 영역밖을 클릭하면 sideNav가 닫히도록 처리했습니다.
  4. 화면 사이즈 변화를 디바운스로 처리해 작은 화면에 적응된 사이드바 설정이 변화한 화면크기에 반응할 수 있도록 처리 했습니다.

const navRef = useRef(null);
useOnClickOutside(navRef, () => {
setIsToggled(false);
});
const handleResize = _.debounce(() => {
if (window.innerWidth <= 768) {
setIsToggled(false);
}
}, 200);
useEffect(() => {
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, [handleResize]);


🔒 팀 코드 컨벤션

  • git commit message 컨벤션
커밋명 내용
feat 파일, 폴더, 새로운 기능 추가
fix 버그 수정
docs 제품 코드 수정 없음
style 코드 형식, 정렬, 주석 등의 변경
refactor 코드 리팩토링
test 테스트 코드 추가
chore 환경설정, 빌드 업무, 패키지 매니저 설정등..
hotfix 치명적이거나 급한 버그 수정
remove 사용하지 않는 변수, 파일 etc 삭제
working 이미 만들어진 기능, 함수 작업중
merge branch merge
  • branch 컨벤션
브랜치명 내용
develop 파일, 폴더, 새로운 기능 추가
fix 버그 수정
docs 제품 코드 수정 없음
refactor 코드 리팩토링
hotfix 치명적이거나 급한 버그 수정
  • issue 컨벤션과 pr컨벤션도 branch 컨벤션과 동일
    • [ Fix ] 이런식으로 포맷이 달라짐

🔨 사용 기술

HTML5 CSS3 JavaScript React ReactRouter Recoil

Axios styled-components MUI Lodash

Git GitHub Notion


📦 폴더 구조

📂 src
├── 📂 apis // json-server와 통신하는 api
├── 📂 components // 컴포넌트 관리
│   ├── 📂 AdManagement
│   ├── 📂 Card
│   ├── 📂 common // svg icons, SEO
│   ├── 📂 DropDown
│   ├── 📂 Home
│   └── 📂 Layout // sideNav와 Header 포함
├── 📂 constants // 상수 관리
├── 📂 hooks
│   ├── 📂 AdManagement
│   │   ├── 📄 useEndDate // recoil을 통해 시작,끝 날짜를 state로 관리
│   │   └── 📄 useStartDate 
│   └── 📄 useOnClickOutside // 반응형 nav 클릭 탐지
├── 📂 pages // 페이지 관리
│   └── 📂 Home
│       ├── 📄 Home
│       └── 📄 index
├── 📂 store // recoil store 관리
│   ├── 📄 addFilter
│   ├── 📄 cards // ad_list_data.json 관련
│   ├── 📄 data // trend_data.json 관련
│   ├── 📄 date
│   └── 📄 graphNav // 대시보드 graph data 관련
├── 📂 styles // 전역 style 관리
│   ├── 📄 GlobalStyles
│   └── 📄 theme
├── 📂 utils // 공통적으로 사용되는 util 함수 관리
│   ├── 📄 dateConvert
│   ├── 📄 getKPI
│   ├── 📄 handleFormatDate
│   ├── 📄 unitDecider
│   └── 📄 validateCost
├── App.jsx
└── index.jsx

👨‍👩‍👧‍👦 팀원

조은지
(팀장)
고영훈
(서기)
김창희
(팀원)
박정민
(팀원)
Joeunji0119 YeonghunKO PiperChang ono212
Joeunji0119 YeonghunKO PiperChang ono212
문지원
(팀원)
이상민
(공지)
이지원
(팀원)
조수진
(팀원)
moonkorea00 dltkdals224 365supprot suzz-in
moonkorea00 dltkdals224 365support suzz-in

About

원티드 프리온보딩 프론트엔드 - Assignment #4

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages