초기 페이지 로딩 후 빠른 페이지 전환이 가능해 사용자 경험이 향상됩니다.
서버 부하가 줄어듭니다.
검색 엔진 최적화(SEO)에 불리할 수 있습니다.
초기 페이지 로딩 속도가 느릴 수 있습니다.
import React, { useEffect, useState } from 'react';
const App = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
return (
<div>
{data ? <div>{data.message}</div> : <div>Loading...</div>}
</div>
);
};
export default App;
import React from 'react';
const App = ({ data }) => (
<div>
{data ? <div>{data.message}</div> : <div>Loading...</div>}
</div>
);
export async function getServerSideProps() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return { props: { data } };
}
export default App;
빌드 타임 렌더링: 빌드 과정에서 모든 페이지가 미리 렌더링되어 정적인 HTML 파일로 생성됩니다.
빠른 로딩 속도: 사용자가 페이지를 요청할 때 이미 완전히 렌더링된 HTML 파일을 제공하므로 매우 빠르게 로딩됩니다.
SEO에 유리: 검색 엔진 크롤러는 완전히 렌더링된 HTML 페이지를 바로 크롤링할 수 있어 SEO에 유리합니다.
변경 시 재배포 필요: 콘텐츠 변경이 있을 경우, 웹사이트를 다시 빌드하고 배포해야 합니다.
// pages/index.js
import React from 'react';
export default function Home({ posts }) {
return (
<div>
<h1>Blog Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
// getStaticProps 함수는 빌드 타임에 데이터를 가져와서 페이지에 전달합니다.
export async function getStaticProps() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await res.json();
return {
props: {
posts,
},
};
}
| 특징 | CSR | SSR | SSG |
|---|---|---|---|
| 초기 로딩 속도 | 느림 (초기 JavaScript 로드 필요) | 빠름 (완전히 렌더링된 HTML 제공) | 매우 빠름 (정적 HTML 제공) |
| 페이지 전환 속도 | 빠름 (클라이언트 측에서 JavaScript로 처리) | 느림 (서버 요청 필요) | 빠름 (정적 HTML 제공) |
| SEO | SEO에 불리할 수 있음 | SEO에 유리 | SEO에 유리 |
| 서버 부하 | 낮음 | 높음 | 매우 낮음 |
| 개발 복잡도 | 클라이언트 측 로직에 집중 (단순할 수 있음) | 서버와 클라이언트 모두 다룸 (복잡할 수 있음) | 데이터 변경 시 재빌드 필요 (유연성 부족) |
디자이너 분이 기획한 건 전체 행성 중 3개를 먼저 보여주고, 슬라이더 시에 나머지 행성들을 순차적으로 로테이션 도는 방식인데

제가 구현한 건 아예 처음부터 화면에 6가지의 행성이 전부 보여지는 것이기에 기획했던 거랑 다르게 흘러가는 것 같아서 코드를 일부 수정했습니다.
기존 행성 애니메이션 코드
// 기존 코드에서의 행성 애니메이션
useEffect(() => {
const animatePlanets = () => {
const radius = 500; // 고리 반경
const angleStep = (2 * Math.PI) / planets.length; // 각 행성 사이의 각도
planetsRef.current.forEach((planet, index) => {
if (planet) {
const angle = (index - currentSlide) * angleStep; // 각 행성의 위치 계산
const xPos = radius * Math.sin(angle); // x 좌표
const yPos = 0; // y 좌표 (수평으로 회전)
const zPos = radius * Math.cos(angle); // z 좌표
const isVisible = index >= currentSlide && index < currentSlide + visiblePlanetsCount;
const scale = isVisible ? 1.5 : 1;
const zIndex = isVisible ? 10 : 0;
const opacity = isVisible ? 1 : 0.5;
gsap.to(planet, {
x: xPos,
y: yPos,
z: zPos,
scale: scale,
zIndex: zIndex,
opacity: opacity,
duration: 1,
ease: 'power2.inOut',
});
}
});
};
if (videoLoaded) {
animatePlanets();
}
}, [currentSlide, videoLoaded]);
수정 후 애니메이션 코드
// 새로운 코드에서의 행성 애니메이션
useEffect(() => {
const animatePlanets = () => {
const radius = 500; // 고리 반경
const angleStep = (2 * Math.PI) / planets.length; // 각 행성 사이의 각도
planetsRef.current.forEach((planet, index) => {
if (planet) {
const adjustedIndex = (index + (planets.length - Math.floor(visiblePlanetsCount / 2))) % planets.length;
const angle = (adjustedIndex - currentSlide) * angleStep; // 각 행성의 위치 계산
const xPos = radius * Math.sin(angle); // x 좌표
const yPos = 0; // y 좌표
const zPos = radius * Math.cos(angle); // z 좌표
const isVisible = (index >= currentSlide && index < currentSlide + visiblePlanetsCount) || (index < currentSlide && index + planets.length < currentSlide + visiblePlanetsCount);
const isActive = adjustedIndex === (currentSlide + Math.floor(visiblePlanetsCount / 2)) % planets.length;
const scale = isActive ? 2 : 1;
const zIndex = isActive ? 10 : 0;
const opacity = isVisible ? (isActive ? 1 : 0.5) : 0;
gsap.to(planet, {
x: xPos,
y: yPos,
z: zPos,
scale: scale,
zIndex: zIndex,
opacity: opacity,
duration: 1,
ease: 'power2.inOut',
});
}
});
};
if (videoLoaded) {
animatePlanets();
}
}, [currentSlide, videoLoaded]);
기존의 코드와 다른 점을 설명해보겠습니다.
1. adjustedIndex 변수
2. isActive 변수
isActive = true;인 경우에 행성의 크기(scale)을 키우고, z-index를 높여 입체감을 강조합니다.3. 로직 가시성 상승
4. 그 외 스타일 조정
현재 결과물

저기서 슬라이더를 할 시 행성이 순서대로 로테이션 되는 형식입니다.
대박이잖아... 휘진님 프로젝트 넘 기대돼요 ㅠ