Work Log | 클린 코드로 리팩토링 하기

Kate Jung·2024년 5월 15일
0

Work Log

목록 보기
1/1
post-thumbnail

나오는 코드들은 변형을 준 코드입니다.

📌 이메일 형태 converting하기

🔹 before

/**
     * 직접 넘어온 도메인이 있으면 해당 값으로 세팅. 없으면 state 변수에 있는 값으로 세팅.
     * value + @ + 도메인값 으로 value 넘김.
     *
     * @param currentValue
     * @param _domain 추가 도메인
     */
    const handleChangeEmail = (currentVal: string, _domain?: string): void => {
        const currentDomain = _domain || domain; 
        const emailValue = `${currentVal}@${currentDomain === "direct" ? directDomain.current || "" : currentDomain}`; // 👈 1. 한 눈에 알아보기 어려움
        const valid = validate(emailValue);
        setValue(currentValue);

				// 👇 2. 더 축약할 수 있음.
        if (onChange !== undefined) {
            onChange(name, emailValue);
        }
        if (handleChangeValue) {
            handleChangeValue(name, { value: emailValue, isValid: valid });
        }
    };
  • 코드 설명

    주석 참고

  • 아쉬웠던 부분

    • 강조하고 싶은 부분은 주석(+ 👈 이모지)으로 추가했다.

    • 일단 한 눈에 알아보기가 매우 어려웠다.

      그리고 어떤 state는 useState로 어떤 state는 useRef로 관리했는데, 이런 방식은 코드를 이해하고 관리하는데 더한 어려움을 초래하는 부분이라고 생각했다.

    • 또한 코드를 더 줄여서 가독성을 높일 수 있겠다고 생각했다.

🔹 after

// 👇 한 눈에 알아보기 쉬움
/**
     * 새로 받은 값에 맞춰 이메일 주소 형태(emailId + @ + 도메인값) 제작
     * (직접 넘어온 도메인이 있으면 해당 값으로 세팅. 없으면 state 변수에 있는 값으로 세팅.) // 👈 주석 및 논리는 동일하게 유지
     *
     * @param newEmailId
     * @param newDomain
     * @param newDirectDomain
     */
const constructEmailAddress = (newEmailId?: string, newDomain?: string, newDirectDomain?: string) => {
        // 👇 3가지 변수에 동일한 규칙 적용
        const currentEmailId = newEmailId ?? emailId;
        const currentDomain = newDomain ?? domain;
        const currentDirectDomain = newDirectDomain ?? directDomain;

        return `${currentEmailId}@${currentDomain === "direct" ? currentDirectDomain : currentDomain}`;
};

    /**
     * 새로운 형성된 이메일을 필요에 따라 처리
     * - 새 값에 맞는 이메일 형식 만들기
     * - validation 체크
     * - props로 넘겨받은 함수에 값 전달 등
     */
    const handleChangeEmail = (newEmail: emailValueType) => {
        const newEmailAddress = constructEmailAddress(newEmail); // 👈 [함수 분리] 이메일 컨버팅
        const valid = validate(newEmailAddress);

        onChange?.(name, newEmailAddress); // 👈 [축약] 옵셔널 체이닝 추가
        handleChangeValue?.(name, { value: newEmailAddress, isValid: valid }); // 👈 [축약] 옵셔널 체이닝 추가
    };
  • 코드 설명

    주석 참고

  • 결과

    • 한 눈에 알아보기 쉽게 변형

      • state를 useState로 통일
      • 이메일 값 converting 시, 동일한 규칙 적용 (Nullish coalescing operator (??))
      • 기능에 맞게 함수 분리 (constructEmailAddress)
      • 옵셔널 체이닝 추가
    • CTO님 및 동료에게 칭찬은 덤 👏

📌 선택한 탭의 index 찾기

🔹 before

const IndexOfselectedTab = useMemo<TabIndexType>(() => {
        for (let i = 0; i < items.length; i++) {
            if (router.asPath.includes(encodeURI(items[i].as)) || router.pathname.includes(items[i].link)) {
                return i + 1;
            }
        }
        return false;
    }, [router.pathname]);
  • 코드 설명과 아쉬웠던 부분

    CTO님이 작성하셨었던 기존 코드다.

    잘 만드셨지만 아쉬운 부분은 로직을 한 눈에 파악하기 어렵다는 점이 있었다.

    결국 조건(if문 내부)에 맞는 index를 찾아 있다면 +1을 하고 없다면 false 처리 한다는 로직인데, js 메소드를 잘만 찾으면 더 가독성 있고 짧은 코드를 만들 수 있겠다는 생각이 들어서 리팩토링을 하게 되었다. (또한 시간적 여유도 있어서 진행했다.)

🔹 after

const IndexOfselectedTab: TabIndexType = useMemo(() => items.findIndex(({ as, href }) => decodeURI(asPath).includes(as) || pathname.includes(href)) + 1 || false, [pathname]);
  • 코드 설명

    가독성 ⬆️ (직관적인 js메소드 사용 & 간결해진 코드)

    findIndex라는 적절한 메소드를 찾았다.

    as나 href 포함되어 있다면 해당 index에 +1을, 아니면 false를 반환하는 로직이다.

    전보다 간결해졌을 뿐만 아니라 가독성도 좋아졌음을 알 수 있다.

    (CTO님이 감탄하셔서 뿌듯했다.)

profile
복습 목적 블로그 입니다.

0개의 댓글