가수면
조건부 css 본문
포트폴리오에 넣을 프로젝트를 새롭게 시작했다.
기획했었던 아이템도 중간에 엎어지고 새로운 기술 스택도 도입하려다 보니 많은 것들을 하진 못했지만, 머리 터질듯 고민했었던 코드들도 있었다.
이번 주 익힌 것들
- 타입스크립트 (계속 공부 중)
- 리액트 쿼리 v4 (계속 공부 중)
- 라우터 v6
- React Hook Form 라이브러리
- 달력 구현하기 (공휴일 적용)
트러블 슈팅
- React Hook Form에 유효성에 따른 css 입히기 -
라이브러리는 최대한 덜고 가고 싶었지만 React Hook Form도 한번 다뤄보자는 팀원의 말을 따르기로 함.
유효성에 따라 alert창 없이 인풋창의 테두리 색이 서서히 바뀌었으면 좋겠다는 요구를 반영하던 중, 라이브러리를 커스텀하는 데 어려움이 있었다.
해결 과정 및 해결
(1) 입력값 or 상태값에 따라 css가 바뀌어야 하니 그 값을 활용하면 되겠다고 판단.
(2) 그러나 입력값과 상태값이 일반적인 방법으로는 console을 찍어볼 수 없는 형태였기에 라이브러리를 하나하나 뜯어보며 활용해 볼 만한 값을 찾기 시작함.
(2) 한참을 헤매다가 errors가 뱉어내는 메시지에 따라 유효성이 걸러지는 것에 주목.
(3) 초기값과 유효성을 통과했을 때는 errors가 undefined를 출력하고, 통과하지 못했을 때는 유효성을 걸어 놓은 조건이 출력되는 것을 확인.
(4) input 태그의 className에 아래와 같은 방식으로 코드를 입력해 해결했다.
className={errors?.password.type === undefined ? "pass" : "fail"}
- 달력 구현 -
date picker나 input의 date타입을 사용하면 쉽게 해결할 수 있겠지만, 디자이너가 뽑아주는 그림에 따라 커스텀을 해야될 수도 있었고, 개인적으로 무게나 성능면에서 불필요하게 라이브러리를 사용하는 것은 별로 좋아하지 않았기에 직접 달력을 만들어 보기로 함.
해결 과정 및 해결
(1) 구글에 떠도는 레퍼런스들은 죄다 라이브러리를 섞거나 바닐라 자바스크립트로만 이루어진 것들이었기에 리액트에 잘 어우러질 만한 코드로 작성하기 위해 로직을 이해하고 적용하는 데 시간이 걸림.
(2) 달력 완성
(3) 추가로 공휴일도 적용되었으면 좋겠다는 요구를 받음. 레퍼런스들을 찾을 순 없었지만 대략적인 로직이 머릿속에 그려져서 수락함.
(4) 공공 데이터 포탈에서 인증키를 발급받아 공휴일 API를 axios로 받아옴.
(5) 받아온 데이터가 '20230108' 과 같이 숫자가 담긴 배열 형태였는데 내가 짜놓은 달력의 로직은 연도, 월별, 일별로 나뉘어 각각 number 타입이라 숫자 앞에 0이 붙지 않은 상태였고, 따라서 생각보다 일이 조금 복잡해진 상황.
(6) 달력의 로직을 통째로 바꿔야하나 받아 온 데이터를 가공해야하나 저울질하다가 후자가 더 쉽겠다는 판단에 작업 돌입
(7) 공휴일 배열을 filter로 돌림 -> 요소들의 형태를 문자열로 바꿈 -> 월 부분 자름 -> 다시 숫자로 형태 변경 -> 현재 달과 비교 ->
filter로 걸러낸 배열을 다시 map으로 돌림 -> 요소를 문자열로 변경 -> 일 부분 자름 -> 다시 숫자로 변경
(8) 공휴일에 해당되는 날짜를 빨간색 글씨로 출력해내는 과정에서 className안에서 연산해야하는 제약 때문에 난관에 봉착.
(9) className 안에다가 삼항 연산자 말고 조건이나 로직을 집어넣는 방법이 없나 찾아봤지만 라이브러리를 사용하는 것 말고는 방법을 찾지 못 함. 안 그래도 6번 과정에서 비효율적인 연산들이 들어갔는데 최대한 라이브러리 말고 삼항 연산자를 사용해 해결하는 방법이 없나 모색
(10) for문 안에 새로운 for문을 돌려보다가 실패
(11) className 안에서 map을 돌려봤지만 실패
(12) 기타 기억도 나지 않는 잡다한 시도들 전부 실패
(13) 이거 for문으로 돌리면 될 것 같은데 className 안에서는 어떻게 못 돌리나...하다가 그렇다면 차라리 밖에서 돌린 데이터를 가져오면 되지 않을까라는 생각에 도달.
(14) className에 compare(i)라는 함수를 적고 밖에서 compare 함수를 짜 리턴해주는 것으로 해결.
const returnDay = useCallback(() => {
let dayArr = []
let holidayMonth = holiday.filter(v => parseInt(String(v).substring(4, 6)) === selectedMonth)
let holidayDate = holidayMonth.map(v => parseInt(String(v).substring(6, 8)))
const compare = (i) => {
for (let h = 0; h <= holidayDate.length; h++) {
if (holidayDate[h] === i) return true
}
}
for (const today of week) {
const day = new Date(selectedYear, selectedMonth - 1, 1).getDay();
if (week[day] === today) {
for (let i = 1; i <= lastDay; i++) {
dayArr.push(
<button key={i}
className={new Date(selectedYear, selectedMonth - 1, i).getDay() === 0 || compare(i) ?
"weekday sunday" :
(new Date(selectedYear, selectedMonth - 1, i).getDay() === 6 ? "weekday saturday" : "weekday")}
onClick={() => setSelectedDate(`${selectedYear}년 ${selectedMonth}월 ${i}일`)} >
{i}</ button >
)
}
} else {
dayArr.push(<div key={today} className="weekday"></div>)
}
}
return dayArr
}, [selectedYear, selectedMonth, lastDay, holiday])
해결해야 하는 과제
공휴일 데이터를 가공하는 과정이 너무 비효율적이라는 생각이 듦.
후에 달력 로직을 공휴일 데이터를 잘 활용할 수 있는 로직으로 리팩토링하는 것이 좋아보인다.