안녕하세요, 여러분!
현재 공유 달력 앱을 개발하고 있습니다. 일정 컴포넌트를 개발하면서 겪었던 경험을 공유해보고자 합니다.
저는 null값을 넣어서 한칸을 띄우는 방식을 채택했습니다.
먼저 일정 데이터를 API 조회를 하면 일정이 배열 형태로 응답받습니다.
[
{
"scheduleId":114,
"name":"미용실",
"startDate":"2024-05-24T03:35:34.385Z",
"endDate":"2024-05-24T03:35:34.385Z",
...
}
...
]
로직 순서
1. 데이터가 없으면 빈배열로 초기화
2. 시작 날짜와 종료 날짜가 동일하면 한개의 데이터만 저장후 바로 종료
3. 시작 날짜의 배열 Length와 종료 날짜의 배열 Length를 비교해서 큰 숫자와 동일하게 null값을 추가하여 높이를 맞춥니다
4. 시작 날짜의 startingDay와 종료 날짜의 endingDay를 true로 표시해줍니다.
5. 시작 날짜와 종료 날짜사이에 배열들도 3번과 같은 의미로 null값을 추가하여 높이를 맞춰줍니다.
const periodsData : { [date: string]: (ISchedule | null)[] } = {}
events.forEach((event) => {
const startDate = format(event.startDate, 'yyyy-MM-dd');
const endDate = format(event.endDate, 'yyyy-MM-dd');
//1. 시작 날짜가 periodsData에 없으면 생성
if (!periodsData[startDate]) {
periodsData[startDate] = [];
}
//1. 종료 날짜가 periodsData에 없으면 생성
if (!periodsData[endDate]) {
periodsData[endDate] = [];
}
//2. 시작 날짜와 종료 날짜가 동일한 경우
if (startDate === endDate) {
periodsData[startDate].push({
...event,
startingDay: true, // 일정의 시작
endingDay: true, // 일정의 종료
});
} else {
const startLength = periodsData[startDate].length;
const endLength = periodsData[endDate].length;
//3. 시작 날짜와 종료 날짜를 비교해서 같은 높이로 맞추기
if (startLength > endLength) {
while (periodsData[endDate].length < startLength) {
periodsData[endDate].push(null);
}
} else if (endLength > startLength) {
while (periodsData[startDate].length < endLength) {
periodsData[startDate].push(null);
}
}
//4. 시작 날짜에 시작 표시
periodsData[startDate].push({
...event,
startingDay: true,
endingDay: false,
});
//4. 종료 날짜에 끝 표시
periodsData[endDate].push({
...event,
startingDay: false,
endingDay: true,
});
//5. 시작 날짜와 종료 날짜 사이의 날짜들에 대한 표시
let currentDate = new Date(startDate);
currentDate.setDate(currentDate.getDate() + 1);
while (currentDate < new Date(endDate)) {
const middleDate = format(currentDate, 'yyyy-MM-dd');
if (!periodsData[middleDate]) {
periodsData[middleDate] = [];
}
const middleLength = periodsData[middleDate].length;
// 시작 날짜와 중간 날짜를 비교해서 같은 높이로 맞추기
if (startLength > middleLength) {
while (periodsData[middleDate].length < startLength) {
periodsData[middleDate].push(null);
}
}
periodsData[middleDate].push({
...event,
startingDay: false,
endingDay: false,
});
currentDate.setDate(currentDate.getDate() + 1);
}
}
});
{
"2024-06-22":[
null,
{
"scheduleId":122,
"name":"일정2",
"startDate":"2024-06-20T07:36:29.196Z",
"endDate":"2024-06-22T07:36:29Z",
"startingDay":false,
"endingDay":true
},
],
...
}
Day 컴포넌트에서 해당하는 날짜를 검색하고 null일 경우 한칸 띄우는 View를 구성하는 것으로 해결했습니다.
"공달이" 프로젝트를 하면서 가장 어려웠던 부분이라 생각합니다. 최대한 단순하게 구현을 해야 성능이라든지 유지 비용에 효율성을 높일 수 있다고 생각했습니다.
초반에 분석하고 설계를 잘 해놓으면 개발하는데 속도가 붙는다고 느끼게 되었습니다.