Reflow 와 Repaint

Reflow 와 Repaint

Front-end developer WONISM
Interested in ReactJS, RxJS and ReasonML.

reflow와 repaintλŠ” μˆ˜μ •λœ λ Œλ” 트리λ₯Ό λ‹€μ‹œ λ Œλ”λ§ν•˜λŠ” κ³Όμ •μ—μ„œ λ°œμƒν•˜λŠ” κ²ƒμœΌλ‘œ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ„±λŠ₯을 λ–¨μ–΄λœ¨λ¦¬λŠ” 주된 μš”μΈμ΄λ‹€. 극단적인 경우, CSS 효과둜 인해 Java Script 의 μ‹€ν–‰ 속도가 느렀질 μˆ˜λ„ μžˆλ‹€.

Repaint

λ¦¬νŽ˜μΈνŠΈλŠ” λ ˆμ΄μ•„μ›ƒμ—λŠ” 영ν–₯을 주지 μ•Šμ§€λ§Œ, κ°€μ‹œμ„±μ—λŠ” 영ν–₯을 μ£ΌλŠ” μ—˜λ¦¬λ¨ΌνŠΈκ°€ λ³€κ²½λ˜λ©΄ λ°œμƒν•œλ‹€.
예λ₯Ό λ“€λ©΄, opacity, background-color, visibility, outline

μ˜€νŽ˜λΌμ— λ”°λ₯΄λ©΄, β€œλΈŒλΌμš°μ €κ°€ DOM νŠΈλ¦¬μ— μžˆλŠ” λ‹€λ₯Έ λͺ¨λ“  λ…Έλ“œμ˜ κ°€μ‹œμ„±μ„ 확인해야 ν•˜λ―€λ‘œ λ¦¬νŽ˜μΈνŠΈλŠ” λΉ„μš©μ΄ 많이 λ“ λ‹€.”고 ν•œλ‹€.

Reflow

β€œλ¦¬ν”Œλ‘œμš°β€λŠ” λͺ¨λ“  μ—˜λ¦¬λ¨ΌνŠΈμ˜ μœ„μΉ˜μ™€ 길이 등을 λ‹€μ‹œ κ³„μ‚°ν•˜λŠ” κ²ƒμœΌλ‘œ λ¬Έμ„œμ˜ 일뢀 ν˜Ήμ€ 전체λ₯Ό λ‹€μ‹œ λ Œλ”λ§ν•œλ‹€.
단일 μ—˜λ¦¬λ¨ΌνŠΈ ν•˜λ‚˜λ₯Ό 변경해도, ν•˜μœ„ μ—˜λ¦¬λ¨ΌνŠΈλ‚˜ μƒμœ„ μ—˜λ¦¬λ¨ΌνŠΈ 등에 영ν–₯을 λ―ΈμΉ  수 μžˆλ‹€.

λ¦¬ν”Œλ‘œμš°κ°€ νŠΈλ¦¬κ±°λ˜λŠ” 경우

  • DOM μ—˜λ¦¬λ¨ΌνŠΈ μΆ”κ°€, 제거 λ˜λŠ” λ³€κ²½
  • CSS μŠ€νƒ€μΌ μΆ”κ°€, 제거 λ˜λŠ” λ³€κ²½

    • CSS μŠ€νƒ€μΌμ„ 직접 λ³€κ²½ν•˜κ±°λ‚˜, 클래슀λ₯Ό μΆ”κ°€ν•¨μœΌλ‘œμ¨ λ ˆμ΄μ•„μ›ƒμ΄ 변경될 수 μžˆλ‹€. μ—˜λ¦¬λ¨ΌνŠΈμ˜ 길이λ₯Ό λ³€κ²½ν•˜λ©΄, DOM νŠΈλ¦¬μ— μžˆλŠ” λ‹€λ₯Έ λ…Έλ“œμ— 영ν–₯을 쀄 수 μžˆλ‹€.
  • CSS3 μ• λ‹ˆλ©”μ΄μ…˜κ³Ό νŠΈλžœμ§€μ…˜

    • μ• λ‹ˆλ©”μ΄μ…˜μ˜ λͺ¨λ“  ν”„λ ˆμž„μ—μ„œ λ¦¬ν”Œλ‘œμš°κ°€ λ°œμƒν•œλ‹€.
  • offsetWidth 와 offsetHeight 의 μ‚¬μš©

    • offsetWidth 와 offsetHeight 속성을 읽으면, 초기 λ¦¬ν”Œλ‘œμš°κ°€ νŠΈλ¦¬κ±°λ˜μ–΄ μˆ˜μΉ˜κ°€ κ³„μ‚°λœλ‹€.
  • μœ μ € 행동

    • μœ μ € μΈν„°λž™μ…˜μœΌλ‘œ λ°œμƒν•˜λŠ” hover 효과, ν•„νŠΈμ— ν…μŠ€νŠΈ μž…λ ₯, μ°½ 크기 μ‘°μ •, κΈ€κΌ΄ 크기 λ³€κ²½, μŠ€νƒ€μΌμ‹œνŠΈ λ˜λŠ” κΈ€κΌ΄ μ „ν™˜λ“±μ„ ν™œμ„±ν™”ν•˜μ—¬ λ¦¬ν”Œλ‘œμš°λ₯Ό νŠΈλ¦¬κ±°ν•  수 μžˆλ‹€.

μ„±λŠ₯ μ €ν•˜ μ΅œμ†Œν™”ν•˜κΈ°

  • 클래슀 변경을 톡해 μŠ€νƒ€μΌμ„ λ³€κ²½ν•  경우, μ΅œλŒ€ν•œ λ§λ‹¨μ˜ λ…Έλ“œμ˜ 클래슀λ₯Ό λ³€κ²½ν•œλ‹€.

    • μ΅œλŒ€ν•œ 말단에 μžˆλŠ” λ…Έλ“œλ₯Ό λ³€κ²½ν•¨μœΌλ‘œμ¨, λ¦¬ν”Œλ‘œμš°μ˜ 영ν–₯을 μ΅œμ†Œν™”ν•œλ‹€.
  • 인라인 μŠ€νƒ€μΌμ„ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.

    • μŠ€νƒ€μΌ 속성을 톡해 μŠ€νƒ€μΌμ„ μ„€μ •ν•˜λ©΄, λ¦¬ν”Œλ‘œμš°κ°€ λ°œμƒν•œλ‹€.
    • μ—˜λ¦¬λ¨ΌνŠΈμ˜ ν΄λž˜μŠ€κ°€ 변경될 λ•Œ μ—˜λ¦¬λ¨ΌνŠΈλŠ” ν•˜λ‚˜μ˜ λ¦¬ν”Œλ‘œμš°λ§Œ λ°œμƒμ‹œν‚¨λ‹€.
    • 인라인 μŠ€νƒ€μΌμ€ HTML 이 λ‹€μš΄λ‘œλ“œλ  λ•Œ, λ ˆμ΄μ•„μ›ƒμ— 영ν–₯을 λ―ΈμΉ˜λ©΄μ„œ μΆ”κ°€ λ¦¬ν”Œλ‘œμš°λ₯Ό λ°œμƒμ‹œν‚¨λ‹€.
  • μ• λ‹ˆλ©”μ΄μ…˜μ΄ λ“€μ–΄κ°„ μ—˜λ¦¬λ¨ΌνŠΈλŠ” position: fixed λ˜λŠ” position: absolute 둜 μ§€μ •ν•œλ‹€.

    • absolute λ˜λŠ” fixed μœ„μΉ˜μΈ μ—˜λ¦¬λ¨ΌνŠΈλŠ” λ‹€λ₯Έ μ—˜λ¦¬λ¨ΌνŠΈμ˜ λ ˆμ΄μ•„μ›ƒμ— 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠλŠ”λ‹€. (λ¦¬ν”Œλ‘œμš°κ°€ μ•„λ‹Œ λ¦¬νŽ˜μΈνŠΈκ°€ λ°œμƒν•˜λŠ”λ°, 이것은 훨씬 적은 λΉ„μš©μ΄ λ“ λ‹€.)
  • λΆ€λ“œλŸ¬μš΄ μ• λ‹ˆλ©”μ΄μ…˜μ΄ μ„±λŠ₯을 μ €ν•˜μ‹œν‚¨λ‹€.

    • ν•œ λ²ˆμ— 1px μ”© μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό μ΄λ™ν•˜λ©΄ λΆ€λ“œλŸ¬μ›Œ λ³΄μ΄μ§€λ§Œ, μ„±λŠ₯이 λ–¨μ–΄μ§€λŠ” λ””λ°”μ΄μŠ€λŠ” 말썽일 수 μžˆλ‹€.
    • μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό ν•œ ν”„λ ˆμž„λ‹Ή 4px μ”© μ΄λ™ν•˜λ©΄ 덜 λΆ€λ“œλŸ½κ²Œ λ³΄μ΄κ² μ§€λ§Œ, λ¦¬ν”Œλ‘œμš° 처리의 1/4만 ν•„μš”ν•˜λ‹€.
  • λ ˆμ΄μ•„μ›ƒμ„ μœ„ν•œ <table> 은 ν”Όν•œλ‹€.

    • <table> 은 μ μ§„μ μœΌλ‘œ λ Œλ”λ§λ˜μ§€ μ•Šκ³ , λͺ¨λ‘ λΆˆλ €μ§€κ³  κ³„μ‚°λœ λ‹€μŒμ—μ„œμ•Ό λ Œλ”λ§μ΄ λœλ‹€. λ˜ν•œ, μž‘μ€ λ³€κ²½λ§ŒμœΌλ‘œλ„ ν…Œμ΄λΈ”μ˜ λ‹€λ₯Έ λͺ¨λ“  λ…Έλ“œμ— λŒ€ν•œ λ¦¬ν”Œλ‘œμš°κ°€ λ°œμƒν•œλ‹€.
    • λ ˆμ΄μ•„μ›ƒ μš©λ„κ°€ μ•„λ‹Œ 데이터 ν‘œμ‹œ μš©λ„μ˜ <table> 을 μ‚¬μš©ν•˜λ”λΌκ³ , table-layout: fixed 속성을 μ£ΌλŠ” 것이 μ’‹λ‹€. table-layout: fixed λ₯Ό μ‚¬μš©ν•˜λ©΄, μ—΄ λ„ˆλΉ„κ°€ 머리글 ν–‰ λ‚΄μš©μ„ 기반으둜 κ³„μ‚°λ˜κΈ° λ•Œλ¬Έμ΄λ‹€.
  • CSS μ—μ„œ Java Script ν‘œν˜„μ‹μ„ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.

    • IE 와 FF λŠ” λͺ¨λ‘ CSS μ—μ„œ Java Script λ₯Ό μ‹€ν–‰ν•  수 μžˆλ‹€. IE μ—μ„œλŠ” ν‘œν˜„ 기법과 HTC λ™μž‘ 방법이 있고, FF μ—μ„œλŠ” XBL 을 μ‚¬μš©ν•˜λŠ” 방법이 μžˆλ‹€. (이 방법은 CSS μ—μ„œ Java Script λ₯Ό 직접 μ‹€ν–‰ν•˜μ§€λŠ” μ•Šμ§€λ§Œ, κ·Έ νš¨κ³ΌλŠ” λ™μΌν•˜λ‹€.)
    • λ¬Έμ„œκ°€ λ¦¬ν”Œλ‘œμš°λ  λ•Œλ§ˆλ‹€ Java Script ν‘œν˜„μ‹μ΄ λ‹€μ‹œ κ³„μ‚°λœλ‹€.
  • CSS ν•˜μœ„ μ…€λ ‰ν„°λ₯Ό μ΅œμ†Œν™”ν•œλ‹€.

    • μ‚¬μš©ν•˜λŠ” κ·œμΉ™μ΄ μ μ„μˆ˜λ‘ λ¦¬ν”Œλ‘œμš°κ°€ λΉ λ₯΄λ‹€.
    • gulp-uncss, grunt-uncss 와 같은 λ„κ΅¬λ‘œ μŠ€νƒ€μΌ μ •μ˜ 및 파일 크기λ₯Ό 쀄인닀.
  • μˆ¨κ²¨μ§„ μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό λ³€κ²½ν•œλ‹€.

    • display: none; 으둜 μˆ¨κ²¨μ§„ μ—˜λ¦¬λ¨ΌνŠΈλŠ” 변경될 λ•Œ, λ¦¬νŽ˜μΈνŠΈλ‚˜ λ¦¬ν”Œλ‘œμš°λ₯Ό μΌμœΌν‚€μ§€ μ•ŠλŠ”λ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό ν‘œμ‹œν•˜κΈ° 전에 μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό λ³€κ²½ν•œλ‹€.
  • Java Script λ₯Ό 톡해 μŠ€νƒ€μΌμ„ λ³€κ²½ν•  경우, .cssText λ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜, 클래슀λ₯Ό λ³€κ²½ν•œλ‹€.

var el = document.getElementById('reflow-test');

el.style.padding = '8px';
el.style.width = '320px';
el.style.height = '240px';
// 3 번의 λ¦¬ν”Œλ‘œμš° λ°œμƒ

/////////
var el = document.getElementById('reflow-test');

el.style.cssText = 'padding: 8px; width: 320px; height: 240px;';
/* or */
el.className = 'changed';
// 1 번의 λ¦¬ν”Œλ‘œμš° λ°œμƒ

/**
 * Style of `changed` class
 * .changed {
 *   padding: 8px;
 *   width: 320px;
 *   height: 240px;
 * }
 */
  • Java Script λ₯Ό 톡해 리슀트λ₯Ό μΆ”κ°€ν•˜λŠ” 경우, DOM Fragment λ₯Ό 톡해 μΆ”κ°€ν•œλ‹€.

    • 3 개의 리슀트λ₯Ό μΆ”κ°€ν•˜λŠ” 경우, ν•œ λ²ˆμ— ν•˜λ‚˜μ”© μΆ”κ°€ν•˜λ©΄ μ΅œλŒ€ 7 개의 λ¦¬ν”Œλ‘œμš°κ°€ λ°œμƒν•œλ‹€.
      <ul> 이 좔가될 λ•Œ
      <li> 에 λŒ€ν•΄ 3번
      ν…μŠ€νŠΈ λ…Έλ“œμ— λŒ€ν•΄ 3번
const frag = document.createDocumentFragment();
const ul = frag.appendChild(document.createElement('ul'));

for (let i = 1; i <= 3; i++) {
  li = ul.appendChild(document.createElement('li'));
  li.textContent = `item ${ i }`;
}

document.body.appendChild(frag);
  • 캐쉬λ₯Ό ν™œμš©ν•œ Reflow μ΅œμ†Œν™”.

    • λΈŒλΌμš°μ €λŠ” λ ˆμ΄μ•„μ›ƒ 변경을 큐에 μ €μž₯ν–ˆλ‹€κ°€ ν•œ λ²ˆμ— μ‹€ν–‰ν•¨μœΌλ‘œμ¨ λ¦¬ν”Œλ‘œμš°λ₯Ό μ΅œμ†Œν™”ν•˜λŠ”λ°, offset, scrollTop κ³Ό 같은 κ³„μ‚°λœ μŠ€νƒ€μΌ 정보λ₯Ό μš”μ²­ν•  λ•Œλ§ˆλ‹€ μ •ν™•ν•œ 정보λ₯Ό μ œκ³΅ν•˜κΈ° μœ„ν•΄ 큐λ₯Ό λΉ„μš°κ³ , λͺ¨λ“  변경을 λ‹€μ‹œ μ μš©ν•œλ‹€.
    • 이λ₯Ό μ΅œμ†Œν™”ν•˜κΈ° μœ„ν•΄ μˆ˜μΉ˜μ— λŒ€ν•œ μŠ€νƒ€μΌ 정보λ₯Ό λ³€μˆ˜μ— μ €μž₯ν•˜μ—¬ 정보 μš”μ²­ 횟수λ₯Ό μ€„μž„μœΌλ‘œμ¨ λ¦¬ν”Œλ‘œμš°λ₯Ό μ΅œμ†Œν™”ν•œλ‹€.
// Bad practice
for (let i = 0; i < len; i++) {
  el.style.top = `${ el.offsetTop + 10 }px`;
  el.style.left = `${ el.offsetLeft + 10 }px`;
}

// Good practice
let top = el.offsetTop, left = el.offsetLeft, elStyle = el.style;

for (let i = 0; i < len; i++) {
  top += 10;
  left += 10;
  elStyle.top = `${ top }px`;
  elStyle.left = `${ left }px`;
}
  • λΈŒλΌμš°μ € λ„κ΅¬λ‘œ 리페인트 이슈 λΆ„μ„ν•˜κΈ°

    • λͺ¨λ“  μ£Όλ₯˜ λΈŒλΌμš°μ €λŠ” λ¦¬ν”Œλ‘œμš°κ°€ μ„±λŠ₯에 λ―ΈμΉ˜λŠ” 영ν–₯을 λ³΄μ—¬μ£ΌλŠ” [νƒ€μž„λΌμΈ] 도ꡬλ₯Ό μ œκ³΅ν•œλ‹€.
    • IE 의 κ²½μš°μ—λŠ” dynaTrace AJAX Edition, Webkit Browser 의 κ²½μš°μ—λŠ” Google Chrome SpeedTracer κ°€ μžˆλ‹€.

μ°Έκ³