의존성 배열
: useEffect 훅에서 특정 상태나 값이 변경될 때만 부수효과(side Effect)가 실행되도록 제어하는 배열.
이 배열은 useEffect의 두 번째 인자로 전달됨.
동작 방식
: 의존성 배열이 비어 있으면, useEffect는 컴포넌트가 처음 마운트 될 때 한 번만 실행됨.
특정 값들이 배열에 포함되어 있으면, 그 값들이 변경될 때마다 useEffect가 실행됨.
배열을 생략하면, useEffect는 컴포넌토가 매번 렌더링될 때마다 실행됨.
ex.
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Count changed:', count);
}, [count]); // count가 변경될 때만 useEffect 실행
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
이 코드에서 useEffect는 count 값이 변경될 때마다 실행됨.
메서드 바인딩(Method Binding)
: 객체의 메서드를 해당 객체에 묶어주는 작업을 의미.
특히 React의 클래스형 컴포넌트에서 이벤트 핸들러나 다른 메서드를 사용할 때 this 키워드를 올바르게 참조하기 위해 메서드를 바인딩 해야하는 경우가 있음.
바인딩의 필요성
: javascript에서 this는 호출 방식에 따라 달라짐. 클래스 메서드가 이벤트 핸들러로 사용될 때 this가 메서드를 호출한 객체(ex. 버튼 클릭 이벤트)로 설정될 수 있음. 이를 방지하고, 항상 클래스 인스턴스를 참조하게 하기 위해 바인딩이 필요함.
ex.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
// 메서드를 바인딩하지 않으면, this.increment에서 this가 undefined가 됨
this.increment = this.increment.bind(this);
}
increment() {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<button onClick={this.increment}>Increment</button>
);
}
}
여기서 increment 메서드(주로 카운터와 같은 기능을 구현할 때, 현재 값을 하나 증가시키는 역할을 함)는 this.increment.bind(this)를 통해 현재 인스턴스에 묶여야 함.
자동 바인딩 (화살표 함수 사용)
: 클래스 필드 문법을 사용해 메서드를 화살표 함수로 정의하면, 자동으로 바인딩 됩니다. 화살표 함수는 정의된 시점의 this를 유지함.
이 방식을 사용하면 코드가 더 간결해지고, 바인딩 실수를 줄여줌.
ex.
class MyComponent extends React.Component {
state = { count: 0 };
// 화살표 함수를 사용하면, 자동으로 바인딩됨
increment = () => {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<button onClick={this.increment}>Increment</button>
);
}
}
함수형 컴포넌트에서 바인딩
:this 키워드가 없으므로, 바인딩이 필요하지 않음. 이벤트 핸들러는 그냥 함수로 정의하고 필요에 따라 useState, useReducer, useRef 등을 사용해 상태를 관리함.
ex.
import React, { useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
return (
<button onClick={increment}>Increment</button>
);
}
렌더링
: 컴포넌트가 화면에 표시되는 과정. React에서는 렌더링이 새로운 UI를 계산하고, 이를 실제 DOM에 반영하는 과정을 의미함. 렌더링은 컴포넌트의 상태(state)나 속성(props)이 변경될 때마다 발생함.
과정
1. 초기 렌더링 : 컴포넌트가 처음 화면에 나타날 때 발생함.
2. 재렌더링 : 상태나 속성이 변경될 때, 변경될 내용을 반영하기 위해 컴포넌트가 다시 렌더링 됨.
3. 정적 렌더링 : 정적인 HTML 파일을 브라우저가 로드하여 UI를 처음으로 그릴 때 발생함.
최적화
: 불필요한 재렌더링을 방지하기 위해 React.memo, useMemo, useCallback과 같은 최적화 기법을 사용할 수 있음.
useRef
: React의 훅(hook) 중 하나로, 참조(ref / 특정 DOM 요소나 값에 접근할 수 있는 방법)를 관리하기 위해 사용됨.
useRef는 주로 직접 DOM 요소에 접근할 때 유용하며, 상태 업데이트 없이 값이 변해야 하는 경우에 사용됨.
예를 들어, 입력 필드에 포커스를 설정하거나 스크롤 위치를 제어할 때 사용할 수 있음.
반환값
: { current: value } 형태의 객체를 반환함. 이 객체는 컴포넌트가 렌더링 될 때마다 유지되며, 참조된 값은 current 속성을 통해 접근할 수 있음.
ex.
import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus(); // input 요소에 포커스 설정
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleFocus}>Focus the input</button>
</div>
);
}
→ useRef로 생성한 inputRef는 <input> 요소에 대한 참조를 유지하며, 버튼을 클릭하면 handleFocus 함수가 호출되고, inputRef.current.focus( )를 통해 입력 필드에 포커스가 설정 됨.
값 저장 및 유지
: useRef는 렌더링 간 값이 변하더라도, 컴포넌트가 다시 렌더링 되지 않도록 하는 방법으로 사용할 수 있음.
ex.
import React, { useRef, useState } from 'react';
function Timer() {
const [count, setCount] = useState(0);
const countRef = useRef(count);
const handleClick = () => {
countRef.current = countRef.current + 1;
setCount(countRef.current); // 상태 업데이트
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
→ countRef.current에 값을 저장하면 상태처럼 작동하지만, 값이 업데이트되더라도 컴포넌트가 자동으로 다시 렌더링 되지 않습니다. (이 방법은 컴포넌트가 렌더링될 때마다 값을 재계산할 필요가 없을 때 유용함)
특성 및 주의사항
1. 렌더링과 무관한 값 관리 : useRef의 값은 컴포넌트의 렌더링과 무관하게 유지됨. 따라서 상태를 업데이트 할 필요 없이, 값만을 저장하고 싶을 때 사용할 수 있음.
2. 상태와의 차이점 : useState는 상태가 변경될 때마다 컴포넌트가 재렌더링 되는 반면, useRef는 값이 변경되어도 컴포넌트가 재렌더링 되지 않음.
3. DOM 접근의 대안 : useRef는 클래스형 컴포넌트에서 사용되던 React.createRef의 함수형 컴포넌트 대안임. 주로 DOM에 직접 접근해야 할 때 사용됨.
4. 실시간 변수 저장 : 상태를 사용하지 않고, 컴포넌트의 렌더링과 무관하게 실시간으로 값이 변경되어야 하는 경우에 유용함.