반응형

페이지 모달에서 에니메이션이 동작하지 않는 것이다.

원인은 DOM 추가와 active 클래스 추가가 동시에 일어나서 CSS transition 이 작동하지 않았음

그래서 requestAnimationFrame() 으로 해결했는데

혹시나 해서 과거 코드의 참 많이 쓰기도 했고 해악이기도 했었던 sleep(0) 이런거랑 같은거인지를 물어보았다.

아니라고 합니다.

뭐라고 하는지 들어보려면 아래를 확인

 

⏺ requestAnimationFrame은 단순한 sleep 함수가 아니라 브라우저의 렌더링 사이클과 동기화되는
  특별한 함수입니다.

  🎨 브라우저 렌더링 사이클

  브라우저는 다음 순서로 화면을 그립니다:
  1. JavaScript 실행
  2. Style 계산 (CSS 적용)
  3. Layout (요소 크기/위치 계산)
  4. Paint (픽셀 그리기)
  5. Composite (레이어 합성)

  이 과정은 보통 60fps로 실행됩니다 (16.67ms마다 1번).

  ⏰ setTimeout vs requestAnimationFrame

  setTimeout(fn, 10)

  document.body.appendChild(element);
  setTimeout(() => {
      element.classList.add('active');
  }, 10);

  - 임의의 시간 후 실행
  - 렌더링 사이클과 무관하게 실행
  - 10ms 후 실행되지만, 렌더링 중간에 실행될 수도 있음
  - 불필요한 렌더링을 유발할 수 있음

  requestAnimationFrame(fn)

  document.body.appendChild(element);
  requestAnimationFrame(() => {
      element.classList.add('active');
  });


  - 다음 렌더링 직전에 실행
  - 브라우저가 "이제 그릴 준비됐어!"라고 할 때 실행
  - 렌더링 사이클과 완벽하게 동기화
  - 부드러운 애니메이션 보장


  🔄 왜 두 번 호출하나요?

  requestAnimationFrame(() => {
      requestAnimationFrame(() => {
          element.classList.add('active');
      });
  });


  이유:
  1. 첫 번째 RAF: DOM에 요소 추가 후 첫 렌더링 대기
    - 요소가 DOM 트리에 추가됨
    - 초기 스타일 계산 (opacity: 0, scale: 0.9)
    - 화면에 그려짐 (보이지 않는 상태)
  2. 두 번째 RAF: 초기 상태가 확정된 후 실행
    - 이제 transition 시작점이 확정됨
    - active 클래스 추가
    - CSS transition 애니메이션 시작

  📊 타이밍 비교

  // ❌ 즉시 실행 - 애니메이션 없음
  element.appendChild();
  element.classList.add('active'); // 0ms - 초기 상태가 없어서 transition 안됨

  // ⚠️ setTimeout - 불안정
  element.appendChild();
  setTimeout(() => {
      element.classList.add('active'); // 10ms - 타이밍이 보장 안됨
  }, 10);

  // ✅ RAF - 안정적
  element.appendChild();
  requestAnimationFrame(() => {
      requestAnimationFrame(() => {
          element.classList.add('active'); // 다음 프레임 (약 16-33ms)
      });
  });


  🎯 핵심 차이점

  | 특징                             | setTimeout             | requestAnimationFrame |
  |---------             ---|-----------            --|-----------------------|
  | 실행 시점                  | 지정한 ms 후              | 다음 렌더링 직전             |
  | 렌더링 동기화            | ❌ 없음                      | ✅ 완벽 동기화              |
  | 성능                          | 불필요한 렌더링 가능  | 최적화됨                  |
  | 애니메이션 부드러움 | 떨림 가능                    | 항상 부드러움               |
  | 브라우저 최적화        | ❌                              | ✅ (탭 비활성 시 중지)        |

  💡 실제 사용 예시

  // 🎬 애니메이션이 필요한 경우
  requestAnimationFrame(() => {
      element.style.transform = 'translateX(100px)';
  });

  // ⏱️ 단순 지연이 필요한 경우
  setTimeout(() => {
      console.log('1초 후 실행');
  }, 1000);

  // 🎨 CSS transition 트리거
  element.style.display = 'block';
  requestAnimationFrame(() => {
      requestAnimationFrame(() => {
          element.style.opacity = '1'; // transition 작동
      });
  });



  결론: requestAnimationFrame은 브라우저의 그리기 주기와 완벽하게 동기화되어 애니메이션을
  부드럽고 효율적으로 만드는 전문 도구입니다!

 

🔎 CSS Transition 작동 과정

요소가 DOM에 추가됨
자바스크립트로 element.appendChild() 하거나, 서버에서 HTML을 내려주면 브라우저는 DOM(Document Object Model) 트리에 그 요소를 넣습니다.

브라우저가 초기 상태 렌더링
DOM에 들어온 요소는 CSSOM(CSS Object Model) 과 합쳐져서 렌더 트리를 구성합니다.

이때 적용되는 클래스/스타일 중에서 “시작 상태(start state)”가 반영됩니다. (예: opacity: 0)

reflow & repaint 발생
브라우저가 레이아웃을 다시 계산하고(reflow), 픽셀 단위로 화면에 그립니다(repaint).

즉 “초기 상태”를 사용자 화면에 그린 거예요.

클래스가 추가되어 최종 상태로 변화 요청
자바스크립트에서 element.classList.add("active") 같은 동작을 하거나, CSS 상태 변화(:hover 등)가 발생합니다.

CSS transition 이 정의되어 있다면, 브라우저는 이전 값 → 새로운 값 사이를 일정 시간에 걸쳐 보간(interpolate)해서 애니메이션합니다.

예: opacity: 0 → opacity: 1 으로 0.5초 동안 변화.

Transition 실행
이 과정에서 브라우저는 중간 단계의 스타일을 계산하면서 매 프레임마다 repaint 합니다.

개발자가 지정한 transition-duration, transition-timing-function 값에 따라 부드럽게 변화합니다.

👉 즉, CSS Transition 은 “상태 변화”가 감지된 순간, 브라우저가 현재 상태와 목표 상태 사이를 보간해서 화면에 반영하는 것

💡 핵심 정리
DOM에 추가될 때 이미 최종 클래스를 붙여버리면 브라우저는 “초기 상태를 렌더링할 기회”를 갖지 못합니다 → transition이 눈에 띄지 않고 바로 최종 상태로 그려져 버림.

그래서 보통은:

element.classList.add("hidden");   // 초기 상태
document.body.appendChild(element);
requestAnimationFrame(() => {
  element.classList.add("active"); // transition 발동
});


이런 식으로 한 프레임 늦게 최종 상태 클래스를 붙여서 transition 을 보장합니다.

반응형

+ Recent posts