(React) 08. Custom hooks

김동우·2021년 8월 22일
1

wecode

목록 보기
31/32
post-thumbnail

잠깐! 시작하기 전에

이 글은 wecode에서 실제 공부하고, 이해한 내용들을 적는 글입니다. 글의 표현과는 달리 어쩌면 실무와는 전혀 상관이 없는 글일 수 있습니다.

또한 해당 글은 다양한 자료들과 작성자 지식이 합성된 글입니다. 따라서 포스팅이 틀린 정보이거나, 해당 개념에 대한 작성자의 이해가 부족할 수 있습니다.

설명하듯 적는게 습관이라 권위자 발톱만큼의 향기가 날 수 있으나, 엄연히 학생입니다. 따라서 하나의 참고자료로 활용하시길 바랍니다.

글의 내용과 다른 정보나 견해의 차이가 있을 수 있습니다.
이럴 때, 해당 부분을 언급하셔서 제가 더 공부할 수 있는 기회를 제공해주시면 감사할 것 같습니다.


서론

  1. 팀원들의 개발 속도를 올리고 싶다!

  2. 중복되는 로직을 한 줄로 줄이고만 싶다!

하는 사람들에게 딱 좋은 내용입니다.

예시는 fetch, async-await 로직입니다.

아무리 생각해도 이런 기능이 있었기에 React가 사랑스럽지 않았을까 생각이 드네요.

물론 utils 파일의 존재는 팀 프로젝트에 있어 필수적이라고 생각합니다.

React hooks는 그 이상의 무언가를 보여주고 있지 않을까? 하는 마음이 살짝 드네요.

사실 팀원들에게 이 hooks를 설명하고, 사용하게 하는 것이 가장 어려운 일인데, 이는 또 잘 이겨낼 수 있기를 바랍니다.

그럼 시작해보겠습니다.

hooks.js

import { useEffect, useState } from 'react';
import { KAKAO_LOGIN, REDIRECT_URI } from './config';

export const useFetch = (url, methodOptions) => {
  const [responseData, setResponseData] = useState({});
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  const fetchUrl = async () => {
    try {
      const response = await fetch(url, methodOptions);

      if (!response.ok) {
        throw new Error(response.status);
      }

      const json = await response.json();
      setResponseData(json);
      setLoading(false);
    } catch (e) {
      setError(e);
    }
  };

  useEffect(() => {
    fetchUrl();
  }, []);

  return [responseData, loading, error];
};
// commonLogic - 범용성 넓음

//--------------------------------------------------------

export const useKakaoLogin = codeData => {
  const [userInfo, setUserInfo] = useState('');
  const [loading, setLoading] = useState(true);
  const [errorText, setErrorText] = useState('');

  const login = async () => {
    try {
      const kakaoTokenCall = await fetch(
        `https://kauth.kakao.com/oauth/token?grant_type=authorization_code&client_id=${process.env.REACT_APP_REST_API_KEY}&redirect_uri=${REDIRECT_URI}&code=${codeData}`
      );

      const kakaoToken = await kakaoTokenCall.json();

      const backEndUserInfoCall = await fetch(KAKAO_LOGIN, {
        method: 'POST',
        headers: { Authorization: kakaoToken.access_token },
      });

      const backEndUserInfo = await backEndUserInfoCall.json();

      setUserInfo(backEndUserInfo);
      setLoading(false);
    } catch (e) {
      setErrorText(e, 'error!');
    }
  };

  useEffect(() => {
    login();
  }, []);

  return [userInfo, loading, errorText];
};
// module화 기반 Logic - 범용성 거의 없음

설명

위 두 로직은 둘 다 hooks.js 내에 존재하지만 범용성이 넓은 로직과 적은 로직의 예시입니다.

사실 아직 두 로직밖에 없습니다.

차이를 아시겠나요?

범용성이 넓은 로직을 배포하기 위해서는 함수 내에 거의 모든 데이터 타입을 인자로 받아야만 합니다.

그 예시가 해당 두 로직에서는 URL이 될 수 있겠네요.

특정 상황에서만 쓰이게 하는 조건은 분명 특정 데이터가 있으면 그렇다! 가 되겠네요.

즉, 하나의 함수를 만들더라도 내부에 존재하는 데이터를 어떻게 인자로 받게 할 것인가? 를 고민하는 것이 중요하다고 볼 수 있겠습니다.

이를 대부분 추상화라고 표현합니다.

정확한 개념을 알고 싶다면 '데이터의 추상화' 라는 키워드로 구글을 뒤져보는걸 추천드립니다.

그러나 저와 같은 입문자에게 해당 지식은 때론 너무 깊을 수 있으니 적당히 보고 나오시길 바랍니다.

그러니까 이번 글에서는 간단한 부분부터 짚고 넘어갑시다.

하나의 함수를 배포하기 위해서는 내부에 특정 용도의 데이터가 존재해서는 안된다.

왜 그런지 이제 공용 컴포넌트를 만들게 되면서 슬슬 이해하고 계시겠죠?

마치며

우리가 중복을 제거하는 것은 싱크로율이 100%에 수렴하는 코드행 뿐만이 아닙니다.

코드행 내부, 파일 사이에도 분명 다른 의미의 중복이 존재하고 있으니까 말이죠.

두 페이지, 혹은 세 페이지, 혹은 전체 앱 내부의 중복.

우린 중복을 없애며 매일 나아가야 합니다.

어렵더라도 노력하면 언젠가 저도 기획단계에서 중복을 최소화 할 수 있겠죠.

그렇게 될 날을 그리며 이번 글은 이만 마치도록 하겠습니다.

읽어주셔서 감사합니다.

1개의 댓글

comment-user-thumbnail
2021년 8월 22일

이 포스트 내용 굉장히 좋아요!!

답글 달기