티스토리 뷰

온라인 강의나 블로그 또는 책을 읽다보면 "중복된 코드는 제거해야 한다", "재사용성을 키워야 한다"는 말을 여러 번 들을 수 있다. 나도 강의를 듣고, 블로그를 읽고, 그러다 보니 이와 관련된 배움을 얻었고, 생각도 하고 있고, 글도 쓰기도 했다. 그러나 정작 제대로 느껴본 적이 없었다.

 

이것이 얼마나 중요한 지 제대로 느껴본 적이 없는 상태로 생각하고, 글만 작성하고 있었다. 그러다, 이번에 간단한 개인 프로젝트에서 기능 함수를 재사용하는 경험을 하면서 "이래서 필요하다고 한 것이구나"라고 바로 느낄 수 있었다.

 

간단하게 예를 들어 설명하자면, 아래와 같은 검색 기능을 하는 코드가 있다고 보자.

(제대로 된 코드가 아닌 예시 코드)

function SearchBar() {
    const [searchTerm, setSearchTerm] = useState("");
    const navigate = useNavigate();

    const changeInputValue = (e: React.ChangeEvent<HTMLInputElement>) => {
      setSearchTerm(e.target.value);
    };

    const handleSearch = () => {
      if (searchTerm.trim()) {
        navigate(`/search?query=${encodeURIComponent(searchTerm)}`);
      } else {
        alert("검색어를 입력해주세요.");
      }
    };

    const pressEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === "Enter") {
        handleSearch();
      }
    };

    return (
        <SearchContainer>
            <SearchInput
                type='text'
                value={searchTerm}
                onChange={changeInputValue}
                onKeyUp={pressEnterKey}
                placeholder='데이터 검색'
                alt='검색'
            />
            <SearchButton onClick={handleSearch}>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6">
                    <path fillRule="evenodd" d="M10.5 3.75a6.75 6.75 0 1 0 0 13.5 6.75 6.75 0 0 0 0-13.5ZM2.25 10.5a8.25 8.25 0 1 1 14.59 5.28l4.69 4.69a.75.75 0 1 1-1.06 1.06l-4.69-4.69A8.25 8.25 0 0 1 2.25 10.5Z" clipRule="evenodd" />
                </svg>
            </SearchButton>
        </SearchContainer>
    )
}

 

대략, 위 처럼 구현하여 처리할 수 있을 것이다.

 

  • 검색어 값을 받는 `useState`를 선언
  • Input의 입력값이 바뀔 때마다 값이 저장되도록 하는 함수
  • 엔터 키를 누르거나 검색 버튼을 누르면 검색이 실행되는 함수

 

만약, 또 다른 유형의 검색하는 페이지를 만든다면 어떻게 만들 수 있을까?

function OhterSearchBar() {
    const [searchTerm, setSearchTerm] = useState("");
    const navigate = useNavigate();

    const changeInputValue = (e: React.ChangeEvent<HTMLInputElement>) => {
      setSearchTerm(e.target.value);
    };

    const handleSearch = () => {
      if (searchTerm.trim()) {
        navigate(`/search?query=${encodeURIComponent(searchTerm)}`);
      } else {
        alert("검색어를 입력해주세요.");
      }
    };

    const pressEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === "Enter") {
        handleSearch();
      }
    };

    return (
        ...
    )
}

 

기존과 똑같이 검색어 값을 저장할 변수를 선언하고, 각 기능을 하는 함수를 생성해서 처리할 것이다.

그러나, 이렇게 구현하게 되면 같은 코드를 여러 번 사용하여 중복된 코드가 만들어진다. 만약, 이를 `Hook`으로 처리한다면 어떨까?

 

export const useSearchEvent = () => {
  const [searchTerm, setSearchTerm] = useState("");
  const navigate = useNavigate();

  const changeInputValue = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchTerm(e.target.value);
  };

  const handleSearch = () => {
    if (searchTerm.trim()) {
      navigate(`/search?query=${encodeURIComponent(searchTerm)}`);
    } else {
      alert("검색어를 입력해주세요.");
    }
  };

  const pressEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      handleSearch();
    }
  };

  return {
    searchTerm,
    changeInputValue,
    handleSearch,
    pressEnterKey,
  };
};

 

중복된 코드를 `Hook`으로 위 처럼 처리한다면, 검색 기능을 필요로 하는 컴포넌트에서는 단순히 불러와서 사용하면 기존보다 코드도 더 간결해지고 간단해지지 않을까?

 

그렇다면, 이제 위의 'Hook'을 사용해보면 어떻게 처리할 수 있을까?

 

function SearchBar() {
    const {
      searchTerm,
      changeInputValue,
      handleSearch,
      pressEnterKey,
    } = useSearchEvent();

    return (
        <SearchContainer>
            <SearchInput
                type='text'
                value={searchTerm}
                onChange={changeInputValue}
                onKeyUp={pressEnterKey}
                placeholder='데이터 검색'
                alt='검색'
            />
            <SearchButton onClick={handleSearch}>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6">
                    <path fillRule="evenodd" d="M10.5 3.75a6.75 6.75 0 1 0 0 13.5 6.75 6.75 0 0 0 0-13.5ZM2.25 10.5a8.25 8.25 0 1 1 14.59 5.28l4.69 4.69a.75.75 0 1 1-1.06 1.06l-4.69-4.69A8.25 8.25 0 0 1 2.25 10.5Z" clipRule="evenodd" />
                </svg>
            </SearchButton>
        </SearchContainer>
    )
}
function OhterSearchBar() {
    const {
      searchTerm,
      changeInputValue,
      handleSearch,
      pressEnterKey,
    } = useSearchEvent();

    return (
        ...
    )
}

 

이제 간단하게 생성해놓은 `Hook`을 가져와서 사용하기만 하면 된다.

기존과 달리, 중복된 코드들이 하나의 컴포넌트로써 재사용이 가능하게 됐고, 이를 사용했던 컴포넌트들은 단순히 가져와서 사용함으로써 더 간결하게 처리할 수 있게 됐다.

 

만약, 기능을 추가해야 한다면 `Hook` 컴포넌트에 해당 기능을 담은 함수를 추가해서 내보내기만 하면 된다. 간단하다.

단순한 코드이지만, 만약, 코드가 더 길거나 더 큰 경우에는 더 유용하고 효율적이라고 생각한다.