01.11 TIL

천영석·2021년 1월 11일
post-thumbnail

각종 버그 수정

스크롤을 매우 빠르게 올리거나 내릴 때

이 버그를 해결하기 위해 3일 정도의 시간이 걸렸다.
스크롤에 따른 버그는 아래의 두 가지가 있었다.

✔ 0번 -> 2번 scene으로 빠르게 스크롤 했다고 가정했을 때 2번 scene에서 0번 scene으로 갈 때 0번 scene에서 아주 잠깐 스크롤을 할 때의 이미지가 나오는 것
✔ 3번 scene의 sticky class가 지워지지 않는 것

첫 번째 스크롤 버그

첫 번째 버그는 더 부드러운 스크롤을 위해 가속도가 적용된 pageYOffset을 사용해서 나타난 버그로 기존의 pageYOffset으로 사용했을 때 나타나지 않는 버그임을 이용해 해결할 수 있었다.
우선, 가속도가 적용된 pageYOffset의 코드는 아래와 같다.

const acc = 0.1;
let delayedPageYOffset;
delayedPageYOffset = delayedPageYOffset + (pageYOffset - delayedPageYOffset) * acc;

이렇게 가속도가 적용된 pageYOffset을 사용하는 이유는 부드러운 스크롤을 위해서이고, 그래서 requestAnimationFrame을 사용했다.

만약 0에서 100으로 pageYOffset이 이동했다면 가속도인 0.1의 비율만큼 delayedPageYOffset이 증가할 것이고, 이를 rAF에 할당했기 때문에 부드럽게 증가되는 것을 확인할 수 있다.
rAF의 종료 조건은 pageYOffset과 delayedPageYOffset의 차이가 1 미만일 때로 설정했다.

이때, 스크롤을 너무 빠르게 해서 10000px부터 0px까지 한 번에 스크롤을 했다고 생각해보자.
그리고 scene은 2개로 각각의 높이가 5000px이라고 하자.
그러면 10000 -> 9000 -> 8100 -> 7290 ... -> 1까지 줄어들 것이다.

하지만 현재 설정해놓은 currentScene 즉, 현재 pageYOffset의 위치에 따른 scene의 값은 delayedPageYOffset이 아닌 pageYOffset을 기준으로 하고 있다.
그래서 위처럼 값이 감소하고 있는 동안에 currentScene은 pageYOffset인 0을 기준으로 하기 때문에 첫 번째 scene을 가리키고 있다.

요약하면 두 번째 scene은 스크롤 하기 이전의 그림에 멈춰있으면서 첫 번째 scene의 그림을 그리고 있는 것이다.
그래서 다시 두 번째 scene으로 넘어갈 때, 잠깐 이전의 그림이 표시되는 것이었다.

이를 해결하기 위해 currentScene 자체를 pageYOffset이 아닌 delayedPageYOffset으로 해보았지만 이건 위와 반대의 오류가 발생했다. currentScene이 두 번째 scene에 멈춰있는 것이다. 그래서 첫 번째 scene에 두 번째 scene의 그림이 그려졌다.

결국 scene이 넘어갈 때마다 한 번씩 초기화를 해주는 것으로 해결했다.
첫 번째 scene에서 두 번째 scene으로 넘어가면 첫 번째 scene의 마지막 이미지를 그려주고, 두 번째 scene에서 첫 번째 scene으로 넘어가면 두 번째 scene의 첫 번째 이미지를 그려주는 식이다.

이 코드는 하드코딩의 느낌이 있어서 좋은 코드가 아닌 것 같다. 언제는 마지막 이미지를 그려야 하고, 언제는 첫 번째 이미지를 그려야 하는지를 알려줘야 하기 때문이다. 그래도 이 방법이 3일 간 생각한 나만의 최선의 방법이라고 생각했고, 현재는 아무 오류 없이 동작하기 때문에 만족하고 있다. 성능에도 별 차이가 없는 것도 확인했다.

강의에서도 알려주지 않은 버그를 해결할 수 있어서 시간은 오래 걸렸지만 코딩의 즐거움을 느낄 수 있었다.

두 번째 스크롤 버그

이 버그의 원인은 첫 번째 버그의 원인과 같은데 마지막 scene에서 특정 위치가 되면 sticky라는 class를 추가하고, 특정 위치가 되면 제거하도록 코드를 작성했다.
하지만 추가하거나 제거하는 것을 마지막 scene에서만 하도록 switch문으로 작성했기 때문에 매우 빠르게 스크롤을 올렸을 경우 currentScene은 마지막 scene이 아니기 때문에 sticky class가 삭제되지 않는 것이었다.

그래서 이 버그도 마지막 scene이 아니면서 class에 sticky가 들어가 있을 때 sticky를 삭제하도록 해서 버그를 해결했다.

html에 footer 태그를 사용해서 최하단에 위치시킬 생각이었는데, 각 scene들은 height가 고정되어 있고, 마지막 scene에서 margin-top을 할당해야 하는 상황때문에 footer태그가 최하단이 아닌 살짝 위로 올라가서 마지막 scene의 글을 가리게 되었다.

이를 해결하기 위해 마지막 scene의 마지막 문단의 위치를 알아야만 했고, 상대위치, 절대위치에 대해 공부를 하게 되었다.

우선, 상대위치는 viewport를 기준으로 얼만큼 떨어져있는지에 관한 것으로 getBoundingClientRect() 메소드를 사용할 수 있다.
여기에서 getBoundingClientRect().top을 통해 viewport 기준 top에서 얼만큼 떨어져 있는지에 대한 값이 나오게 된다.

절대위치는 window.pageYOffset + getBoundingClientRect().top을 통해 절대위치를 구할 수 있다.

이를 통해 footer의 위치를 하단으로 고정할 수 있게 되었다.

profile
느려도 꾸준히 발전하려고 노력하는 사람입니다.

0개의 댓글