드림컴트루..
팀프로젝트를 하면서 매일 출근해서는 팀 관리 및 담당 작업을 진행하고
집에와서 2~3시간동안은 기획단계에서는 하지 않았던
하지만 한 번쯤 다른 웹 사이트에서 봤던 소소한 잔기능들을 추가하는 일을 하고 있었다.
매일 매일 잔기능을 1개씩 추가할 때마다 내가 느끼는 기분
커다란 메인 기능은 아니지만 잔잔바리 기능을 하루에 하나씩 추가할 때마다 뿌듯함이 늘어난다
2~3주차에, 정규 작업시간에는 예약 페이지와 마이페이지 작업을 하고
귀가 후에는 내가 해보고 싶었던 기능이나 UI를 만들어서 다음날 팀원들에게 슬쩍 보여주기.
자주 방문하는 웨이브 홈페이지에 하단에 가면 공지사항 리스트가 상하로 롤링을 한다.
화살표도 있는걸 보면 캐러셀이 맞는 것 같긴한데 ㅜㅜ 상하로 도는 캐러셀을 팀 작업 초기에 찾았다가 어디서 봤는지 기억이 안나더라 ㅜㅜ 이래서 기록을 해야하는데 까먹었다...
우리가 평소에 사용하던 캐러셀은 좌우가 대부분이어서 쓰던 캐러셀을 쓸 순 없었고
css 부분을 제외한 코드
useEffect와 setInterval()을 사용해서!!!!
export default function Notice() {
const [idx, setIdx] = useState(0);
const idxRef = useRef(0);
const notice = [
{
no: 1,
header: "[안내]",
title: "7월 신용카드 무이자 할부 안내",
date: "2022-07-01",
},
{
no: 2,
header: "[점검]",
title: "7/20 시스템 점검 안내",
date: "2022-07-13",
},
{
no: 3,
header: "[안내]",
title: "7월 정기 휴무 안내",
date: "2022-07-19",
},
{
no: 4,
header: "[수정]",
title: "개인정보 처리방침, 청소년 보호정책 개정안 공지",
date: "2022-07-22",
},
{
no: 5,
header: "[안내]",
title: "roominus 제휴 문의 안내",
date: "2022-07-24",
},
];
useEffect(() => {
setInterval(() => {
idxRef.current = (idxRef.current + 1) % notice.length;
setIdx(idxRef.current);
console.log(idxRef);
}, 4000);
}, [notice.length]);
return (
<Container>
<Wrapper style={{ transform: `translateY(-${70 * idx}px)` }}>
{notice.map((el, idx) => {
return (
<Content key={idx}>
<NoticeBox>
<span>{el.header}</span>
<Title>{el.title}</Title>
<span>{el.date}</span>
</NoticeBox>
</Content>
);
})}
</Wrapper>
</Container>
);
}
신기하다!!!
그 후 추가
공지사항 리스트 롤링에서 발견한 에러 ㅜㅜ
메모리 문제가 어디서 발생하는지 찾기 위해 곳곳의 콘솔을 확인해 보다가 발견하였다.
너무 치명적인 에러 같았는데, 롤링 페이지를 만들어 놓고 여태까지 모르고 있었다....
useEffect의 setInterval() 함수를 종료하지 않아서 메모리 문제가 발생할 수도!!
물론 이 공지사항은 사용하고 있는 백엔드 api도 없고, 그냥 하드 코딩한 부분이 보여지고 있었어서,
당장은 큰 문제가 발생하지 않았다고 생각한ㄷ.
하지만 만약 내가 api를 받아서 하고 있었다면?
백엔드 서버에 무리를 주었을 수도 있다는 생각에 아찔했다.
문제가 되는 부분은 이 부분이다.
구성 요소가 다시 렌더링되거나 마운트가 해제될 때마다 정리 기능이 타이머를 지워서
메모리 누수를 방지하는 데 도움이 된다고 한다.
이런 부분을 잘 이해하려면, 리액트 컴포넌트의 생명 주기를 제대로 알고 있었어야 하는 구나를 깨닫게 되었다.
결과적으로 수정하기는 했지만, 조금 불안해서 css로만 활용해서 롤링하는 공지사항으로 변경하였다.
어떤게 좋은 코드이고 나쁜 코드인지 파악이 안되는 상태에서 돌아가기만 하면 넘어가다보니 조금 실수가 있었던 것 같다. 좀 속상했던 부분이다. 내가 useEffet를 비롯해서 제대로 파악하고 있었다면 setInterval을 사용하고 꼭 clean up 시켜야하는 것을 알아챘을텐데, 많이 반성했다.
공지사항을 아예 빼고 싶지는 않아서, css로 롤링하는 데모를 코드젠에서 찾았다.
해당 코드를 우리 공지사항에 맞게 수정해서 애니메이션, 키프레임을 활용한 롤링을 구현했다.
import styled from "@emotion/styled";
import { Router, useRouter } from "next/router";
import { breakPoints } from "../../../../commons/styles/media";
const Container = styled.div`
width: 100%;
`;
const Wrapper = styled.div`
display: flex;
font-size: 1.3em;
justify-content: space-around;
border-top: 1.5px solid #4a00e0e7;
border-bottom: 1.5px solid #4a00e0e7;
text-align: center;
@media ${breakPoints.tablet} {
font-size: 1.1em;
}
@media ${breakPoints.mobile} {
font-size: 1em;
}
`;
const Flip = styled.div`
height: 50px;
overflow: hidden;
@media ${breakPoints.tablet} {
height: 45px;
}
@media ${breakPoints.mobile} {
height: 45px;
}
> div > div {
padding-bottom: 0.7em;
padding-left: 1em;
margin-bottom: 3em;
display: inline-block;
color: #26282c;
@media ${breakPoints.tablet} {
padding-bottom: 1.7em;
}
@media ${breakPoints.mobile} {
padding-bottom: 2.5em;
}
}
div:first-child {
animation: show 13s linear infinite;
}
div div {
}
div:first-child div {
padding-top: 10px;
}
div:last-child div {
padding-top: 2em;
}
@keyframes show {
0% {
margin-top: -250px;
}
5% {
margin-top: -180px;
}
33% {
margin-top: -180px;
}
38% {
margin-top: -90px;
}
66% {
margin-top: -90px;
}
71% {
margin-top: 0px;
}
99.99% {
margin-top: 0px;
}
100% {
margin-top: -270px;
}
}
`;
const ContentBox = styled.div`
width: 30em;
@media ${breakPoints.mobile} {
width: 13em;
}
`;
const Contents = styled.div`
text-align: left;
width: 100%;
:hover {
cursor: pointer;
}
`;
const Date = styled.div``;
export default function Notice() {
const router = useRouter();
const onClickMoveToNotice01 = () => {
router.push("/customer/notice/01");
};
const onClickMoveToNotice02 = () => {
router.push("/customer/notice/02");
};
const onClickMoveToNotice03 = () => {
router.push("/customer/notice/03");
};
return (
<Container>
<Wrapper>
<Flip>
<div>
<div>[안내]</div>
</div>
<div>
<div>[안내]</div>
</div>
<div>
<div>[공지]</div>
</div>
</Flip>
<Flip>
<ContentBox>
<Contents onClick={onClickMoveToNotice01}>
신용카드 무이자 할부 안내
</Contents>
</ContentBox>
<ContentBox>
<Contents onClick={onClickMoveToNotice03}>
8월 3일 시스템 점검 안내
</Contents>
</ContentBox>
<ContentBox>
<Contents onClick={onClickMoveToNotice02}>8월 휴무 안내</Contents>
</ContentBox>
</Flip>
<Flip>
<div>
<div>2022-08-03</div>
</div>
<div>
<div>2022-08-01</div>
</div>
<div>
<div>2022-07-30</div>
</div>
</Flip>
</Wrapper>
</Container>
);
}