728x90
안녕하세요 오늘은 React에서 IntersectionObserver API를 활용해 특정 컴포넌트가 화면에 진입할 때 부드럽게 나타나는 효과를 구현해보겠습니다. React에서 scroll 이벤트 없이 간단하게 등장 애니메이션을 만드는 예제입니다.
IntersectionObserver란?
보통 스크롤에 반응하는 UI를 만들 때 scroll 이벤트를 사용하지만,
이 방법은 성능 저하, 여러 컴포넌트 관리의 복잡성 등의 문제가 생길 수 있습니다.
이런 문제를 해결해주는 게 바로 IntersectionObserver입니다.
"요소가 뷰포트에 들어왔는지"를 관찰해서 이벤트 없이도 실행을 제어할 수 있는 브라우저 API입니다.
먼저 FadeInSection 컴포넌트를 만들어줍니다.
1. FadeInSection.jsx
import { useEffect, useRef, useState } from "react";
const FadeInSection = ({ children }) => {
const ref = useRef();
const [isVisible, setVisible] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setVisible(true);
observer.unobserve(ref.current); // 한 번만 작동
}
},
{ threshold: 0.2 }
);
observer.observe(ref.current);
return () => observer.disconnect();
}, []);
return (
<div
ref={ref}
className={`transition-all duration-[2000ms] ease-in-out transform p-6 bg-white dark:bg-gray-800 rounded shadow ${
isVisible ? "opacity-100 translate-y-0" : "opacity-0 translate-y-12"
}`}
>
{children}
</div>
);
};
export default FadeInSection;
- entry.isIntersecting이 true가 되는 순간을 감지합니다.
- observer.unobserve()를 사용해 한 번만 작동하게 설정했습니다. 페이지 최초 진입했을 때 한번만 실행됩니다.
- Tailwind CSS로 애니메이션 적용하였습니다.
2. App.jsx
import Header from "./components/Header";
import Hero from "./components/Hero";
import About from "./components/About";
import Contact from "./components/Contact";
import ThreeDPortfolio from "./components/ThreeDPortfolio";
import AvatarPortfolio from "./components/SimpleAvatar";
import ProjectGallery from "./components/ProjectGallery";
import StatsSection from "./components/StatsSection";
import ServicesSection from "./components/ServicesSection";
import BlogSlider from "./components/BlogSlider";
import ParticlePortfolio from "./components/ParticleSystem";
import SimpleCounter from "./components/SimpleCounter";
import SimpleTodo from "./components/SimpleTodo";
import SimpleCalculator from "./components/SimpleCalculator";
import VideoBackground from "./components/VideoBackground";
import { motion, useScroll } from "motion/react";
import FadeInSection from "./components/FadeInSection";
function App() {
const { scrollYProgress } = useScroll();
return (
<>
<motion.div
id="scroll-indicator"
style={{
scaleX: scrollYProgress,
position: "fixed",
top: 0,
left: 0,
right: 0,
height: "10px",
originX: 0,
backgroundColor: "#ff0088",
zIndex: 9999,
transformOrigin: "0% 50%",
}}
/>
<div style={{ minHeight: "200vh" }}>
{" "}
{/* 충분한 스크롤을 위한 임시 높이 */}
<VideoBackground />
<Header />
<Hero />
<FadeInSection>
<About />
</FadeInSection>
<FadeInSection>
<ServicesSection />
</FadeInSection>
<FadeInSection>
<StatsSection />
</FadeInSection>
<ProjectGallery />
<BlogSlider />
<SimpleCounter />
<SimpleTodo />
<SimpleCalculator />
<ThreeDPortfolio />
<AvatarPortfolio />
<ParticlePortfolio />
<Contact />
</div>
</>
);
}
export default App;
- 메인 컴포넌트 파일인 App.jsx 에 FadeInSection 파일을 import 해줍니다.
- 원하는 컴포넌트를 감싸줍니다.
- 복잡한 scroll 이벤트 제어나 클래스 토글 없이, 상태와 observer가 내부에서 자동으로 처리됩니다.
시연 영상입니다.
<FadeInSection> 으로 감싼 컴포넌트가 부드럽게 fade in 되는 것을 확인할 수 있습니다.
'React' 카테고리의 다른 글
[React] react-hot-toast 사용하여 토스트 알림 UI 간편하게 만들기 (3) | 2025.07.30 |
---|---|
[React] react-simple-typewriter로 타이핑 효과 쉽게 구현하기 (0) | 2025.07.29 |
[React] 홈페이지 메인화면에 배경 영상 추가하기 (2) | 2025.07.26 |
[React] Tailwind CSS와 useState를 활용한 간단한 계산기 구현 (0) | 2025.07.24 |
[React] Tailwind CSS 라이브러리 사용해 페이지네이션 구현하기 (3) | 2025.07.24 |