logo

DowanKim

23. 변하지 않는 배열을 컴포넌트 외부에 선언해야하는 이유

2025년 10월 19일

이게머니

1. 공통적으로 세번 사용되는 로직, 유틸로 따로 분리해야함.

const toAbsoluteUrl = (u?: string) => { if (!u) return ''; if (/^https?:\/\//i.test(u)) return u; const base = import.meta.env.VITE_API_BASE_URL ?? ''; return `${base}${u.startsWith('/') ? u : `/${u}`}`; };

2. 배열을 컴포넌트 외부에 선언해서 매 렌더링마다 배열이 재생성되지 않도록 하는 것이 좋을 것 같아요.

const navItems = [ { name: '꾸미기', path: '/character' }, { name: '랭크', path: '/rank' }, { name: '홈', path: '/home' }, { name: '학습 기록', path: '/record' }, { name: '마이 페이지', path: '/mypage' }, ];

배열은 컴포넌트 안에 현재 선언하면, 리렌더링마다 배열이 재생성되는 문제가 있습니다.

이에 다음과 같이 변경하였습니다

/** * 네비게이션 관련 상수들 */ export interface NavItem { name: string; path: string; } export const NAV_ITEMS: NavItem[] = [ { name: '꾸미기', path: '/character' }, { name: '랭크', path: '/rank' }, { name: '홈', path: '/home' }, { name: '학습 기록', path: '/record' }, { name: '마이 페이지', path: '/mypage' }, ] as const;

변하지 않는 상수 배열이므로, 위와 같이 모듈레벨 상수로 분리하여 배열 재생성을 막고, 재사용성과 타입안정성을 향상시키는 것으로 수정하였습니다.

3. 불필요하게 타입 체크를 한 이유가 있을까요?

<NavWrapper> {navItems.map((item) => ( <NavItem key={typeof item.name === 'string' ? item.name : '마이 페이지'}

앞선 상수파일 분리 수정 과정에서, interface도 설정을 해두었기 때문에 더더욱 타입체크가 필요없어졌습니다.

또한 name이 한국어 문자열인데 key값으로 들어가는 것도 혹시 모를 문제가 생길 수 도 있을 것 같습니다.

실제 url과 일치하는 path값을 key 로 그냥 넘겨주는 것으로 수정 완료하였습니다.

4.checkAnswer를 handleConfirm 보다 상단에 구현하는 것이 좋을 것 같아요.

const checkAnswer = (selectedAnswer: string | boolean, quizData: QuizData): boolean => { if (quizData.questionType === 'OX') { return selectedAnswer === quizData.questionData.correctAnswer; } else if (quizData.questionType === 'MULTIPLE_CHOICE') { return selectedAnswer === quizData.questionData.correctAnswer; } return false; };

handleConfirm이 checkAnswer를 사용하고 있는 상황이므로, 헬퍼함수(checkAnswer)를 상단으로 옮겨 수정 완료했습니다.

이를 통해, 코드를 위에서 아래로 읽으면서 이해하기 쉽고 가독성이 좋아졌습니다.