useEffect & useLayoutEffect

⏰ 2024-07-11 (λͺ©) 01:47:46

screener

Table of Contents

  • 1. κ°œμš”











κ°œμš”

ReactλŠ” ν΄λž˜μŠ€ν˜•(Class Component)κ³Ό ν•¨μˆ˜ν˜•(Function Cmpoonent) 두 μ’…λ₯˜λ‘œ λ‚˜λ‰œλ‹€. ν•¨μˆ˜ν˜• Reactκ°€ νŠΈλ Œλ“œκ°€ 된 μ΄ν›„λ‘œ, Hookκ³Ό Context λ“±, ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈλ₯Ό μœ„ν•œ λ‹€μ–‘ν•œ μš”μ†Œκ°€ 좔가됐닀.

κ·Έ 쀑 React의 라이프사이클과 μ—°κ΄€λ˜λŠ” Hook은 μ»΄ν¬λ„ŒνŠΈ κ°œλ°œμ— μžˆμ–΄ μ€‘μš”ν•œ μš”μ†Œλ‹€. κ°œλ°œμžκ°€ 자체적으둜 λ‹€μ–‘ν•œ 훅을 λ§Œλ“€ 수 μžˆμ§€λ§Œ, React λ˜ν•œ κ°œλ°œμžκ°€ Reactλ₯Ό μ’€ 더 κ°„νŽΈν•˜κ³  효율적으둜 ν™œμš©ν•  수 μžˆλ„λ‘ 라이브러리 λ‹¨κ³„μ—μ„œ λ‹€μ–‘ν•œ Hook을 μ œκ³΅ν•˜κ³  μžˆλ‹€.

κ·Έ 쀑 많이 λ Œλ”λ§μ„ μ œμ–΄ν•˜λŠ”λ° μ‚¬μš©ν•˜λŠ” ν›…μœΌλ‘œ useEffect와, λΉ„μŠ·ν•˜λ©΄μ„œλ„ λ‹€μ†Œ μƒμ†Œν•œ useLayoutEffectκ°€ μ‘΄μž¬ν•œλ‹€.

이 λ¬Έμ„œμ—μ„œλŠ” useEffect와 useLayoutEffect ν›…μ˜ λ‚΄μš©κ³Ό μ‚¬μš©λ²•μ„ μ•Œμ•„λ΄„μœΌλ‘œμ¨, λ Œλ”λ§ μž‘μ—…μ„ 적절히 μ œμ–΄ν•΄λ³Έλ‹€.

useEffect

React 개발자라면 useEffectλ₯Ό λ°˜λ“œμ‹œ ν•œ 번쯀 μ‚¬μš©ν–ˆμ„ 것이닀. useEffect 훅은, ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈμ—μ„œ React μ™ΈλΆ€μ˜ μ½”λ“œλ₯Ό λ™μž‘ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•˜λŠ” 훅이라 μ •μ˜λœλ‹€.

μ—¬κΈ°μ„œ React μ™ΈλΆ€μ˜ μ½”λ“œλž€, API 데이터λ₯Ό κ°€μ Έμ˜¨λ‹€κ±°λ‚˜, νŠΉμ • DOM을 μ‘°μž‘ν•œλ‹€κ±°λ‚˜, λΈŒλΌμš°μ € μ˜μ—­μ˜ μ½”λ“œλ₯Ό μ‚¬μš©ν•˜λŠ” λ“±μ˜ μ½”λ“œλ₯Ό μ˜λ―Έν•œλ‹€.

useEffect의 κ°€μž₯ 큰 νŠΉμ§•μ€, useEffect에 μ„ μ–Έλœ μ½”λ“œλŠ” λ°˜λ“œμ‹œ λ Œλ”λ§ μž‘μ—…μ΄ μ™„λ£Œλœ 이후에 μ‹€ν–‰λœλ‹€λŠ” 것이닀. 즉, λ°˜λ“œμ‹œ ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œμ—μ„œμ˜ λ™μž‘μ„ μ˜λ―Έν•œλ‹€.

일반적인 μ›Ή ν”„λ‘ νŠΈ 개발과 달리, React ν˜Ήμ€ 그와 λΉ„μŠ·ν•œ ν”„λ‘ νŠΈμ—”λ“œ ν”„λ ˆμž„μ›Œν¬μ˜ 경우, μ»΄ν¬λ„ŒνŠΈκ°€ λ Œλ”λ§λœλ‹€λŠ” κ°œλ…μ΄ 생기며, μ˜¬λ°”λ₯΄μ§€ μ•Šμ€ λ‹¨κ³„μ—μ„œ λ‘œμ§μ„ μˆ˜ν–‰ν•  경우, λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄, μ»΄ν¬λ„ŒνŠΈκ°€ 아직 λ Œλ”λ§λ˜μ§€ μ•Šμ•˜μŒμ—λ„, DOM에 μ ‘κ·Όν•œλ‹€κ±°λ‚˜, μΏ ν‚€λ₯Ό μ‚¬μš©ν•˜λŠ” λ“±μ˜ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλ₯Ό μˆ˜ν–‰ν•  경우, λ Œλ”λ§ μ‹€νŒ¨ ν˜Ήμ€ 그에 μ€€ν•˜λŠ” 였λ₯˜κ°€ λ°œμƒν•˜λ©°, λ Œλ”λ§μ— μ‹€νŒ¨ν•˜κ²Œ λœλ‹€.

λ Œλ”λ§μ΄ μ™„μ „νžˆ λλ‚œ 이후엔 ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œ λ‘œμ§μ„ μˆ˜ν–‰ν•  수 μžˆμœΌλ―€λ‘œ, useEffectλ₯Ό 톡해, ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œμ—μ„œλ§Œ λ™μž‘ν•˜λŠ” μ½”λ“œλ₯Ό λͺ…μ‹œν•  수 μžˆλ‹€.

μ‚¬μš©λ²•

μ•„λž˜λŠ” useEffect의 기초적인 μ‚¬μš©λ²•μ΄λ‹€.

TSX

1
useEffect(callback, arr);

callback에 μ›ν•˜λŠ” 콜백 λ©”μ„œλ“œλ₯Ό 지정할 수 μžˆλ‹€. λ³„λ„μ˜ νŒŒλΌλ―Έν„°λ₯Ό 받을 μˆ˜λŠ” μ—†λ‹€. 이 콜백 λ©”μ„œλ“œλŠ” λ Œλ”λ§ μž‘μ—…μ΄ λλ‚œ 이후, λΉ„λ™κΈ°μ μœΌλ‘œ μˆ˜ν–‰λ  것이닀.

arr은 μ˜μ‘΄μ„± 배열이닀. ν•΄λ‹Ή λ°°μ—΄μ—λŠ” μ–΄λ–€ λ³€μˆ˜λ“  ν• λ‹Ήν•  수 있으며, ν• λ‹Ήν•œ λ³€μˆ˜κ°€ λ³€κ²½λ˜λ©΄, useEffect의 콜백 λ©”μ„œλ“œκ°€ λ‹€μ‹œ μˆ˜ν–‰λœλ‹€.

μ΄λŸ¬ν•œ νŠΉμ§•μœΌλ‘œ νŠΉμ • λ³€μˆ˜ λ³€κ²½ μ‹œ, μ˜λ„μ μœΌλ‘œ νŠΉμ • λ™μž‘μ„ μˆ˜ν–‰ν•˜μ—¬, λ³€μˆ˜μ˜ 변경에 λŒ€μ‘ν•˜μ—¬ μ μ ˆν•œ λ Œλ”λ§μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.

return을 ν†΅ν•œ ν›… μ΄ˆκΈ°ν™”

useEffectλŠ” 기본적으둜 voidλ₯Ό λ°˜ν™˜ν•˜μ§€λ§Œ, return을 ν™œμš©ν•˜μ—¬ 콜백 λ©”μ„œλ“œλ₯Ό λ°˜ν™˜ν•  수 μžˆλ‹€. 이λ₯Όν…Œλ©΄ μ•„λž˜μ™€ 같은 방식이닀.

TSX

1
2
3
4
5
6
7
8
9
10
11
useEffect(() => {
	const handle = () => {
		console.log(`just resized at ${Date.now()}`)
	}

	document.addEventListener('resize', handle);

	return () => {
		document.removeEventListener('resize', handle);
	}
}, []);

return으둜 콜백 λ©”μ„œλ“œλ₯Ό λ‹€μ‹œ λ°˜ν™˜ν–ˆλ‹€. 이 return은 훅을 μ΄ˆκΈ°ν™”ν•˜λŠ” μ½”λ“œλ‘œ, return의 콜백 λ©”μ„œλ“œκ°€ μˆ˜ν–‰λ˜λŠ” 쑰건은 μ•„λž˜μ™€ κ°™λ‹€.

  1. μ»΄ν¬λ„ŒνŠΈκ°€ μ–Έλ§ˆμš΄νŠΈ 될 λ•Œ.
  2. λ””νŽœλ˜μ‹œ λ°°μ—΄μ˜ 값이 λ³€κ²½λ˜μ–΄ λ¦¬λ Œλ”λ§ 될 λ•Œ.

μœ„μ™€ 같이, μ»΄ν¬λ„ŒνŠΈ μ–Έλ§ˆμš΄νŠΈ 및 λ¦¬λ Œλ”λ§ μ‹œ, μ΄ˆκΈ°ν™”ν•˜κ±°λ‚˜, μ œκ±°ν•΄μ•Όν•  λ™μž‘μ΄ μžˆμ„ 경우 μ‚¬μš©ν•œλ‹€.

μœ„ μ½”λ“œλ₯Ό 예둜 λ“€μžλ©΄, μ»΄ν¬λ„ŒνŠΈκ°€ λ Œλ”λ§λ˜λ©΄μ„œ, document 전역에 λ¦¬μ‚¬μ΄μ¦ˆ 이벀트λ₯Ό μΆ”κ°€ν–ˆλ‹€. λ§Œμ•½, return으둜 이벀트λ₯Ό μ œκ±°ν•˜μ§€ μ•Šμ„ 경우, μ»΄ν¬λ„ŒνŠΈκ°€ λ§ˆμš΄νŠΈλ˜κ±°λ‚˜, λ Œλ”λ§μ΄ λ‹€μ‹œ 일어날 λ•Œλ§ˆλ‹€ λ¦¬μ‚¬μ΄μ¦ˆ μ΄λ²€νŠΈκ°€ λˆ„μ λ˜μ–΄ 볡수둜 μˆ˜ν–‰λœλ‹€.

μ˜ˆμ‹œ μ½”λ“œ

TSX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { useEffect } from 'react';

function Component(): JSX.Element {
	useEffect(() => {
		const tag = document.getElementById('target');

		if (tag) {
			tag.innerHTML = `in client side at ${Date.now()}`
		}
	}, [ deps ])

	return (
		<div>
			<h1>title</h1>

			<p id="target">initial</p>
		</div>
	)
}

useEffect의 μ½”λ“œλŠ” λ Œλ”λ§ μž‘μ—…μ΄ λλ‚œ 이후 λ™μž‘ν•œλ‹€. #target의 HTML λ‚΄μš©μ„ λ³€κ²½ν•˜λ©°, μ‚¬μš©μžλŠ” λ Œλ”λ§ 된 직후, useEffect의 μ½”λ“œκ°€ μˆ˜ν–‰λ˜κΈ° μ „κΉŒμ§€μ˜ 짧은 μ‹œκ°„λ™μ•ˆ initialμ΄λΌλŠ” 초기 ν…μŠ€νŠΈλ₯Ό κ΄€μΈ‘ν•  수 μžˆλ‹€.

deps λ³€μˆ˜κ°€ λ³€ν•  λ•Œλ§ˆλ‹€, 콜백 λ©”μ„œλ“œκ°€ λ‹€μ‹œ μ‹€ν–‰λ˜λ©°, κ·Έ λ•Œλ§ˆλ‹€ Date.now()에 μ˜ν•΄ ν‘œμ‹œλœ 값이 λ°”λ€ŒλŠ” κ±Έ 확인할 수 μžˆλ‹€.

useLayoutEffect

useEffectλŠ” μœ„μ—μ„œλ„ λ‹€λ€˜λ‹€μ‹œν”Ό, λ Œλ”λ§ ν›„ μ½”λ“œλ₯Ό λΉ„λ™κΈ°μ μœΌλ‘œ μˆ˜ν–‰ν•œλ‹€. λŒ€λ‹€μˆ˜μ˜ React κ°œλ°œμžλ“€μ΄ 많이 μ ‘ν•˜λ―€λ‘œ, 이 글을 보고 μžˆλŠ” λ‹Ήμ‹  μ—­μ‹œ React 개발자라면, 별닀λ₯Έ μ„€λͺ…이 ν•„μš” 없을 μ •λ„λ‘œ μ΅μˆ™ν•  것이닀.

κ·Έλ ‡λ‹€λ©΄ useLayoutEffectλž€ 무엇이고, μ–΄λ–»κ²Œ λ‹€λ£°κΉŒ?

μ‚¬μš©λ²•

μ•„λž˜λŠ” useLayoutEffect의 기초적인 μ‚¬μš©λ²•μ΄λ‹€.

TSX

1
useLayoutEffect(callback, arr);

κ²°λ‘ λΆ€ν„° μ–˜κΈ°ν•˜μžλ©΄ useEffect와 μ‚¬μš© 방법이 μ™„μ „νžˆ λ™μΌν•˜λ‹€. 별닀λ₯Έ μ„€λͺ…이 ν•„μš” 없을 정도.

μ˜ˆμ‹œ μ½”λ“œ

TSX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { useLayoutEffect } from 'react';

function Component(): JSX.Element {
	useLayoutEffect(() => {
		const tag = document.getElementById('target');

		if (tag) {
			tag.innerHTML = `in client side at ${Date.now()}`
		}
	}, [ deps ])

	return (
		<div>
			<h1>title</h1>

			<p id="target">initial</p>
		</div>
	)
}

μ΄λŠ” μ˜ˆμ‹œ μ½”λ“œμ—μ„œλ„ λ‚˜νƒ€λ‚˜μžˆλŠ”λ°, useEffect와 useLayoutEffect의 ν‚€μ›Œλ“œλ§Œ 변경해도 μ •μƒμ μœΌλ‘œ λ™μž‘ν•¨μ€ λ¬Όλ‘ , μ΅œμ’… κ²°κ³Όλ¬Όλ§ˆμ € λ™μΌν•˜λ‹€.

κ·Έλ ‡λ‹€λ©΄ useEffect와 useLayoutEffect λ‹¨μˆœνžˆ μ•Œ 수 μ—†λŠ” 내뢀적인 이유둜 κ°ˆλΌμ‘Œμ§€λ§Œ, λ™μž‘μ€ 같은 μˆ¨κ²¨μ§„ 쌍λ‘₯μ΄μ˜€λ˜κ±ΈκΉŒ?

useEffect와 useLayoutEffect의 차이

μ•žμ„œ λ§ν–ˆλ“―μ΄, useEffect와 useLayoutEffect의 λ™μž‘ 방식은 λ™μΌν•˜λ‹€. μ°¨μ΄λŠ” λ‹€λ₯Έ 곳에 μžˆλŠ”λ°, λ°”λ‘œ λ™μž‘μ˜ μ‹œμ μ΄λ‹€.

React νŽ˜μ΄μ§€κ°€ μ‹€μ œ 우리 λˆˆμ— ν‘œν˜„λ˜λŠ” 과정은 크게 두 κ°€μ§€λ‘œ λ‚˜λ‰œλ‹€. ν”νžˆ λ§ν•˜λŠ” λ Œλ”λ§(rendering) 단계와 νŽ˜μΈνŒ…(painting) 단계가 μ‘΄μž¬ν•œλ‹€.

  • λ Œλ”λ§(rendering): DOM 트리λ₯Ό κ΅¬μ„±ν•˜κΈ° μœ„ν•΄, λ ˆμ΄μ•„μ›ƒ 및 μŠ€νƒ€μΌμ„ μ—°μ‚°ν•˜λŠ” κ³Όμ •
  • νŽ˜μΈνŒ…(painting): DOM 트리λ₯Ό μ‹€μ œλ‘œ ν‘œν˜„ν•˜λŠ” κ³Όμ •

보편적으둜 λ Œλ”λ§μ΄λΌ λ­‰λš±κ·Έλ € ν‘œν˜„ν•˜μ§€λ§Œ, μ‹€μ œλ‘œ νŽ˜μ΄μ§€κ°€ μ™„μ „νžˆ ν‘œν˜„λ˜λŠ” μ‹œμ μ€ νŽ˜μΈνŒ… μž‘μ—…μ΄ λλ‚œ 이후이닀. 슀크립트의 양이 ν¬κ±°λ‚˜ λ³΅μž‘ν•˜μ—¬, 연산이 였래걸릴 경우, μ‚¬μš©μžλŠ” μž₯μ‹œκ°„ 흰 화면을 보게 λœλ‹€.

useLayoutEffectλŠ” λ Œλ”λ§ 이후, νŽ˜μΈνŒ…μ΄ μ‹œμž‘λ˜κΈ° 이전에 λ™κΈ°μ μœΌλ‘œ λ™μž‘ν•˜λŠ” 훅이닀. λ°˜λŒ€λ‘œ useEffectλŠ” νŽ˜μΈνŒ… 이후 λΉ„λ™κΈ°μ μœΌλ‘œ λ™μž‘ν•œλ‹€.

각 ν›…μ˜ λ™μž‘ μ‹œμ 

κ°„λ‹¨ν•˜κ²Œ λ„μ‹ν™”ν•˜λ©΄ μœ„μ™€ 같은 방식이닀. useLayoutEffectλŠ” μ‚¬μš©μžκ°€ νŽ˜μ΄μ§€λ₯Ό 보기 전에 연산이 μΌμ–΄λ‚˜λ―€λ‘œ, μ΄ˆκΈ°κ°’ 연산에 μœ μš©ν•˜λ‹€.

useEffect둜 이λ₯Ό κ΅¬ν˜„ν•˜λ©΄, 기본값이 잠깐 ν‘œμ‹œλœ 이후, useEffect의 λ™μž‘μœΌλ‘œ μ•½κ°„μ˜ μ‹œκ°„μ°¨λ₯Ό 두고 λ°˜μ˜λ˜λŠ”κ±Έ λ³Ό 수 μžˆλ‹€. useLayoutEffectλŠ” μ‚¬μš©μžκ°€ νŽ˜μ΄μ§€λ₯Ό λ³Ό 수 μžˆλŠ” νŽ˜μΈνŒ… 이전에 λ™μž‘ν•˜λ―€λ‘œ, 초기 μ—°μ‚° κ³Όμ •μ—μ„œ λ‚˜νƒ€λ‚˜λŠ” 헛점을 숨길 수 μžˆλ‹€.

단, useEffect와 달리 λ™κΈ°μ μœΌλ‘œ λ™μž‘ν•˜λ―€λ‘œ, λ„ˆλ¬΄ λ³΅μž‘ν•œ 연산을 ν• λ‹Ήν•  경우 λ Œλ”λ§ μ‹œκ°„μ΄ κΈΈμ–΄μ§€λ―€λ‘œ μ£Όμ˜ν•΄μ•Όν•œλ‹€.

CodeSandbox둜 차이 λΉ„κ΅ν•˜κΈ°

CodeSandboxλ₯Ό 톡해 useEffect와 useLayoutEffectλ₯Ό λΉ„κ΅ν•΄λ³΄μž. μ™„μ „νžˆ λ™μΌν•œ λ™μž‘μ„ μˆ˜ν–‰ν•˜λŠ” 두 훅을 μž‘μ„±ν–ˆλ‹€.

각 훅은 λ°˜λ³΅λ¬Έμ„ 5000번 μˆ˜ν–‰ν•˜μ—¬, DOM에 ν…μŠ€νŠΈλ₯Ό ν‘œν˜„ν•œλ‹€.

useLayoutEffect둜 인해 초기 λ Œλ”λ§ μ‹œκ°„μ΄ μ†Œμš”λ˜λ©°, νŽ˜μΈνŒ…μ΄ μ™„λ£Œλ˜μ–΄ νŽ˜μ΄μ§€κ°€ ν‘œμ‹œλœ 직후, useEffectκ°€ λ™μž‘ν•œλ‹€.

λ•Œλ¬Έμ— μ‚¬μš©μžλŠ” useEffect의 λ™μž‘μ΄ λλ‚˜κΈ° μ „κΉŒμ§€ μ•½κ°„μ˜ 빈 곡간을 보게 λœλ‹€.

κ²°λ‘ 

useLayoutEffect와 useEffect의 μ‚¬μš©λ²•μ€ λ™μΌν•˜μ§€λ§Œ, λ™μž‘ μ‹œμ μ˜ μƒμ΄ν•¨μœΌλ‘œ 인해 차이가 λ°œμƒν•œλ‹€.

useLayoutEffect은 μž‘κ³  κ°„λ‹¨ν•œ 초기 연산에 μš©μ΄ν•˜λ©°, useEffectλŠ” 데이터 fetch, 이벀트 ν›… λ“± λ‹€μ–‘ν•œ λ‘œμ§μ„ μˆ˜ν–‰ν•˜λŠ” 데 μš©μ΄ν•˜λ‹€.

μš©λ„μ— λ§žλŠ” 훅을 μ‚¬μš©ν•¨μœΌλ‘œμ¨, νŽ˜μ΄μ§€μ˜ λ Œλ”λ§μ„ 효과적으둜 κ΄€λ¦¬ν•΄λ³΄μž.


🏷️ νƒœκ·Έ
# TypeScript
# React
# useEffect
# useLayoutEffect

μ½μ–΄μ£Όμ…”μ„œ κ³ λ§ˆμ›Œμš”!

도움이 λ˜μ…¨λ‹€λ©΄, κ³΅κ°μ΄λ‚˜ λŒ“κΈ€μ„ λ‹¬μ•„μ£Όμ‹œλŠ” 건 μ–΄λ–€κ°€μš”?

λΈ”λ‘œκ·Έ μš΄μ˜μ— 큰 힘이 λ©λ‹ˆλ‹€.

https://hits.seeyoufarm.com/api/count/incr/badge.svg?count_bg=%23484848&icon=react.svg&icon_color=dodgerblue&title=view&title_bg=%23242424&url=https%3A%2F%2Fblog.itcode.dev%2Fposts%2F2024%2F07%2F11%2Fuse-effect-use-layout-effect