본문 바로가기
Today I Learned/SeSAC 웹 2기

React useRef, Lifecycle(useEffect) | 12주차 (1)

by suyeonnie 2025. 1. 14.

📂 오늘 배운 내용

리액트에서 요소를 선택하는 `useRef`

함수형 컴포넌트의 lifeCycle `useEffect`


ref (reference)

리액트에서 요소(HTML element) 선택하는 방법은

(1) Html에서 쓴 방식대로 id 지정

(2) ref 지정

 

-2가지 방식이 있는데, 1번 방식의 경우 같은 컴포넌트를 반복해서 사용하면 id가 중복되는 문제가 발생한다.

반면에 2번 방식 ref 지정은 컴포넌트 내부에서만 작동한다!

 

주로 DOM을 직접적으로 건드려야할 때 사용한다:

  • 특정 Input에 Focus 주기
  • 스크롤 박스 조작

 

함수형 컴포넌트  ref 사용하기 : `useRef()`

 

 

용도

(1) DOM 요소에 접근: `document.querySelector()`와 비슷!

  • 예: 버튼 클릭 시 input 요소에 포커스 주기
  • 근데 react-hook-form 라이브러리 사용하면 수동으로 ref 설정해 DOM 제어할 필요 없음

(2) 로컬 변수로 사용

  • 로컬변수: 컴포넌트가 리랜더링 되어도 값이 초기화되지 않고 그대로 유지
  • ref 값이 변경되어도 컴포넌트는 렌더링되지 않음
  • 상태 업데이트가 필요없는 데이터  저장에 유용함 (타이머, ID 값 관리)

 

Ref vs. State vs. Variable

  variable (js 변수) state ref
렌더링 여부 렌더링될 때마다
변수값 초기화*
State 값(데이터)  변경되면
렌더링 발생(Re-rendering)
ref 값 변경되어도
렌더링되지 않음
특징 - 컴포넌트 내부에서만 사용 가능

- UI 변경과 무관
- UI에 영향을 주는
데이터 관리에 적합
- DOM 요소에 직접 접근할 때

- 렌더링 필요없는 데이터 관리
활용 사례 - 간단한 계산

- 함수 내부 임시 데이터 저장
- 입력값 관리

- UI업데이트 필요한
상태 관리
- 포커스 관리

- 렌더링에
영향을 주지 않는 데이터
참고 예시 함수 내부 임시값 계산 버튼 클릭 시 UI 업데이트 input 포커스 주기,
스크롤 위치 관리

 

*리렌더링 되면 함수를 처음~끝까지 다시 읽기 때문에 값도 초기화된다.

 

state: `setState`를 사용해 상태를 업데이트하면 컴포넌트가 다시 렌더링된다.

 


Life cycle

리액트의 모든 컴포넌트들은 생애주기를 가져서 생성 -> 업데이트 -> 소멸의 과정을 거친다.

 

위 이미지에 나온 함수들은 클래스 컴포넌트에서 사용한다.  함수형 컴포넌트에서는 useEffect를 사용해 생애주기를 관리한다.

 

constructor 거의 사용하지 않지만 사용하는 경우: 

  • 업데이트 시점에는 동작하지 않고, 마운트 시점에만 동작이 필요한 경우
  • 상태 초기화와 부모 클래스의 생성자 호출이 필요한 경우
  • 복잡한 초기화 작업이 필요한 경우
  • 메서드 바인딩이 반드시 필요한 경우 (화살표 함수를 사용하지 않을 때)

 

함수형 컴포넌트 Life cycle : `useEffect()`

 

useEffect(callback, 배열)

  • useEffect는 비동기를 지원하지 않아서 콜백함수에 async await를 사용할 수 없다.
  • 따라서 async await를 사용하는 함수를 따로 만들어야 한다. 
  • useEffect 내 then catch는 가능

 

useEffect 생애 주기

 

1. 생성

useEffect(() => {
  console.log('컴포넌트가 생성됨');
}, []);
  • 컴포넌트가 화면에 나타남
  • 빈배열 전달 시 최초 마운트 시에만 실행
  • 주로 초기 데이터 가져오거나, 초기화 작업 시 사용
  • 예: API 호출, 이벤트 리스너 등록 

 

2. 업데이트 (=re-rendering)

 

상태나 props가 변경되어 다시 렌더링된다.

 

2-1. 의존성 배열 없는 경우:

useEffect(() => {
  console.log('컴포넌트가 업데이트됨');
});
  • 컴포넌트 리렌더링될 때마다 실행
  • 모든 state나 props의 변경에 반응

 

2-2. 의존성 배열 있는 경우:

useEffect(() => {
  console.log('count 값이 변경됨');
}, [count]);
  • 의존성 배열에 전달된 특정 값이 변경될 때만 실행
  • 보통 props/state값을 의존성 배열에 넣어줌. 관련있는 변수(데이터, 변수, 함수)는 다 넣어주자~!
  • 특정 데이터/ 상태 변경에 따라 부수 작업(side effect)를 실행해야 할 때
  • 예: 사용자가 입력한 값에 따라 검색 결과 업데이트

 

3. 제거

  • 컴포넌트 제거될 때(화면에서 사라질 때) 실행
  • `useEffect`의 반환 값으로 함수(cleanup) 제공하면 됨 → 제거될 때 Return 안의 함수가 동작함

 

반환 함수 동작 시점:

(1) 컴포넌트 언마운트될 때

useEffect(() => {
  console.log('컴포넌트가 생성됨');

  return () => {
    console.log('컴포넌트가 제거됨');
  };
}, []);

 

(2) 의존성 배열에 값이 있을 경우, 값이 변경되기 전에 기존의 cleanup 함수 실행

useEffect(() => {
  console.log('count 값이 변경됨');

  return () => {
    console.log('이전 count 상태 정리');
  };
}, [count]);

 

사용 사례 (잘 와닿지 않음🤢)

  • 이벤트 리스너 제거
  • 타이머 제거
  • 네트워크 요청 취소
  • 메모리 누수 방지

 


💡 깨달음

axios, fetch 등 시간이 걸리는 작업은 항상 UseEffect와 함께 쓴다! 

왜냐면 렌더링해서 화면도 바꿔줘야하고, 데이터도 불러와야하기 때문임.


🌐  참고

SeSAC x 코딩온 웹 개발자 풀스택 과정 2기

 

22. ref-lifecycle

[ref]

- 방명록

- inputContainer

- 숫자 퀴즈!

 

[useEffect] 포스트 목록 만들기