✍️ 서론
덕타운은 기숙사 어플인만큼 리스트뷰가 많다.


그런데 보다시피 같은 리스트뷰더라도 형식이 매번 다르다.
나는 각 셀을 열과 행의 묶음으로 보았고 그렇다면 테이블로 표현하는 것이 좋겠다고 생각했다.
그리고 여러 화면에서 쓰니 이를 컴포넌트로 만들고자 했다.

여기서 셀이란 위의 그림의 빨간 테두리이다.(그냥 나 혼자 그렇게 칭한다.)
사진 속 셀은 주황색 선을 기준으로 행이 나뉘고 연두색 선을 기준으로 첫번째 행에서 열이 나뉜다.
👾 목표
여러 화면에서 활용 가능한 테이블 컴포넌트를 만들자!
☘️ 진행 과정
테이블에 채워질 내용들은 대체적으로 서버에서 받아온 배열 속 값들이다. 따라서 컴포넌트는 배열을 받아야한다.
또한 각 테이블에 채워질 내용은 페이지마다 형식이 다르므로 이를 지정할 클래스명이 필요하다.
요구사항에 맞게 컴포넌트는 다음과 같이 사용하고자 했다.
<TableView
tableFor='클래스명'
items = {[{id:1, date: '2023.12.16', title: '제목1'}, {id:2, date: '2023.12.09', title: '제목2'}]}
/>
`tableFor`은 말 그대로 @@ 페이지에 쓸 페이지라는 의미로 클래스명을 지정하는 라벨이다.
`items`는 서버로부터 받아온 데이더 배열이다. 현재 서버와 연결된 상태가 아니므로 더미데이터를 넣어두었다.
처음엔 '열의 개수를 받아서 조절하면 되겠지'라고 생각했는데 하다보니 그게 그렇게 생각보다 뚝딱되는 작업이 아니었다.
어떻게 할까 고민하다가 클래스명에 따라서 서로 다른 테이블 뷰를 만들어서 리턴하는 방식으로 바꾸었다.
그렇게하면 굳이 컴포넌트로 할 필요가 있나 싶지만 곂치는 화면이 있을 때 재사용할 수 있고 그렇지 않더라도 컴포넌트를 사용하는 화면에선 코드가 깔끔해보이니 상관없다고 생각했다.
function TableView({ items, tableFor }) {
let table = [];
switch (tableFor) {
case 'repair':
const repairTableArr = items.map(item => {
let rows = [];
const createCols = () => {
let cols = [];
cols.push(<td className='dateCol'>{item.date}</td>);
cols.push(<td className='contentCol'>{item.content}</td>);
cols.push(<td className='confirmCol'>{item.confirm}</td>);
cols.push(<td className='statusCol'>{item.status}</td>);
return cols;
}
rows.push(<tr className='tableRow'>{createCols()}</tr>);
return rows;
})
table = repairTableArr;
break;
case 'noticeList':
const noticeListTableArr = items.map(item => {
const today = new Date();
const itemDate = new Date(item.date);
const isNew = (itemDate.getFullYear()===today.getFullYear())&&(itemDate.getMonth()===today.getMonth())&&(itemDate.getDate()===today.getDate());
let rows = [];
const createCols = () => {
let cols = [];
cols.push(
<td className='titleCol'>
<div className='titleCol_abbr_container'><abbr className={isNew ? 'new' : 'old'}>N</abbr></div>
<Link className={isNew ? 'newA' : 'oldA'} to={`/notice/list/detail/${item.id}`}>{item.title}</Link>
</td>
);
return cols;
}
rows.push(<tr className='tableRow1'>{createCols()}</tr>);
rows.push(<tr className='tableRow2'><td colSpan={2}> {item.date}</td></tr>);
rows.push(<tr className='space'/>);
return rows;
})
table = noticeListTableArr;
break;
}
return (
<table className={tableFor}>
{table}
</table>
);
}
코드가 너무 길어서 구성이 다른 두 케이스만 가져왔다. 'repair'는 행이 한 개이지만 'noticeList'는 행이 여러 개이다.
구성과 상관없이 각 테이블은 열에 담길 내용을 `cols`라는 배열에 먼저 추가하고, 그 다음 행에 담길 내용을 `rows`라는 배열에 추가한다.
이는 하나의 셀을 생성하는 것이므로 items 속 item의 개수만큼 이를 반복한다.
그리고 완성이 된 행 배열을 switch문 바깥의 `table`이라는 배열에 추가한다.
'repair'는 행이 한 개이기 때문에 `createCols()`로 열을 먼저 구성한 후 이를 행에 추가했다.
반면 'noticeList'는 행이 여러 개이기 때문에 'repair'과 동일하게 첫 번째 행을 추가하고 다른 행들을 추가했다.
🧐 느낀점
뭔가 더 간단한 방법이 있지 않을까 계속 고민했는데 결국 나는 찾지 못했다.
매번 어떻게 셀을 구성할까 고민되지만 테이블로 리스트를 구현할 수 있게 되어 뿌듯하다!
'Project > Duktown' 카테고리의 다른 글
| [DukTown/React] 데이터 전송 후 새로고침 (1) | 2023.12.01 |
|---|