벡엔드, 디자이너분과 같이 협업 프로젝트를 진행 중이다. "Keepy-Uppy"라는 개발 프로젝트 협업을 돕는 서비스다. 작업하는 과정에서 물음표가 생긴 부분을 멘토님께 질문드렸고 새로 알게 된 내용을 정리할 겸, 조금 더 제대로 공부할 겸 남긴다.
💁🏻♀️ too long? click HERE
🚨 문제 상황
지난 번 svg 파일을 컴포넌트화 해서 사용하는 방법에 대해 알게 된 후 우리 프로젝트에도 그렇게 변경하는 것이 좋겠다는 의견을 냈고, 감사히 다른 팀원 분께서 변환 작업을 맡아주셨다. 그래서 오늘은 기존에 사용하던 svg 이미지들을 해당 컴포넌트로 바꾸는 작업을 했다.
그런데 한 가지 헷갈렸던 부분. 내가 맡은 사이드바에 페이지 이동 링크가 있는데 나는 이 네 가지 게시판의 이름, 아이콘, 링크를 상수화 해서 해당하는 이름의 프로퍼티 값이 반영되도록 코드를 짜둔 상태였다.
이렇게!
constants.ts
import BoxOffIcon from '../../../../public/assets/box-off.svg';
import BoxOnIcon from '../../../../public/assets/box-on.svg';
import CalendarOffIcon from '../../../../public/assets/calendar-off.svg';
import CalendarOnIcon from '../../../../public/assets/calendar-on.svg';
import FolderOffIcon from '../../../../public/assets/folder-off.svg';
import FolderOnIcon from '../../../../public/assets/folder-on.svg';
import SectionOffIcon from '../../../../public/assets/section-off.svg';
import SectionOnIcon from '../../../../public/assets/section-on.svg';
interface Board {
[key: string]: string;
}
export interface Boards {
dashboard: Board;
calendar: Board;
kanbanboard: Board;
board: Board;
}
// (link 값들은 우선 임시로 넣어 둔 상태)
export const BOARDS: Boards = {
dashboard: {
boardName: '대시보드',
iconOn: BoxOnIcon, // 이미지를 컴포넌트화 하면서 이 부분에 해당 컴포넌트를 넣어야 헀다.
iconOff: BoxOffIcon,
link: '/main',
},
calendar: {
boardName: '나의 캘린더',
iconOn: CalendarOnIcon,
iconOff: CalendarOffIcon,
link: '/schedules/1',
},
kanbanboard: {
boardName: '칸반보드',
iconOn: SectionOnIcon,
iconOff: SectionOffIcon,
link: '/myIssues/1',
},
board: {
boardName: '자유게시판',
iconOn: FolderOnIcon,
iconOff: FolderOffIcon,
link: '/teams/1/posts',
},
};
이미지들을 컴포넌트화 하면서 on/off 속성은 active 프롭값을 boolean 타입으로 넘겨주기 때문에 icon이라는 프로퍼티 하나로 통일할 수 있었다. 그런데 문제는 기존 string 타입으로 들어가던 이미지 경로값 부분에 리액트 컴포넌트가 들어가야 한다는 점.
어떻게 할지 고민하며 찾아보다가 결국엔 멘토님께 여쭤보았다.
🤔 문제 원인
일차적인 원인은 너무 간단했다. 리액트 컴포넌트를 사용하려면 .ts 확장자가 아닌 .tsx를 사용해야 한다. [1]
🤗 문제 해결
기존의 ts 확장자를 tsx로 바꾸어주면 우선 일차적인 문제는 해결.
constants.tsx
import { ReactNode } from 'react';
import BoxIcon from '@/assets/BoxIcon';
import CalendarIcon from '@/assets/CalendarIcon';
import FolderIcon from '@/assets/FolderIcon';
import ViewListIcon from '@/assets/ViewListIcon';
interface Board {
boardName: string;
icon: ReactNode; // string에서 ReactNode 타입으로 변경
link: string;
}
export interface Boards {
dashboard: Board;
calendar: Board;
kanbanboard: Board;
board: Board;
}
// (link 값들은 우선 임시로 넣어 둔 상태)
export const BOARDS: Boards = {
dashboard: {
boardName: '대시보드',
icon: <BoxIcon />, // 요렇게 컴포넌트 쇼쇽-
link: '/main',
},
calendar: {
boardName: '나의 캘린더',
icon: <CalendarIcon />,
link: '/schedules/1',
},
kanbanboard: {
boardName: '칸반보드',
icon: <ViewListIcon />,
link: '/myIssues/1',
},
board: {
boardName: '자유게시판',
icon: <FolderIcon />,
link: '/teams/1/posts',
},
};
이후에도 컴포넌트가 담긴 이 변수들을 어떻게 사용해야 할까에 대한 문제를 맞닥뜨렸다. 이 부분에 대해선 다음 포스트에 이어서 기록하려 한다.
🧠 배우고 느낀 점
tsx 코드 내에서는 컴포넌트가 값이 될 수 있다.
[1] 사실 .ts → .tsx 로 바꿔야 한다는 생각을 스스로 안 했던 건 아니다. 그런데 tsx 코드 안에서 일반 객체 리터럴로 만들어진 객체 안에 컴포넌트는 들어갈 수 없다고 생각해서 단순히 생각에 그쳤던 것이다. 컴포넌트는 리턴문 안에서만 쓸 수 있는 줄 알았는데 그게 아니었다. 앞으로는 그냥 넘어가지 말고 혹시나 싶어도 한번 시도해 보자.
'Frontend > React.js' 카테고리의 다른 글
[React] cloneElement로 변수에 담긴 컴포넌트 활용하기 (1) | 2024.11.28 |
---|---|
[React] svg 컴포넌트 만들기 (0) | 2024.11.28 |