애니메이션 효과 (스크롤 등장 & 타이핑)
화면에 움직임을 주는 두 가지 효과를 모았습니다.
스크롤 등장 애니메이션
setupRevealAnimation()에서 IntersectionObserver를 threshold: 0.2로 생성하고, .reveal 클래스가 붙은 요소들을 관찰합니다.
요소가 뷰포트에 20% 이상 들어오면 is-visible 클래스를 추가하고, 그 즉시 observer.unobserve()로 관찰을 중단해 같은 요소에서 애니메이션이 반복 실행되지 않도록 합니다.
왜 transform과 opacity로 움직일까
이 프로젝트의 utilities.css는 .reveal을 opacity: 0, transform: translateY(28px)로 숨겨 두었다가, is-visible이 붙으면 600ms 동안 제자리로 올라오며 나타나게 합니다. 같은 효과를 top 값으로도 만들 수 있지만, 어떤 속성을 바꾸느냐에 따라 브라우저가 하는 일의 양이 크게 달라집니다.
/* 무거운 방식: 위치가 바뀌니 매 프레임 레이아웃부터 다시 계산 */
.reveal { position: relative; top: 28px; }
.reveal.is-visible { top: 0; transition: top 0.6s; }
/* 가벼운 방식 (이 프로젝트의 실제 코드): 그려진 그림을 옮기고 투명도만 바꿈 */
.reveal {
opacity: 0;
transform: translateY(28px);
transition: opacity 600ms ease, transform 600ms ease;
}
.reveal.is-visible {
opacity: 1;
transform: translateY(0);
}| 바꾸는 속성 | 다시 하는 단계 | 부담 |
|---|---|---|
top, left, width, height, margin | 레이아웃 → 페인트 → 합성 | 큼 (주변 요소 위치까지 다시 계산) |
color, background, box-shadow | 페인트 → 합성 | 중간 |
transform, opacity | 합성 | 작음 (GPU가 처리하는 경우가 많음) |
애니메이션은 1초에 60번 안팎으로 화면을 다시 그리기 때문에, 가능하면 transform과 opacity만 바꾸는 것이 부드럽습니다. 이 프로젝트는 이미 가벼운 방식으로 작성되어 있습니다. 레이아웃·페인트·합성 단계는 브라우저 동작 원리 글에서 자세히 다룹니다.
아직 없는 부분으로, 움직임에 어지러움을 느끼는 사용자를 위해 운영체제에서 "동작 줄이기"를 켜 둔 경우에는 애니메이션을 끄는 것도 좋은 UX 배려입니다.
@media (prefers-reduced-motion: reduce) {
.reveal { opacity: 1; transform: none; transition: none; }
}Hero 타이핑 효과
typeHeroText()는 문구 배열(phrases)을 한 글자씩 추가/삭제하며 순환합니다. 아래 네 가지 지연을 각각 다른 setTimeout으로 구분해, 사람이 타이핑하는 듯한 리듬을 흉내 냅니다.
| 구간 | 지연 |
|---|---|
| 한 글자 타이핑 | 110ms |
| 한 글자 삭제 | 55ms |
| 문구 완성 후 대기 | 1300ms |
| 삭제 완료 후 다음 문구 전환 | 250ms |
정리
- 스크롤 등장:
IntersectionObserver로 보일 때 한 번만 실행 - 움직임은
transform·opacity로 만들면 레이아웃을 다시 하지 않아 부드러움 prefers-reduced-motion으로 동작 줄이기 설정을 존중- 타이핑:
setTimeout지연을 구간마다 다르게 줘서 자연스러운 리듬
출처: Codyssey-B1/B1-1
