본문 바로가기

Refactoring

[Refactoring] Typescript Partial 활용해서 코드량 줄이기

typescript로 사이드 프로젝트를 진행하면서 코드 리팩토링을 하던 중 partial을 활용하면 코드량을 줄일 수 있을거라는 피드백을 받았다.
타스 공부할 때 partial에 대해서 공부하긴 했었지만, 실제 코드에 적용해본적은 없어서 얼마나 많이 코드량이 줄어들지 기대가 됐다.

 

먼저, partial에 대해서 다시 한번 알아보자!

Partial 

특정 타입에 부분집합의 만족하는 타입을 정의할 수 있다.

type Person {
  name: string;
  birth: string;
  age: number;
}

type Friend = Partial<Person>;
const hans: Friend = {}; // 가능
const harry: Friend = { name: "harry" }; // 가능
const amy: MyEmail = { name: "amy", age: 24 }; // 가능

 

예시 코드를 보면 알 수 있듯이, Partial<Person> 타입을 가지는 Friend 타입은 Person의 부분집합 값을 모두 수용 가능하다.

 

기존에 프로젝트에서는 부모 컴포넌트에서 자식 컴포넌트로 값을 업데이트 할 수 있는 함수를 props로 전달중이었는데,
이때 업데이트 되어야 할 속성들이 4개여서 총 4개의 함수를 전달중이었다.
이 부분을 Partial을 사용해서 1개의 함수 전달로 개선 할 예정이다!

 

아래 타입에 대해서 Partial을 적용 할 예정이다.

type DiscussionFeedData = {
  subject1: string;
  subject2: string;
  content: string;
  hashtag: string[];
};

 

개선 전 부모 컴포넌트

  const updateSubject1 = (sub1: string) => {
    setDiscussionFeedData((prev) => ({
      ...prev,
      subject1: sub1,
    }));
  };
  const updateSubject2 = (sub2: string) => {
    setDiscussionFeedData((prev) => ({
      ...prev,
      subject2: sub2,
    }));
  };

  const updateContents = (newContents: string) => {
    setDiscussionFeedData((prev) => ({
      ...prev,
      content: newContents,
    }));
  };

  const updateHashTags = (newHashtags: string[]) => {
    setDiscussionFeedData((prev) => ({
      ...prev,
      hashtag: newHashtags,
    }));
	};
	
<AddContent
        feedType="discussion"
        updateContents={updateContents}
        updateHashtags={updateHashTags}
        updateSubject1={updateSubject1}
        updateSubect2={updateSubject2}
/>


개선 전 자식 컴포넌트 <AddContent/>

// props 선언하는 부분
  updateContents: (contents: string) => void;
  updateHashtags: (hashtags: string[]) => void;
  updateSubject1?: (sub1: string) => void;
  updateSubject2?: (sub2: string) => void;

// 업데이트 함수 사용하는 부분
  useEffect(() => {
    updateHashtags(hashtags);
  }, [hashtags]);

  const onChangeTextarea = (e: ChangeEvent<HTMLTextAreaElement>) => {
    updateContents(e.target.value);
  };

 

 

이렇게 총 4개의 함수를 일일이 전달해주어 코드의 길이가 불필요하게 길어지고 있었다.
이 부분을 Partial로 개선해보았다.

 

개선 후 부모 컴포넌트

const updateDiscussionFeedData = (
    nextDiscussionFeedData: Partial<DiscussionFeedData>,
  ) => {
    setDiscussionFeedData((prev) => ({
      ...prev,
      ...nextDiscussionFeedData,
    }));
  };

<AddContent
   feedType="discussion"
   updateDiscussionFeedData={updateDiscussionFeedData}
/>

 

개선 후 자식 컴포넌트

// props 선언 부분
  updateDiscussionFeedData: (
    nextDiscussionFeedData: Partial<DiscussionFeedData>,
  ) => void;

// 업데이트 함수 사용하는 부분
 useEffect(() => {
    updateDiscussionFeedData({ hashtag: hashtags });
 }, [hashtags]);

 const onChangeTextarea = (e: ChangeEvent<HTMLTextAreaElement>) => {
    updateDiscussionFeedData({ content: e.target.value });
 };

 

불필요한 코드량이 많이 줄어들고 4개의 props가 1개로 줄어 가독성도 많이 향상된 것을 볼 수 있다 🥹
partial을 사용해서 개선을 하니 나중에 DiscussionFeedData 타입 구조가 변경되더라도 추가로 update 함수를 생성하지 않아도 돼서
유지보수 측면에서도 훨씬 좋아진 것 같다!