본문으로 바로가기

Olympic Medal Tricker 리팩토링

category React.js 2025. 1. 29. 13:10

 

1. CSS 파일 네이밍 컨벤션: 케밥 케이스(kebab-case) 사용

Windows와 달리 Linux/Unix 계열의 운영체제는 대소문자를 구분합니다.
즉, Main.css와 main.css는 Windows에서는 같은 파일로 인식되지만, Linux에서는 서로 다른 파일로 취급됩니다.

이처럼 리눅스 서버에서 배포할 때 의도치 않은 파일 불일치 문제가 발생할 수 있기 때문에 CSS 파일명은 항상 소문자로만 작성하는 것이 일반적인 컨벤션입니다.

 

기존 CSS 파일명은 컴포넌트 파일명과 같은 카멜 케이스를 사용

기존 CSS 파일명

소문자와 하이픈(-)을 사용하는 케밥 케이스로 변경 

 

 

2.  number의 input창에 숫자가 아닌 문자를 적을 경우 NaN이 출력되는 문제

기존 input 값을 바로 Number형으로 변환

const handleChange = (e) => {
        const { name, value } = e.target;
        const setValueType = name === 'gold' || name === 'silver' || name === 'bronze' ? Number(value) : value.trim();
        setMedalItem({ ...medalItem, [name]: setValueType });
    };

 

 

✅ isNaN을 통해 NaN일 경우 0이 출력되도록 코드 구현

const handleChange = (e) => {
        const { name, value } = e.target;
        const setValueType =
            name === 'gold' || name === 'silver' || name === 'bronze'
                ? isNaN(Number(value))
                    ? 0
                    : Number(value) 
                : value.trim();
        setMedalItem({ ...medalItem, [name]: setValueType });
    };

 

3. 확장성을 고려한 커스텀 훅 매개변수 default 설정

기존 코드(매개변수 key 강제 전달) 

// App.jsx
const { medalList, addMedal, updateMedal, deleteMedal } = useMedalList('medalListStorage');

// useMedalList.jsx
export const useMedalList = (key) => {
...
}

 

✅ default 값 설정

// App.jsx
const { medalList, addMedal, updateMedal, deleteMedal } = useMedalList();

// useMedalList.jsx
export const useMedalList = (key = 'medalLists') => {
...
}

 

 

4. 불필요한 컴포넌트 분리 방지 및 렌더링 최적화

 

❌ <tr>이라는 태그는 테이블 없이는 독립적으로 사용될 수 없지만 컴포넌트로 분리

// MedalTable.jsx
<table className="medal-list-table">
	...
    <tbody>
        {sortMedalListByRank.map((m) => {
            return <MedalItem key={m.country} handleDeleteList={handleDeleteList} medalItem={m} />;
        })}
    </tbody>
</table>

 

컴포넌트란 단순히 여러번 렌더링되는 것이 아닌 독립적으로 재사용될 수 있는 요소

 

✅ table 내에서 map을 이용하여 직접 렌더링

<tbody>
    {sortMedalListByRank.map((medalItem) => {
        return (
            <tr key={medalItem.country}>
                <td>{medalItem.rank}</td>
                <td>{medalItem.country}</td>
                <td>{medalItem.gold}</td>
                <td>{medalItem.silver}</td>
                <td>{medalItem.bronze}</td>
                <td>{medalItem.gold + medalItem.silver + medalItem.bronze}</td>
                <td>
                    <button className="medal-item-btn" onClick={() => handleDeleteList(medalItem.country)}>
                        Delete
                    </button>
                </td>
            </tr>
        );
    })}
</tbody>

 

5. 예기치 못한 에러 방지를 위한 옵셔널 체이닝 활용

medalList가 null이나 undefined일 경우 오류 발생 가능

{medalList.length === 0 ...}

 

옵셔널 체이닝(?.)을 사용하여 medalList가 null 또는 undefined일 경우, length에 접근하지 않고 undefined를 반환

{medalList?.length === 0 ...}