React/ReactThreeFiber

useEffect & useRef

최 수빈 2025. 3. 14. 01:47

 

useEffect & useRef

 

useEffect

 

컴포넌트에서 부수 효과(Side Effects)를 처리할 때 사용되는 Hook

 

  • Side Effects 관리
    API 호출, 타이머 설정, 구독(subscription)등의 작업을 처리할 때 사용
    React의 렌더링 흐름과 독립적으로 실행됨
  • 컴포넌트 생명주기 관리(라이프사이클 제어 가능)
    클래스형 컴포넌트의 componentDidMount, componentDidUpdate, componentWillUnmount를 대체
    특정 시점(마운트, 업데이트, 언마운트)에서 실행되는 코드를 넣을 수 있음
  • 의존성 배열을 활용한 조건부 실행
    특정 상태 값이 변경될 때만 실행되도록 제어 가능

 

useEffect 기본 문법

useEffect(() => {
  console.log("컴포넌트가 마운트 또는 업데이트됨");

  return () => {
    console.log("컴포넌트가 언마운트됨");
  };
}, [/* 의존성 배열 */]); 

 

라이프사이클 단계별 실행

 

Mount (처음 렌더링 시 실행)

useEffect(() => {
  console.log("컴포넌트가 마운트됨");
}, []); // 빈 배열이면 한 번만 실행됨

componentDidMount  useEffect(() => {}, [])

 

Update (특정 상태가 변경될 때 실행)

useEffect(() => {
  console.log("firstName이 변경됨:", firstName);
}, [firstName]); // firstName이 변경될 때 실행됨

componentDidUpdate  useEffect(() => {}, [의존성])

 

Unmount (컴포넌트가 사라질 때 실행)

useEffect(() => {
  return () => {
    console.log("컴포넌트가 언마운트됨");
  };
}, []);

componentWillUnmount  useEffect(() => { return () => {}; }, [])

 

의존성 배열을 활용한 실행 조건

의존성 배열실행 조건

[] (빈 배열) 마운트될 때 한 번 실행
[firstName] firstName이 변경될 때마다 실행
없음 컴포넌트가 렌더링될 때마다 실행

 

*useEffect가 두 번 실행되는 문제

React의 StrictMode가 활성화된 경우(Indes.jsx) 개발 모드에서 일부 Hook이 두 번 실행될 수 있음

해결 방법: index.js에서 <React.StrictMode>를 제거

 

 

 

useRef

 

DOM 요소에 직접 접근하거나, 값이 변경되어도 리렌더링을 발생시키지 않는 변수를 저장할 때 사용

 

  • DOM 요소에 직접 접근
    ref 속성을 이용해 특정 요소를 제어할 수 있음
  • 렌더링 없이 값 유지
    useState와 달리, 값이 변경되어도 렌더링이 발생하지 않음
  • 이전 값 저장
    useRef를 이용해 이전 상태 값을 추적할 수 있음

 

useRef 기본 문법

const inputRef = useRef(null);

<input ref={inputRef} />;
  • inputRef.current를 통해 실제 DOM 요소에 접근 가능
  • .focus(), .value 등을 활용하여 직접 조작할 수 있음

 

useRef vs. useState

기능 useRef useState
렌더링 발생 여부 X O
DOM 직접 접근 가능 불가능
값 유지 가능 가능

 

 

 

useRef 활용 예

 

1. 입력창에 포커스 자동 맞추기

function InputFocus() {
  const inputRef = useRef();

  useEffect(() => {
    inputRef.current.focus(); // 마운트될 때 자동으로 포커스
  }, []);

  return <input ref={inputRef} placeholder="자동 포커스" />;
}

 

2. 이전 값 저장

function PreviousValue() {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef();

  useEffect(() => {
    prevCountRef.current = count;
  }, [count]);

  return (
    <div>
      <p>현재 값: {count}</p>
      <p>이전 값: {prevCountRef.current}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

 

 

 

최종 코드

import React, { useState, useRef, useEffect } from "react";

// 컴포넌트 생명주기
// 1. DOM이 마운트됨 (Mount)
// 2. 상태가 변경됨 (Update)
// 3. DOM이 언마운트됨 (UnMount)

function App() {
  const [formData, setFormData] = useState({
    firstName: "",
    userAlias: "",
  });

  const firstNameInputRef = useRef();

  const { firstName, userAlias } = formData;

  useEffect(() => {
    console.log(`First Name Updated: ${firstName}`);

    return () => {
      console.log("unmounted");
    };
  }, [firstName]);

  const handleInputChange = (e) => {
    const { value, name } = e.target;
    setFormData({
      ...formData,
      [name]: value,
    });
  };

  const handleReset = () => {
    setFormData({
      firstName: "",
      userAlias: "",
    });

    firstNameInputRef.current.focus();
  };

  return (
    <div>
      <input
        name="firstName"
        placeholder="First Name"
        onChange={handleInputChange}
        value={firstName}
        ref={firstNameInputRef}
      />
      <input
        name="userAlias"
        placeholder="Alias"
        onChange={handleInputChange}
        value={userAlias}
      />
      <button onClick={handleReset}>Reset</button>
      <div>
        <strong>Values: </strong>
        {firstName} ({userAlias})
      </div>
    </div>
  );
}

export default App;

 

useEffect,useRef

 

'React > ReactThreeFiber' 카테고리의 다른 글

3D 오브젝트 불러오기  (0) 2025.03.14
useContext  (0) 2025.03.14
React로 사고하기  (1) 2025.03.13
Component  (0) 2025.03.12
Event Handling  (0) 2025.03.12