술담화 클론 프로젝트 - 기억에 남는 코드록

DongHee Kim·2021년 9월 18일
6

Project

목록 보기
6/7

프로젝트가 끝난 후, 코드는 남지만 코드를 생각해내기까지의 고민과 과정은 쉽게 휘발된다. 이를 붙잡기위해 적어보는 기억에 남는 코드록

🍶 fetch 함수 축약

기본적으로 사용되는 fetch 함수 형태는 아래와 같다.
하지만 위의 fetch함수가 여러 번 반복되어 사용된다면 가독성이 현저히 떨어진다.
리팩토링의 중요한 원칙 중 하나 = 반복되는 요소를 축약시키자

위 함수에서 각각의 색으로 테두리친 fetch함수, 두 번의 then함수setState부분을 아래와 같이 변수화해서 가독성은 챙기고, 코드의 길이는 줄일 수 있다.

1. setState 변수화

    const updateProducts = data => this.setState({ products: data.Result });
    const updateMain = data => this.setState({ main: data.Result });

setState 부분을 살펴보니 state 중 products 혹은 main을 변경하는 것으로 나뉘었다. 이 부분을 각각 변수 한 단어로 설정해 축약했다.

2. fetch(API, setState함수) 변수화

반복되는 함수가 있다 => 함수의 틀을 만들고, 바꾸어서 재사용하자.
fetch함수 및 두 번의 then 함수를 하나의 함수로 만들었다.
여기서 변경되는 부분은 API와 setState 부분이니 각각 (setState부분은 callback함수로) 인자로 설정했다.

handleFetch = (API, callback) => {
  fetch(API)
    .then(res => res.json())
    .then(data => {
      callback(data);
    });
};

위 함수에서의 callback(data)는 변수화해두었던 setState인 updateProducts, updateMain 으로 대체할 수 있다.
그럼 아래 처럼 정-말 많이 축약된 코드로 같은 기능을 구현할 수 있다!

//state의 products update
handleFetch(API, updateProducts);

//state의 main update
handleFetch(API, updateMain);

실제로 카테고리 상품 리스트 페이지 내에서 총 3번의 fetch가 이루어져야 했는데, 변수화를 통해 가독성을 높힐 수 있었다. fetch함수는 앞으로 질리도록 쓰게 될테니 잘 기억해두고 두고두고 써먹어야지


🍶 쿼리스트링을 이용한 ordering

1. 각 버튼의 filter 속성에 ordering 기준 텍스트 입력

const FILTER_BTN_DATA = [
  {
    id: 1,
    filter: 'name',
    text: '이름순',
  },

  {
    id: 2,
    filter: 'updated_at',
    text: '최신순',
  },
  {
    id: 3,
    filter: '-grade',
    text: '인기순',
  },
  {
    id: 4,
    filter: 'price',
    text: '낮은 가격순',
  },
  {
    id: 5,
    filter: '-price',
    text: '높은 가격순',
  },
  {
    id: 6,
    filter: 'dgree',
    text: '낮은 도수순',
  },
  {
    id: 7,
    filter: '-dgree',
    text: '높은 도수순',
  },
];

위와 같이 상수 데이터에 map함수를 돌려 버튼 컴포넌트를 나타냈는데, 그 중 filter 속성에 쿼리스트링으로 보낼 값들을 적어주었다. (이 때 백엔드 측과 협의 필수)

2. 버튼 클릭시 state가 update되는 함수 구현

// 최상위 컴포넌트
// state 중 filter항목을 update하는 handleFilter 함수 구현
  handleFilter = e => {
    this.setState({
      filter: e,
    });
  };


// 버튼 컴포넌트
// onClick이벤트로 handleFilter 함수 호출.
// 이 때 인자는 이벤트 타겟의 id(=상수데이터에서 받아온 각각의 filter값)이다.
// 따라서 버튼 클릭시 해당 버튼의 filter 값으로 최상위 컴포넌트 state의 filter 값이 바뀌는 셈

    const { currentFilter, filter, handleFilter, text } = this.props;

    return (
      <button
        className={`filter-btn ${
          currentFilter === filter ? 'yellow-btn' : 'gray-btn'
        }`}
        onClick={e => {
          handleFilter(e.currentTarget.id);
        }}
        id={filter}
      >
        {text}
      </button>
    )

3. 쿼리스트링으로 ordering 요청

state가 변경되니 componentDidUpdate를 통해 fetch를 해주어야 한다.
이전 filter와 현재 filter가 변경되었을 때를 비교하고,
값이 서로 다를 경우 앞서 축약해주었던 형태로 fetch를 다시 해준다.

  componentDidUpdate(prevProps, prevState) {
    const updateProducts = data => this.setState({ products: data.Result });
    if (this.state.filter !== prevState.filter) {
      this.handleFetch(
        `${API}/products/list?limit=20&order-by=${this.state.filter}&category=${this.props.match.params.id}`,
        updateProducts
      );
    }
  }

🍶 쿼리스트링을 이용한 검색 기능

실제 사이트엔 없는 기능이지만, 팀원들과 상의한 후 새롭게 추가한 기능인 안주 검색 기능
프론트엔드 단에서 구현을 해야할지, 글씨를 입력할 때마다 바로바로 검색되게 해야할지.. 팀원들과 많은 고민을 한 끝에 가장 안정적으로 결과물이 나타난다고 생각되는 쿼리스트링을 통한 구현을 선택했다.

1. input값을 state에 저장

state update 함수 만들기

  handleSideDishInput = e => {
    const { name, value } = e.target;
    this.setState({ [name]: value });
  };

위와 같이 이벤트 타겟의 name : value 형태로 state를 update하는 함수를 만들고


state update 함수를 input에 넘겨주기

        <input
          className="filter-input"
          placeholder="어떤 안주와 즐기고 싶으세요?"
          name="sideDish"
          onChange={this.props.handleSideDishInput}
        />

이 함수를 input에 onChange 이벤트로 걸어준다.
input의 name은 sideDish로 입력해두었다. 결과적으로 input에 입력하는 값은 {sideDish(input의 name):input의 입력값} 형태로 state에 저장된다.


2. state값을 쿼리스트링으로 전달

이제 input의 입력값을 쿼리스트링 안에 넣어 서버로 보내주자!

쿼리스트링으로 검색값을 넘겨주는 함수 만들기

  handleSideDish = () => {
    this.handleFetch(
      `${API}/products/list?order-by=${this.state.filter}&category=${this.props.match.params.id}&side-dish=${this.state.sideDish}`,
      data =>
        this.setState({
          products: data.Result,
        })
    );
  };

위 코드에서 우리가 주목해야 할 부분은 side-dish=${this.state.sideDish}
handleSideDish 함수를 통해 우리는 fetch를 할 건데, 이 때 URL의 쿼리스트링에 state의 값을 넘겨준다.


검색값을 넘겨주는 함수를 버튼에 넘겨주기

검색 기능을 실행시킬 버튼을 클릭할 때마다 해당 함수가 호출되도록 onClick이벤트를 걸어주면 끝!

<button
className="filter-side-dish-btn"
onClick={this.props.handleSideDish}
>
안주로 검색하기
</button>
profile
일상의 성실이 자존감을 만드는 성취주의자

2개의 댓글

comment-user-thumbnail
2021년 9월 23일

와 동희님 너무 좋은 기획인거같아요!🙌🙌 저도 나중에..기억이 더 증발되기 전에 기록을 남기는 습관을 들여야겠습니다!

1개의 답글