React State로 상태 관리하기
-> useState와 리렌더링
이번에는 React의 핵심 기능 중 하나인 State(상태)에 대해 알아보겠습니다.
이전에는 Props를 통해 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하고, 이벤트 핸들링을 통해 버튼 클릭과 같은 사용자 행동을 처리했습니다.
하지만 실제 웹 애플리케이션에서는 사용자 행동에 따라 화면의 데이터가 변경되어야 합니다.
예를 들어 다음과 같은 경우입니다.
- 버튼을 클릭하면 숫자가 증가
- 스위치를 클릭하면 ON/OFF 변경
- 입력창에 입력한 내용이 화면에 반영
- 로그인 상태에 따라 다른 화면 표시
이처럼 변하는 데이터를 관리하고, 데이터가 변경되었을 때 UI를 다시 렌더링하기 위해 사용하는 것이 State입니다.
1. State란?
State는 컴포넌트 내부에서 관리하는 상태값입니다.
React 컴포넌트는 State를 이용해 현재 상태를 관리할 수 있습니다.
그리고 State가 변경되면 React는 해당 상태 변화를 감지하여 필요한 UI를 다시 렌더링합니다.
간단하게 표현하면 다음과 같습니다.
State 변경
↓
React가 상태 변경 감지
↓
컴포넌트 다시 렌더링
↓
변경된 State에 맞게 UI 업데이트
예를 들어 현재 숫자가 0이라고 가정해 보겠습니다.
현재 State: 0
사용자가 버튼을 클릭하여 State가 변경됩니다.
0 → 1
React는 State가 변경된 것을 감지하고 컴포넌트를 다시 렌더링합니다.
그러면 화면도 변경된 State 값에 맞게 업데이트됩니다.
화면: 0
↓ 버튼 클릭
State: 1
↓
다시 렌더링
↓
화면: 1
2. useState 사용하기
React에서 State를 생성하기 위해서는 useState를 사용합니다.
먼저 useState를 import 합니다.
import { useState } from 'react'
그리고 컴포넌트 내부에서 사용할 수 있습니다.
import './App.css'
import { useState } from 'react'
function App() {
const state = useState()
console.log(state)
return (
<></>
)
}
export default App
useState()의 결과를 콘솔에서 확인해 보면 배열 형태로 값을 반환하는 것을 확인할 수 있습니다.
[
현재 State 값,
State 값을 변경하는 함수
]
배열에는 두 개의 요소가 들어 있습니다.
첫 번째 요소
새롭게 생성된 State의 현재 값입니다.
현재 useState()에 초기값을 전달하지 않았기 때문에 초기값은 undefined입니다.
두 번째 요소
State의 값을 변경하는 함수입니다.
React에서는 이 함수를 이용하여 State를 변경합니다.
즉, useState()는 다음과 같은 형태의 값을 반환한다고 이해할 수 있습니다.
[
State 값,
State 변경 함수
]
3. 구조 분해 할당으로 State 사용하기
useState()가 배열을 반환하기 때문에 JavaScript의 구조 분해 할당을 사용하여 값을 꺼낼 수 있습니다.
const [state, setState] = useState()
여기서,
- state → 현재 State 값
- setState → State 값을 변경하는 함수
입니다.
일반적으로 다음과 같은 형태로 작성합니다.
const [상태값, 상태변경함수] = useState(초기값)
예를 들면 다음과 같습니다.
const [count, setCount] = useState(0)
여기서,
count → 현재 숫자 상태
setCount → count를 변경하는 함수
0 → 초기값
입니다.
4. 버튼 클릭으로 State 변경하기
이제 count라는 State를 만들고 버튼을 클릭할 때마다 숫자가 증가하도록 만들어 보겠습니다.
import './App.css'
import { useState } from 'react'
function App() {
const [count, setCount] = useState(0)
return (
<>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>
+
</button>
</>
)
}
export default App
처음 count의 값은 0입니다.
const [count, setCount] = useState(0)
화면에는 다음과 같이 표시됩니다.
0
[ + ]
버튼을 클릭하면 다음 코드가 실행됩니다.
setCount(count + 1)
현재 값이 0이라면,
count + 1
의 결과는 1입니다.
따라서 React의 상태 변경 함수를 통해 새로운 값이 설정됩니다.
0 → 1
이후 React는 State가 변경되었음을 감지하고 컴포넌트를 다시 렌더링합니다.
버튼 클릭
↓
setCount(count + 1)
↓
State 변경
↓
React 리렌더링
↓
변경된 count 값으로 UI 업데이트
따라서 화면의 숫자도 1로 변경됩니다.
5. 일반 변수와 State의 차이
일반 JavaScript 변수도 값을 변경할 수 있습니다.
let count = 0
count = count + 1
하지만 일반 변수의 값만 변경한다고 해서 React 화면이 자동으로 다시 렌더링되지는 않습니다.
반면 State를 사용하면,
const [count, setCount] = useState(0)
상태 변경 함수를 통해 값을 변경했을 때,
setCount(count + 1)
React가 상태 변경을 처리하고 화면을 다시 렌더링합니다.
따라서 React에서 UI에 영향을 주는 값은 일반 변수보다 State로 관리하는 것이 중요합니다.
구분일반 변수State
| 값 변경 가능 | 가능 | 가능 |
| 값 변경 시 UI 자동 업데이트 | 불가능 | 가능 |
| React가 변경 관리 | 하지 않음 | 함 |
| UI와 연결 | 직접 연결되지 않음 | 연결됨 |
6. 여러 개의 State 만들기
하나의 컴포넌트에는 여러 개의 State를 만들 수 있습니다.
예를 들어 숫자를 증가시키는 count와 조명의 상태를 관리하는 light를 각각 만들어 보겠습니다.
const [count, setCount] = useState(0)
const [light, setLight] = useState('OFF')
각 State는 독립적으로 관리됩니다.
- count → 숫자 상태 관리
- light → 조명 ON/OFF 상태 관리
전체 코드는 다음과 같습니다.
import './App.css'
import { useState } from 'react'
function App() {
const [count, setCount] = useState(0)
const [light, setLight] = useState('OFF')
return (
<>
<div>
<h1>{light}</h1>
<button
onClick={() =>
setLight(light === 'OFF' ? 'ON' : 'OFF')
}
>
{light === 'ON' ? 'Light OFF' : 'Light ON'}
</button>
</div>
<div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>
+
</button>
</div>
</>
)
}
export default App
7. ON/OFF State 변경하기
먼저 light State를 살펴보겠습니다.
const [light, setLight] = useState('OFF')
초기값은 OFF입니다.
화면에는 현재 State가 출력됩니다.
<h1>{light}</h1>
따라서 처음에는 다음과 같이 표시됩니다.
OFF
버튼을 클릭하면 다음 코드가 실행됩니다.
setLight(light === 'OFF' ? 'ON' : 'OFF')
삼항 연산자를 이용하여 현재 상태에 따라 새로운 값을 설정합니다.
현재 light가 OFF인가?
│
┌──┴──┐
Yes No
│ │
ON OFF
즉,
OFF → ON
ON → OFF
ON → OFF
OFF → ON
과 같이 버튼을 클릭할 때마다 상태가 변경됩니다.
버튼의 텍스트도 현재 상태에 따라 변경됩니다.
{light === 'ON' ? 'Light OFF' : 'Light ON'}
현재 조명이 ON이라면 버튼에는 Light OFF가 표시됩니다.
반대로 조명이 OFF라면 버튼에는 Light ON이 표시됩니다.
8. State와 UI의 관계
이번 예제에서 중요한 부분은 State 값에 따라 UI가 결정된다는 것입니다.
<h1>{light}</h1>
light의 값이 변경되면 화면에 표시되는 값도 변경됩니다.
light = OFF
↓
화면: OFF
버튼 클릭
↓
setLight('ON')
↓
State 변경
↓
리렌더링
↓
화면: ON
마찬가지로 count도 State 값에 따라 UI가 변경됩니다.
<h1>{count}</h1>
count = 0
↓
화면: 0
버튼 클릭
↓
setCount(count + 1)
↓
count = 1
↓
리렌더링
↓
화면: 1
이처럼 React에서는 현재 State를 기준으로 UI를 선언적으로 표현할 수 있습니다.
State가 변경되면 React가 다시 렌더링하고, 변경된 State에 맞는 UI가 화면에 반영됩니다.
9. State 변경 시 주의할 점
State는 직접 값을 변경하는 것이 아니라 상태 변경 함수를 사용해야 합니다.
예를 들어 다음과 같은 방식은 올바른 State 변경 방법이 아닙니다.
count = count + 1
State는 const로 선언되기도 하지만, 더 중요한 이유는 React가 State 변경을 관리하도록 해야 하기 때문입니다.
따라서 다음과 같이 작성합니다.
setCount(count + 1)
즉,
현재 State 값 확인
↓
새로운 State 값 생성
↓
상태 변경 함수 호출
↓
React가 상태 변경 처리
↓
필요한 UI 업데이트
의 흐름으로 동작합니다.
10. 이전 State를 기준으로 변경하는 방법
현재 예제에서는 다음과 같이 작성했습니다.
setCount(count + 1)
간단한 예제에서는 정상적으로 사용할 수 있습니다.
하지만 이전 State 값을 기준으로 새로운 State를 계산하는 경우에는 다음과 같은 함수 형태를 사용할 수도 있습니다.
setCount((prevCount) => prevCount + 1)
여기서 prevCount는 이전 State 값입니다.
이전 count
↓
prevCount
↓
prevCount + 1
↓
새로운 State
따라서 이전 상태를 기반으로 값을 업데이트할 때는 다음과 같은 형태도 자주 사용됩니다.
<button onClick={() => setCount((prevCount) => prevCount + 1)}>
+
</button>
11. 전체 코드 정리
최종 코드는 다음과 같습니다.
import './App.css'
import { useState } from 'react'
function App() {
const [count, setCount] = useState(0)
const [light, setLight] = useState('OFF')
return (
<>
<div>
<h1>{light}</h1>
<button
onClick={() =>
setLight(light === 'OFF' ? 'ON' : 'OFF')
}
>
{light === 'ON' ? 'Light OFF' : 'Light ON'}
</button>
</div>
<div>
<h1>{count}</h1>
<button
onClick={() =>
setCount((prevCount) => prevCount + 1)
}
>
+
</button>
</div>
</>
)
}
export default App
실행 결과는 다음과 같은 흐름으로 동작합니다.
[Light]
OFF
[ Light ON ]
버튼 클릭
↓
ON
[ Light OFF ]
────────────────
[Count]
0
[ + ]
버튼 클릭
↓
1
[ + ]
버튼 클릭
↓
2
[ + ]
마무리
이번에는 React에서 컴포넌트의 상태를 관리하는 State와 useState에 대해 알아보았습니다.
정리하면 다음과 같습니다.
- State는 컴포넌트 내부에서 관리하는 상태값이다.
- State 값에 따라 렌더링되는 UI가 달라질 수 있다.
- useState()를 이용해 State를 생성할 수 있다.
- useState()는 현재 State 값과 상태 변경 함수를 반환한다.
- 구조 분해 할당을 이용해 다음과 같이 사용할 수 있다.
const [state, setState] = useState(초기값)
- State 값은 상태 변경 함수를 이용해 변경한다.
setState(새로운값)
- State가 변경되면 React는 해당 컴포넌트를 다시 렌더링한다.
- 하나의 컴포넌트에는 여러 개의 State를 만들 수 있다.
- UI에 영향을 주는 데이터는 State로 관리할 수 있다.
- 이전 State를 기반으로 값을 변경할 때는 함수형 업데이트를 사용할 수 있다.
setCount((prevCount) => prevCount + 1)
React에서는 State가 현재 화면의 상태를 나타내고, 그 State를 기준으로 UI를 표현합니다.
그리고 사용자의 이벤트에 따라 State를 변경하면 React가 변경된 State에 맞게 화면을 다시 렌더링합니다.
이벤트와 State를 함께 사용하면 이제 버튼 클릭, 입력값 변경 등 사용자의 행동에 따라 동적으로 변화하는 React UI를 만들 수 있습니다.