티스토리 뷰
React state 선언 과정에서는 왜 const를 쓸까?
최근 JavaScript를 이용하여 알고리즘 문제를 풀이하다 궁금증이 들게 되었다.
React 공식문서에서 볼 수 있듯, 우리는 당연하게 const를 이용한 상태 관리 hook useState를 사용하고 있었던 것이다.
왜 우리는 const로 사용해야 하고, React에서는 어떻게 동작하는지 알아보도록 하자.
1. React의 상태 관리 원리
JavaScript에서는 데이터 타입을 다음과 같이 분류한다.
- Primitive Data Types (원시 타입)
- undefined
- Boolean
- Number
- String
- BigInt
- Symbol
- …
- Structural Data Types (참조 타입)
- Object
- Functions
- Array
- Map
- …
변수를 통해 값을 재할당하는 경우, immutable한 타입은 value
값 자체를 전달하기 때문에, 기존의 데이터와 독립된 형태로 사용이 가능하다.
mutable한 타입의 경우, reference
를 전달하여 같은 메모리 주소를 공유한다.
즉, mutable value는 값의 메모리 주소를 참조하여 사용하는 방식이기 때문에, 값을 변경하는 경우 해당 값을 사용하는 모든 곳에 영향을 주게 된다. → Side Effect(부수 효과)
가 발생하게 되는 것이다.
이러한 문제들을 해결하기 위해서는 약간의 비용을 조금 더 들이지만 객체를 불변 객체 형태로 사용하는 것이다.
React에서는 이러한 이유로 useState
는 상태 값을 불변으로 유지하면서 새로운 상태 값을 생성하여 React 컴포넌트가 이를 감지하고 다시 렌더링하도록 설계되어 있다.
즉, 상태 변경은 항상 React의 내부 메커니즘을 통해 이루어지며, state
변수 자체를 직접 변경하지 않는 구조라고 볼 수 있다.
여기서 중요한 점은 state 변수 자체를 직접 변경하지 않는다는 것!
2. const, var, let의 차이
그렇다면 왜 const를 사용했을까?
var
, let
, const
는 JavaScript에서 변수를 선언할 때 사용하며, 서로 다른 동작 방식과 스코프 규칙을 가지고 있다.
1. 선언 및 재할당 가능 여부
키워드 | 재선언 가능 여부 | 재할당 가능 여부 |
---|---|---|
var |
가능 | 가능 |
let |
불가능 | 가능 |
const |
불가능 | 불가능 |
var
: 같은 이름의 변수를 다시 선언할 수 있다.var x = 10; var x = 20; // 재선언 가능 console.log(x); // 20
let
: 같은 이름으로 변수를 다시 선언할 수 없다. 하지만 값의 재할당은 가능.let y = 10; // let y = 20; // SyntaxError: Identifier 'y' has already been declared y = 20; // 재할당 가능 console.log(y); // 20
const
: 선언 이후 값을 변경하거나 재선언할 수 없다.const z = 10; // z = 20; // TypeError: Assignment to constant variable // const z = 30; // SyntaxError: Identifier 'z' has already been declared console.log(z); // 10
2. 스코프(Scope)
키워드 | 스코프 종류 | 스코프 특징 |
---|---|---|
var |
함수 스코프 | 블록 내부에서 선언해도 함수 바깥에서 접근 가능 |
let |
블록 스코프 | 블록 내부에서만 접근 가능 |
const |
블록 스코프 | 블록 내부에서만 접근 가능 |
var
의 함수 스코프if (true) { var x = 10; } console.log(x); // 10 (블록 스코프를 무시)
var
로 선언된 변수는 블록({ })을 무시하고 함수 내부 어디서든 접근할 수 있다.
let
과const
의 블록 스코프if (true) { let y = 20; const z = 30; } // console.log(y); // ReferenceError: y is not defined // console.log(z); // ReferenceError: z is not defined
let
과const
는 블록({ }) 내부에서만 유효하다.
3. 변수 호이스팅(Variable Hoisting)
키워드 | 호이스팅 여부 | 초기화 시점 |
---|---|---|
var |
호이스팅 됨 | undefined 로 초기화 |
let |
호이스팅 됨 | 초기화 전 접근 시 에러 |
const |
호이스팅 됨 | 초기화 전 접근 시 에러 |
호이스팅이란?
변수 선언이 코드의 맨 위로 끌어올려지는 현상을 말한다.
이 때, var과 let, const 간에 초기화 과정에 차이가 존재한다.
var
는 호이스팅 후 초기화가undefined
로 됨.console.log(a); // undefined var a = 10;
let
과const
는 호이스팅 되지만, 초기화되기 전 접근하면 에러 발생.console.log(b); // ReferenceError: Cannot access 'b' before initialization let b = 20;
4. 기본적인 사용 권장 사항
var
는 사용을 지양해야 함: 함수 스코프와 호이스팅 특성으로 인해 의도치 않은 버그가 발생할 가능성이 높음.let
은 값의 변경이 필요한 경우 사용: 재할당이 필요한 변수에 적합.const
는 값의 변경이 없는 경우 사용: 상수 선언이나 값 변경을 방지하고 싶을 때 사용.
3. const로 state를 관리하는 내부 사정
const
로 선언된 변수는 참조 자체가 변하지 않는다.
(물론 참조하는 값인 객체나 배열과 같은 요소는 내부적으로 변경이 이뤄질 수 있지만..!)
React의 상태에서 const
를 사용하는 이유는 크게 아래 두 가지로 볼 수 있다.
1. 상태의 참조를 고정하기 위해
React는 useState
로 반환된 state
와 setState
를 특정 컴포넌트의 상태 관리와 연결한다. 이 연결을 깨지 않기 위해 상태 변수(state
)를 재할당하지 않는 것이 중요한 것.
const [count, setCount] = useState(0);
// 잘못된 예: 상태 참조를 재할당 (의도한 동작이 깨질 수 있음)
count = 5; // TypeError: Assignment to constant variable
2. 의도하지 않은 상태 변경 방지
const
를 사용하면 상태 참조를 재할당할 수 없으므로 실수로 state
를 직접 변경하는 상황을 방지할 수 있다. 대신 setState
를 사용하도록 유도하여 React의 올바른 상태 관리 규칙을 따르게 하는 것이다.
3. let 또는 var를 사용할 수 없음
let
이나 var
는 동일한 변수에 대해 재할당이 가능하므로 상태 관리 로직을 혼란스럽게 만들 수 있다. 예를 들어, 아래와 같이 상태를 직접 변경하거나 참조를 재할당하면 React의 상태 관리 시스템이 이를 감지하지 못하게 된다.
let [count, setCount] = useState(0);
// 잘못된 예: 상태를 직접 변경 (React는 이를 감지하지 못함)
count = 5;
// 올바른 예: 상태를 변경하려면 반드시 setState를 사용
setCount(5);
React에서는 상태가 변경되면 렌더링 트리
를 새롭게 생성
한다. 만약 immutable
하게 데이터를 변경하지 않는다면, 새로운 객체가 생성되지 않고, 메모리 주소에 있는 데이터만 변경되기 때문에, React에서는 상태의 변경
을 감지할 수 없게 된다.
마무리
오늘은 그동안 가볍게 넘어갈 수 있었던 내용에 대해 알아보았다.
단순히 이렇게 사용하는구나라고 생각하고 넘어가기에는 기본적인 구조 자체를 이해하도록 도움을 주는 근본적인 개념이다보니, 변수와 상태를 작성하는 과정에서도 많은 것을 고려하며 작성해야 한다는 것을 깨닫게 했다.
이번 변수 스코프에 작성한 김에 다음 포스팅에서는 스코프에 대해 톺아보고, 클로저에 개념에 대해 알아보도록 해봐야겠다.
참고 자료
'Front-End' 카테고리의 다른 글
[TypeScript] 제네릭(Generic)이란 무엇인가? (1) | 2025.01.02 |
---|
- Total
- Today
- Yesterday
- 자바스크립트 변수
- TypeScript
- 리액트
- 제네릭
- 자바스크립트 const let var 차이
- 프론트엔드
- 타입 선언
- Generic
- 변수 별 차이
- const let var 차이
- react
- 자바스크립트
- 타입스크립트
- JavaScript
- 상태관리
- 리액트 상태관리
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |