75일차 - react tutorial 7탄

·2024년 3월 29일

react

useEffect 의존성 배열을 활용해서, 실행 민감도 조절

  • 민감도 조정!
  • 뭐가 바뀔때만 실행되는 함수를 만들 수 있다. 어떤 값이 바뀔때 캐치해서!
const Sub = ({appNo}) => {
	SubCallCount++;
	console.log(`Sub ${SubCallCount}번 실행됨`);

	const [no, setNo] = useState(0);
	const [no2, setNo2] = useState(0);
	
	useEffect(() => {
		console.log('effect 1 : 최초에 한번만 실행');
	},[]); // props : 상위 컴포넌트가 하위 컴포넌트에 값을 전달할때 사용하는 속성
	
	useEffect(() => {
		console.log('effect 2 : 부모의 appNo가 바뀔때마다 실행');
	},[appNo]);
	
	useEffect(() => {
		console.log('effect 3 : 나(Sub)의 no가 바뀔때마다 실행');
	},[no]);
	
	useEffect(() => {
		console.log('effect 4 : appNo 혹은 no가 바뀔때마다 실행');
	},[appNo, no]);
	
	useEffect(() => {
		console.log('effect 5 : 매번 실행');
	});

	return (
		<>
			<button onClick={() => setNo(no + 1)}>Sub 버튼(no) : {no}</button>
			<button onClick={() => setNo2(no2 + 1)}>Sub 버튼(no2) : {no2}</button>
		</>
	);
};

const App = () => {
	AppCallCount++;
	console.log(`App ${AppCallCount}번 실행됨`);

	const [no, setNo] = useState(0);

	return (
		<>
			<div style={{ border: "5px solid red", padding: 10 }}>
				App no : {no}
				
				<Sub appNo={no}/>
				<hr />
				<button onClick={() => setNo(no + 1)}>App 버튼 : {no}</button>
			</div>
		</>
	);
};

1~100까지 소수 찾기!

  • for(let i = 2; i <= 100; i++){: i라는 변수를 2부터 100까지 반복하면서 증가시키는 반복문을 시작합니다. 이 반복문은 소수를 찾기 위해 2부터 100까지의 모든 숫자를 확인한다.

  • let c = 0;: c라는 변수를 선언하고 0으로 초기화합니다. 이 변수는 현재 숫자 i가 나누어지는 수의 개수를 세는 데 사용된다.

  • for(let j = 1; j <= i ; j++){: 내부 반복문에서 j라는 변수를 사용하여 i를 1부터 i까지 반복하면서 나눌 수 있는지 확인한다.

  • if(i%j==0){ c=c+1; }: i를 j로 나누었을 때 나머지가 0이면, c를 증가시킵니다. 즉, j가 i의 약수라는 뜻이다.

  • if(c==2){ console.log(i); }: 외부 반복문에서 c가 2인 경우에만, 즉 약수가 1과 자기 자신뿐인 경우에만 i를 출력합니다. 따라서 이 때의 i는 소수다.

console.clear();

for(let i = 2; i <= 100; i++){
	let c = 0;
	for(let j = 1; j <= i ; j++){
		if(i%j==0){
			c=c+1;
		}
	}
		if(c==2){
			console.log(i);
		}
}

1부터 입력값까지의 소수갯수를 알려주는 로직 구현에 state 적용

// 소수 판별기(넘겨진 값이 소수인지 아닌지)
function isPrimeNumber(num) {
  if (num <= 1) return false;
  for (let i = 2; i < num; i++) {
    if (num % i == 0) {
      return false;
    }
  }
  return true;
}

// 1부터 n까지 수 중에서 소수만 배열담아서 리턴
function getPrimeNumbers(maxValue) {
  const primeNumbers = [];

  for (let i = 1; i <= maxValue; i++) {
    if (isPrimeNumber(i)) {
      primeNumbers.push(i);
    }
  }

  return primeNumbers;
}

function getPrimeNumbersCount(maxValue) {
  return getPrimeNumbers(maxValue).length;
}

const App = () => {
	const [inputedNo,setInputedNo] = useState(0);
	const primeNumberCount = getPrimeNumbersCount(inputedNo);
	
	const onSubmit = (e) => {
		e.preventDefault();
		
		const form = e.target;
		
		form.number.value = form.number.value.trim();
		
		if(form.number.value.length == 0){
			alert('숫자 써');
			form.number.focus();
			return;
		}
		
		const number = form.number.valueAsNumber;
		form.number.focus();
		
		setInputedNo(number);
		
		// alert(`네가 입력한 숫자는 ${number} (이)다.`);
	}
	
	return (
		<>
			<form onSubmit={onSubmit}>
				<input type="number" name="number" placeholder="숫자 입력해" defaultValue="0"/>
				<button type="submit">확인</button>
				<div>MAX : {inputedNo}</div>
				<hr/>
				<div>소수의 갯수 : {primeNumberCount}</div>
				<hr/>
			</form>
		</>
	);
};

1부터 입력값까지의 소수갯수를 알려주는 로직 구현에 useEffect 적용

// 소수 판별기(넘겨진 값이 소수인지 아닌지)
function isPrimeNumber(num) {
  if (num <= 1) return false;
  for (let i = 2; i < num; i++) {
    if (num % i == 0) {
      return false;
    }
  }
  return true;
}

// 1부터 n까지 수 중에서 소수만 배열담아서 리턴
function getPrimeNumbers(maxValue) {
  const primeNumbers = [];

  for (let i = 1; i <= maxValue; i++) {
    if (isPrimeNumber(i)) {
      primeNumbers.push(i);
    }
  }

  return primeNumbers;
}

function getPrimeNumbersCount(maxValue) {
  return getPrimeNumbers(maxValue).length;
}

const App = () => {
	const [no,setNo] = useState(0);
	const [inputedNo,setInputedNo] = useState(0);
	const [primeNumberCount, setPrimeNumberCount] = useState(0);
	
	// inputedNo 값이 변경 되었을 때만 재랜더링 
	useEffect(() => {
		const primeNumberCount  = getPrimeNumbersCount(inputedNo);
		setPrimeNumberCount(primeNumberCount);
	},[inputedNo]);
	
	const onSubmit = (e) => {
		e.preventDefault();
		
		const form = e.target;
		
		form.number.value = form.number.value.trim();
		
		if(form.number.value.length == 0){
			alert('숫자 써');
			form.number.focus();
			return;
		}
		
		const number = form.number.valueAsNumber;
		form.number.focus();
		
		setInputedNo(number);
		
		// alert(`네가 입력한 숫자는 ${number} (이)다.`);
	}
	
	return (
		<>
			<button onClick={() => setNo(no + 1)}>번호 : {no}</button>
			<hr/>
			<form onSubmit={onSubmit}>
				<input type="number" name="number" placeholder="숫자 입력해" defaultValue="0"/>
				<button type="submit">확인</button>
				<div>MAX : {inputedNo}</div>
				<hr/>
				<div>소수의 갯수 : {primeNumberCount}</div>
				<hr/>
			</form>
		</>
	);
};

useMemo

  • useMemo는 리액트에서 컴포넌트의 성능을 최적화 하는데 사용되는 훅이다.
  • useMemo에서 memo는 memoization을 뜻하는데 이는 그대로 해석하면 ‘메모리에 넣기’라는 의미다.
  • 컴퓨터 프로그램이 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술이다.

리액트 함수형 컴포넌트

  • 리액트에서 함수형 컴포넌트는 렌더링 => 컴포넌트 함수 호출 => 모든 내부 변수 초기화의 순서를 거친다.
const App = () => {
	const [no,setNo] = useState(0);
	const [inputedNo,setInputedNo] = useState(0);
	// const [primeNumberCount, setPrimeNumberCount] = useState(0);
	
// 	// inputedNo 값이 변경 되었을 때만 재랜더링 
// 	useEffect(() => {
// 		const primeNumberCount  = getPrimeNumbersCount(inputedNo);
// 		setPrimeNumberCount(primeNumberCount);
// 	},[inputedNo]);
	
	// 계산을 하거나 번호를 증가시키면 app재실행 -> 작동 시간 느림
	// const primeNumberCount  = getPrimeNumbersCount(inputedNo);
	
	// useMemo : 기억을 한다.
	// useMemo : iuputedNo 값이 바뀌면 getPrimeNumbersCount를 실행.
	// 저장장치를 쓴다와는 거리가 있다.
	const primeNumberCount  = useMemo(() => getPrimeNumbersCount(inputedNo),[inputedNo]);
	
	const onSubmit = (e) => {
		e.preventDefault();
		
		const form = e.target;
		
		form.number.value = form.number.value.trim();
		
		if(form.number.value.length == 0){
			alert('숫자 써');
			form.number.focus();
			return;
		}
		
		const number = form.number.valueAsNumber;
		form.number.focus();
		
		setInputedNo(number);
		
		// alert(`네가 입력한 숫자는 ${number} (이)다.`);
	}
	
	return (
		<>
			<button onClick={() => setNo(no + 1)}>번호 : {no}</button>
			<hr/>
			<form onSubmit={onSubmit}>
				<input type="number" name="number" placeholder="숫자 입력해" defaultValue="0"/>
				<button type="submit">확인</button>
				<div>MAX : {inputedNo}</div>
				<hr/>
				<div>소수의 갯수 : {primeNumberCount}</div>
				<hr/>
			</form>
		</>
	);
};

실행이 오래걸리는 PrimeNumbersCount 컴포넌트 구현

// 소수 판별기(넘겨진 값이 소수인지 아닌지)
function isPrimeNumber(num) {
  if (num <= 1) return false;
  for (let i = 2; i < num; i++) {
    if (num % i == 0) {
      return false;
    }
  }
  return true;
}

// 1부터 n까지 수 중에서 소수만 배열담아서 리턴
function getPrimeNumbers(maxValue) {
  const primeNumbers = [];

  for (let i = 1; i <= maxValue; i++) {
    if (isPrimeNumber(i)) {
      primeNumbers.push(i);
    }
  }

  return primeNumbers;
}

function getPrimeNumbersCount(maxValue) {
  return getPrimeNumbers(maxValue).length;
}

const PrimeNumbersCount = ({max}) => {
	const count = getPrimeNumbersCount(max);
	
	return <>
		<div style={{border:"10px solid black", padding: 50, display: 'flex', alignItems:'center', justifyContent:'center'}}>
			1부터 {max} 사이에 존재하는 소수의 갯수 : {count}</div>
		</>
}

let AppCallCount = 0;

const App = () => {
	AppCallCount++;
	console.log(`App이 ${AppCallCount}번 실행`);
	
	return (
		<>
			<PrimeNumbersCount max={100}/>
			<hr/>
			<PrimeNumbersCount max={200}/>
			<hr/>
			<PrimeNumbersCount max={300}/>
			<hr/>
			<PrimeNumbersCount max={200000}/>
			</>
	);
};

useEffect로 속도 최적화

const PrimeNumbersCount = ({max}) => {
	// const count = getPrimeNumbersCount(max);
	
	const [count, setCount] = useState(0);
	
	useEffect(() => {
		const count = getPrimeNumbersCount(max);
		setCount(count);
	}, [max]);
	
	return <>
		<div style={{border:"10px solid black", padding: 50, display: 'flex', alignItems:'center', justifyContent:'center'}}>
			1부터 {max} 사이에 존재하는 소수의 갯수 : {count}</div>
		</>
}

useMemo로 속도 최적화

const PrimeNumbersCount = ({max}) => {
	const count = useMemo(() => getPrimeNumbersCount(max), [max]);
	
//  const [count, setCount] = useState(0);
// 	useEffect(() => {
// 		const count = getPrimeNumbersCount(max);
// 		setCount(count);
// 	}, [max]);
	
	return <>
		<div style={{border:"10px solid black", padding: 50, display: 'flex', alignItems:'center', justifyContent:'center'}}>
			1부터 {max} 사이에 존재하는 소수의 갯수 : {count}</div>
		</>
}

useCallBack

  • useCallback 또한 메모이제이션 기법으로 컴포넌트 성능을 최적화 시켜주는 도구이다.
  • useCallback도 useMemo와 유사하다. 대신에 useCallback은 인자로 전달한 콜백 함수 그 자체를 메모이제이션 하는 것이다.
useMemo(() => {
	return value;
}. [item])
  • 구조

    • useCallback은 두 개의 인자를 받는다.
    • 1번째 인자로는 메모이제이션 해 줄 콜백함수를 받는다.
    • 2번째 인자로는 의존성 배열을 받는다.
  • 정보를 얻은 출처

놀라운 사실

  • 사실 자바스크립트의 함수는 객체의 한 종류이다!!

TODO

  • 리액트 복습(useEffect, useMemo, useRef, immer, useCallBack)
  • 재료공구 리스트 피그마 퍼블리싱 끝내기

느낀점

  • 리액트.. 사실 조금 배우고 말줄 알았는데 hook 점점 늘어난다.. 뭐 이렇게 비슷한애들을 많이 만들어놓은걸까.. 완전 흠냐뤼..
profile
우당탕탕 연이의 개발일기

0개의 댓글