가나다 2차 프로젝트

Gunwoo Kim·2021년 7월 4일
0

팀프로젝트

목록 보기
2/3

가나다방

이번에 진행한 프로젝트는 가나다방으로 다방을 모티브로 하여 클론하여 진행하였고 이번 프로젝트에는 리액트 훅을 이용하여 프로젝트를 진행하였습니다.
가나다방의 깃헙 주소입니다.

가나다방 시연 영상으로 저는 지도페이지의 개발을 진행하였습니다.

프로젝트 진행에서 클래스평 컴포넌트와 SASS로 진행했던 기존 프로젝트와는 달리 함수형 컴포넌트를 사용 리액트 훅을 이용하여 상태관리를 했으며 스타일도 SASS가 아닌 스타일 컴포넌트를 이용하여 진행하였습니다.

프로젝트 진행에서 어려웠던 점은 기존에 알고있던 내용이 아닌 새로운 개념을 공부하며 프로젝트에 적용해야하는 부분이었습니다.

스타일 컴포넌트는 어떻게 적용해야 하며 css 초기화는 어떻게 진행해야할지 등 어려움이 있었습니다.

프로젝트 구조 및 스타일 컴포넌트 적용

프로젝트 구조는 위와 같았고 공통적으로 적용해야하는 스타일 컴포넌트의 경우 GlobalStyle.js라는 파일에 초기화 세팅을 진행하였고 공통적으로 사용될 css는 mixin.js라는 파일로 컬러값의 경우 theme.js로 만들어서 index.js 파일에 아래와 같이 적용하였습니다.

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Routes from './Routes';
import { GlobalStyle } from './Styles/GlobalStyle';
import { ThemeProvider } from 'styled-components';
import theme from './Styles/theme';
import mixin from './Styles/mixin';

ReactDOM.render(
  <>
    <GlobalStyle />
    <ThemeProvider theme={{ ...theme, ...mixin }}>
      <Routes />
    </ThemeProvider>
  </>,
  document.getElementById('root')
);
// GlobalStyle.js
import { createGlobalStyle } from 'styled-components';
import { reset } from 'styled-reset';

export const GlobalStyle = createGlobalStyle`
${reset}
* {
  box-sizing : border-box;
}
*, html, body {
  font-size : 10px;
  font-family: 'Noto Sans KR', sans-serif;
}
a {
  color: inherit;
  text-decoration: none;
}
input, button {
  background-color: transparent;
  border: none;
  outline: none;
}
ol, ul, li {
  list-style: none;
}
`;

// mixin.js
import { css } from 'styled-components';

const flexSet = (
  justify = 'center',
  items = 'center',
  direction = 'row'
) => css`
  display: flex;
  justify-content: ${justify};
  align-items: ${items};
  flex-direction: ${direction};
`;

const mixin = { flexSet };

export default mixin;

// theme.js
const theme = {
  white: '#ffffffcc',
  black: '#222222',
  lightGray: '#868686',
  gray: '#656565',
  blue: '#326CF9',
  yellow: '#F7E506',
  solidGray: '#cdcdcd',
};

export default theme;

지도페이지

다음은 제가 담당했던 지도페이지 입니다.

구현된 모습은 위와 같고 이때 react-slider 와 query-string, react-naver-map 라이브러리를 사용하였습니다.

react-slider 라이브러리를 이용하여 아래와 같이 from-to 형식의 range 형태의 바를 제작하였고 검색된 데이터의 위치 정보를 가져오기 위해 query-string을 라이브러리를 이용하여 값의 변화를 감지하여 해당 조회된 지역의 방 정보와 지역을 형태를 표기하였습니다.

각각 필터 조건에 따른 상태값 관리를 하기 위해 useReducer를 사용하여 각 필터 탭의 상태를 관리하였고 보다 쉽게 불변성을 관리하기 위해 immer을 사용하여 상태를 변경하였습니다.

지도페이지부터 실제 필터버튼까지의 상태 3~4단계의 props로 전달하여야 하는 불편함이 존재해서 useContext를 사용하여 하위의 모든요소에 상태를 전달하여 사용할 수 있도록 진행하였습니다.

// useMapPageContext.js
import { createContext, useContext } from 'react';
import produce from 'immer';

export const CHECK_BOX = 'CHECK_BOX';
export const RANGE = 'RANGE';

const FilterContext = createContext();
export const useFilterContext = () => useContext(FilterContext);
export const FilterProvider = FilterContext.Provider;

const MapContext = createContext();
export const useMapContext = () => useContext(MapContext);
export const MapProvider = MapContext.Provider;

export const useFilterReducer = (state, action) => {
  switch (action.type) {
    case CHECK_BOX:
      return produce(state, draft => {
        const filterTap = draft.find(filter => filter.type === action.key);
        const list = filterTap.list.find(item => item.value === action.value);
        list.checked = action.checked;
      });
    case RANGE:
      return produce(state, draft => {
        const filterTap = draft.find(filter => filter.type === action.key);
        const list = filterTap.range.list.find(
          item => item.value === action.value
        );
        list.range = action.range;
      });
    default:
      return state;
  }
};

useMapPageContext.jsuseContextuseReduce 를 하위 요소에서 바로 접근하기 쉽게 따로 파일로 빼서 관리하였습니다.

마지막으로 ...

프로젝트를 마무리하고 다양한 리액트 훅에 대한 useState를 시작으로 useEffect, useContext, useReduce 등 공부 할 수 있는 기회가 되어서 좋은 프로젝트기간 이었습니다.

다만 필요한 기능들을 구현하다보니 useEffect가 많아지게 되고 감지해야할 상태값들이 너무 얽히는 상황이 발생하여 이 부분의 분리를 하여 처리하고 싶었으나 그렇지 못한 부분이 좀 아쉬운 상황으로 다가왔고 너무 라이브러리에 의존하여 개발하지 않았나 하는 특히 지도와 같이 굳이 라이브러리를 사용하지 않더라도 네이버에서 제공하는 API로도 충분히 개발을 진행 할 수 있었을거 같다는 생각이 들어 다음에도 지도를 사용하는 경우가 발생한다면 그때는 API만을 사용하여 진행해보고 싶었던 프로젝트였습니다.

0개의 댓글