문득, 한 가지 고민점이 생겼다.
보통 메모이징은 export하기 전, memo로 컴포넌트를 감싸 export하는 방식으로 진행했다.
그런데, 해당 컴포넌트가 공통 컴포넌트여서 다른 컴포넌트 여기저기에서 쓰인다면?
메모이징이 불필요한 상황이 대부분이고 딱 한 부분에서만 메모이징을 해야한다면?
그럼 결국 불필요한 메모이징을 남발하는 꼴이지 않나..?
결국 함수 컴포넌트의 관점에서 생각해보면 Vitual DOM의 컨셉을 가진 객체일 뿐이다.
메모이징이 필요한 컴포넌트에서 선택적으로 메모이징을 해주면 해결 될 문제였다.
(위의 코드는 어디까지나 예시일 뿐, props로 전달되는 taskData는 참조타입 데이터이기 때문에 이에 대한 메모이징도 진행해야한다.)
- 해당 컴포넌트가 여러 곳에서 사용되는 공통 컴포넌트인가?
- 힙 메모리를 사용할만큼 메모이징의 가치가 있는 컴포넌트인가?
위의 상황에서 컴포넌트 자체에 메모이징을 진행할 것인지, import해온 컴포넌트에서 진행할 것인지 상황에 맞게 선택을 하면 된다.
/* TaskCard 컴포넌트 메모이제이션 */
const MemoizedTaskCard = memo(TaskCard);
export function Project() {
const { id: param } = useParams();
const { errorHandler } = useErrorHandler();
const isMobileM = useMediaQuery(DEVICES.MOBILEM);
const isMobileL = useMediaQuery(DEVICES.MOBILEL);
const isTablet = useMediaQuery(DEVICES.TABLET);
const isLaptop = useMediaQuery(DEVICES.LAPTOP);
const gridColumnCount = useMemo(() => {
if (isLaptop) return 4;
if (isTablet) return 3;
if (isMobileL) return 2;
if (isMobileM) return 1;
return 1;
}, [isLaptop, isTablet, isMobileL, isMobileM]);
const { data: projectData, isLoading } = useQuery<ProjectDataForm>(
[QUERY.KEY.PROJECT_DATA, param],
() => getProjectData(param as string),
{
...QUERY.DEFAULT_CONFIG,
onError: (error: unknown) => errorHandler(error),
}
);
/* useMemo를 통한 props(projectData) 객체 메모이제이션*/
const memoizedTasks = useMemo(() => {
return projectData?.tasks.map((taskData: TaskDataForm) => (
<MemoizedTaskCard taskData={taskData} key={taskData.id} />
));
}, [projectData?.tasks]);
if (isLoading) return <Loading />;
return (
<Wrapper>
{projectData && <ProjectInformation projectData={projectData} />}
<ProjectBoard gridColumnCount={gridColumnCount}>
{memoizedTasks}
<NewTaskButton />
</ProjectBoard>
</Wrapper>
);
}