본문 바로가기
제니의 개발일지/도움이 되었던 것 정리

IntersectionObserver 스크롤 감지

by 제니운 2022. 12. 14.
728x90

 

 

 

IntersectionObserver 를 활용해 스크롤 애니메이션을 만드는 방법을 열심히 고민했다.

 

✅ 일반적으로 사용하는 scroll 이벤트의 경우, 스크롤을 아래로 내려도 저장이 되지 않기 때문에 기능 부하가 발생해 효율적이지 못하다.

 

✅ 'scroll'을 사용하면 스크롤 이후의 css는 props를 사용하게 되는데, 그렇게 되면 코드 량이 많아져 비효율적으로 코드를 작성하게 된다. IntersectionObserver 를 사용하면 style-components에서 바로 작업할 수 있다.

 

 

사실 scroll을 사용해서 하는 기능이나, IntersectionObserver 를 활용해서 만드는 기능이나 크게 어려움이 다르지 않았는데 새로운 도전을 하려니 머뭇거리게 되서 scroll 부터 사용을 해버렸는데 처음부터 도전할 걸 그랬다.. ㅎㅎ

 

 

일단 어려우면 그대로 사용해도 문제 없다! 

 

 

1️⃣ observer 코드 작성

 

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    if(entry.isIntersecting){
      entry.target.classList.add('active');
    }
  });
});

 

🔹 entry.target.classList.remove('active') 위 코드를 else 구문에 넣어서 이벤트를 반복, 고정할 수 있다.

 

 

2️⃣ 어디서부터 감지할 건지 + 어디에 적용할 건지

 

const scrollEvent = document.querySelectAll('.header');

scrollEvent.forEach((el) => observer.observe(el));

 

 

🔹 querySelectAll('.header') : .header 처럼 한 이유는 className에서 가져왔기 때문이다. id를 가져오거나 할 경우엔 맞춰서 변경하면 된다.

 

 

🔹 에러가 날 경우 : Property 'forEach' does not exist on type 'HTMLCollectionOf<Element>'

- forEach에서 에러가 나는 경우, 배열 구조로 하지 않았거나 getElementById 처럼 사용했을 때 에러가 났다. querySelectAll 구조로 사용하면 에러 없이 사용 가능하다.

 

 

 

3️⃣ 리액트 함수 밖으로 observer 함수 빼기

 

🔹 함수 안에 있을 경우, observer 코드가 계속 돌기 때문에 아래 코드 처럼 함수 밖으로 빼주는 것이 좋다.

 

 

observer 함수 여기로 빼기

const App:React.FC = () => {
  return()
}

 

 

4️⃣ 코드 리팩토링

 

🔹 className, 예를 들어 header, logo 이런 식은 document를 사용했을 때 다른 화면에서 작동되어버릴 수 있으므로, 해당 화면에서만 작동하게 코드를 수정한다.

 

 

const scrollEvent = document.querySelectorAll(`${Container} . logo`);


// 원래 코드
const scrollEvent = document.querySelectorAll('.logo');

 

위 내용처럼 코드를 바꾸면 Container라는 안에 logo className만 가져오게 할 수 있다.

 

 

 

5️⃣ 렌더링 될 때만 작동하도록 useEffect 사용해주기

 

useEffect(() => {
  const scrollEvent = document.querySelectorAll(`${Container} .logo`);
  
  scrollEvent.forEach((el) => observer.observe(el));
}, []);

 

간단하게 그냥 useEffect 안으로 넣어주면 끝이다.

 

더 좋은 방법도 많이 있겠지만 여기까지 하면 효율적인 코드로 리팩토링까지 끝!

728x90