본문 바로가기
부트캠프

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 45 (웹 애니메이션 - CSS 트랜지션, CSS 애니메이션, JavaScript 애니메이션)

by 나른한_꼬리_ 2025. 6. 30.
반응형

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 45 (웹 애니메이션 - CSS 트랜지션, CSS 애니메이션, JavaScript 애니메이션)

 

목차

 

웹 애니메이션

웹 애니메이션을 만드는 방법은 다음과 같다.

  1. CSS 트랜지션(Transition, 전환)
  2. CSS 애니메이션(Animation)
  3. JavaScript 애니메이션(Animation)

 

1. CSS 트랜지션

CSS 트랜지션(Transition)은 속성 값이 다른 값으로 전환될 때 발생(트리거, trigger)한다.

  • CSS 방식 트리거: 가상 클래스(:hover, :focus, :active)에 자주 사용
  • JavaScript 방식 트리거: 클래스를 추가/제거하거나 style 속성으로 CSS를 변경
 

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 17 (그리드 레이아웃, CSS 애니메이션)

목차그리드 컨테이너그리드 아이템 - 라인 기반 배치그리드 아이템 - Name 기반 배치그리드 정렬CSS 애니메이션(Transition)오늘 하루를 돌아보며 그리드 컨테이너display 속성 값을 grid나 inline-grid로

knowledge.narn1kkori.com

 

2. CSS 애니메이션

애니메이션을 만들려면 @keyframes 구문을 사용하고, 원하는 만큼 백분율(%)로 추가할 수 있다. 애니메이션을 사용할 경우 animation 속성을 사용하고, 8개의 개별 속성을 지원한다.

 

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 18 (키프레임 애니메이션, Transform, CSS 마스크, 멀

목차CSS 키프레임 애니메이션TransformCSS 마스크멀티 컬럼 레이아웃오늘 하루를 돌아보며 CSS 키프레임 애니메이션애니메이션 효과를 줄 수 있는 2가지 방법 중 하나로, @keyframes at-rule을 선언하여 an

knowledge.narn1kkori.com

 

CSS 애니메이션은 복잡할 수 있기 때문에 다음 조건을 충족할 때만 사용하는 것이 좋다.

  • 움직여야 할 속성이 여럿인 경우
  • 반복 횟수, 방향, 종료 상태, 재생 제어 등이 필요할 때
  • 화면이 로드될 때 애니메이션을 트리거해야 할 경우

위 조건을 충족하지 않을 때는 CSS 트랜지션을 사용하는 것이 좋다.

 

애니메이션 성능 고려

브라우저는 애니메이션 효과를 만들기 위해 프레임마다 다음 네 가지 작업을 수행한다.

  1. 스타일 재계산: 변경된 CSS를 다시 계산하기 때문에 비용이 가장 높다.
  2. 레이아웃: 요소의 위치와 크기를 다시 배치(Layout)하며, 비용이 아주 높다. 레이아웃 스래싱 위험이 있다.
  3. 페인트: 요소의 픽셀(색상, 텍스트 등)을 다시 그린다. 비용은 중간이다.
  4. 컴포지트: 레이어를 합쳐 화면에 최종 렌더링하며, 비용이 가장 낮다.

 

레이아웃 변경은 성능에 악영향을 미치기 때문에 가능하면 transform, opacity 속성을 사용하는 애니메이션을 구현하는 것이 좋다. 레이아웃과 페인트 단계를 피할 수 있어 성능 저하 없이 부드럽게 애니메이션이 작동하기 때문이다.

렌더링 단계 대표적인 영향 속성 설명
레이아웃
(Layout)
width, height, top. left, margin, padding, border, display, position 등 요소의 크기 및 위치가 변경되면 발생
가장 큰 비용 발생
페인트
(Paint)
background-color, box-shadow, border-radius, color, text-decoration 등 모양, 색상이 바뀌면 발생
중간 정도 비용 발생
컴포지트
(Composite)
transform, opacity, filter (GPU 가속 가능 속성) 실제 픽셀 계산 없이 레이어를 재배치
가장 비용이 낮고 빠름

 

3. JavaScript 애니메이션

JavaScript로 트랜지션이나 애니메이션 이벤트를 감지해야 할 경우 transition, animation 이벤트를 사용한다. 이러한 이벤트는 CSS 트랜지션, 애니메이션 시점과 JavaScript를 동기화해야 할 때 유용하다.

 

transition 이벤트CSS 트랜지션이 진행될 때 이벤트를 트리거한다. 2개 이상의 속성에 개별 트랜지션을 설정한 경우에는 각 속성마다 이벤트가 트리거된다.

// CSS 트랜지션이 처음 생성될 때(시작 전) 이벤트 트리거
element.addEventListener('transitionrun', (e) => {
  console.log('run', e.propertyName, e.target)
})

// CSS 트랜지션이 시작될 때 이벤트 트리거
element.addEventListener('transitionstart', (e) => {
  console.log('start', e.propertyName, e.target)
})

// CSS 트랜지션이 완료될 때 이벤트 트리거
element.addEventListener('transitionend', (e) => {
  console.log('end', e.propertyName, e.target)
})

// CSS 트랜지션이 중간에 취소될 때 이벤트 트리거
element.addEventListener('transitioncancel', (e) => {
  console.log('cancel', e.propertyName, e.target)
})

animation 이벤트CSS 애니메이션이 진행될 때 이벤트를 트리거한다. 애니메이션이 무한 반복(infinite)될 경우, animationend 이벤트는 트리거 되지 않는다.

// CSS 애니메이션이 시작할 때 이벤트 트리거
element.addEventListener('animationstart', (e) => {
  console.log('start', e.animationName, e.target)
})

// CSS 애니메이션이 반복될 때 이벤트 트리거
element.addEventListener('animationiteration', (e) => {
  console.log('iteration', e.animationName, e.target)
})

// CSS 애니메이션이 완료될 때 이벤트 트리거
element.addEventListener('animationend', (e) => {
  console.log('end', e.animationName, e.target)
})

// CSS 애니메이션이 중간에 취소될 때 이벤트 트리거
element.addEventListener('animationcancel', (e) => {
  console.log('cancel', e.animationName, e.target)
})

 

Web Animations API

CSS 트랜지션이나 애니메이션으로 만들기 어려운 것JavaScript 애니메이션으로 만드는 것이 낫다. 요소에 애니메이션을 적용하려면 element.animate() 메서드를 사용한다.

const element = document.querySelector('.rainbow')

element.animate(
  // 키프레임(keyframes)
  [
    { background: '#ff004d', offset: 0 },
    { background: '#ff77ab', offset: 0.20 },
    { background: '#00e756', offset: 0.5 },
    { background: '#29adff', offset: 0.80 },
    { background: '#ff77ab', offset: 1 },
  ], 
  // 옵션(options)
  {
    duration: 2000,
    direction: 'alternate',
    iterations: Infinity,
  }
)

 

웹 애니메이션 API가 정말 유용한 부분은 애니메이션 제어다. 재생, 일시정지, 역재생 기능을 제어할 수 있다.

const animateElement = element.animate(/* ... */)

// 일시정지
function pauseAnimate() {
  animateElement.pause()
}

// 재생
function playAnimate() {
  animateElement.play()
}

// 재생속도 변경
function chnagePlaybackRate(rate) {
  animateElement.updatePlaybackRate(rate)
}

// 가속
function moreFaster(ratio = 1.1) {
  const currentPlaybackRate = animateElement.playbackRate;
  animateElement.updatePlaybackRate(currentPlaybackRate * ratio)
}

// 감속
function moreSlower(ratio = 0.9) {
  const currentPlaybackRate = animateElement.playbackRate;
  animateElement.updatePlaybackRate(currentPlaybackRate * ratio)
}

// 역재생
function reverseAnimate() {
  animateElement.reverse()
  // animateElement.playbackRate = -1
  // animateElement.play()
}

// 종료 여부
function isFinished() {
  return animateElement.finished
}

// 특정 시간으로 이동
function goToFrame(frameTime /* ms */) {
  animateElement.currentTime = frameTime
}

// 끝으로 이동
function goToEndFrame() {
  animateElement.finish()
}

// 중단
function cancelAnimate() {
  animateElement.cancel()
}

// 애니메이션 종료 이벤트
animateElement.addEventListener('finish', () => {
  console.log('애니메이션 종료')
}

// 애니메이션 중단 이벤트
animateElement.addEventListener('cancel', () => {
  console.log('애니메이션 중단')
}

 

오늘 하루를 돌아보며

강의 초반에 지난 주에 배웠던 이벤트 위임을 활용해서 모달 다이얼로그, 아코디언, 탭 메뉴, 캐러셀의 코드를 수정해 봤다. 실습을 진행하면서 이벤트 위임이 얼마나 유용한 기능인지 알게 됐다.

  • 이벤트 위임을 사용해 코드가 더 간결하고 효율적으로 개선됨
  • 요소의 개수에 상관 없이 리스너는 1개만 필요
  • 동적으로 추가되는 요소에도 자동 대응 가능
  • 유지보수 및 성능 측면에서 장점이 큼

 

물론, 이벤트 위임이 익숙해지도록 연습을 그만큼 많이 해야 하지만 말이다ㅠㅠ 지난 주 과제를 마무리하지 못하고 제출했는데, 이벤트 위임을 사용하면 해낼 수 있을 것 같다. 오늘 과제 못 한 거 다시 시도해 보려고 한다. 실패해도 다시 시도하는 용기를 내보자!

 

반응형