본문 바로가기

프로그래밍&IT/React & CSS

[Fast Campus , React] 8. TicTacToe 앱 만들기 (4) 이벤트 변화, 불변성 (stack, heap 메모리)

 

이벤트 변화

무언가를 "기억하게" 만들어 "뭔가 (X)"를 표시하려 한다.

이때 component는 state를 사용하게 된다

 

Square클릭할 때, 호출할 함수생성 (Board.js)

handleClick(i) {
    const square = this.state.squares.slice(); // slice로 통째 복사
    squares[i] = 'X';
    this.setState({squares: squares});
}

Array.prototype.slice()

어떤 배열의 begin부터 end까지 (end미포함)에 대한 얕은 복사본을 새로운 배열객체로 반환.

원본배열은 바뀌지 않는다.

 

위에서 만든 함수를 props로 Square컴포넌트에 전달 ( Board.js)

<props에 함수도 저장할 수 있다?>

    renderSquare(i) {
        return <Square
            value={this.state.squares[i]}
            onClick={() => this.handleClick(i)}
        />
    }

내려받은 props를 위한 Square컴포넌트도 변경한다 (Square.js)

render() {
        return (
            <button className="square" onClick={()=> this.props.onClick()}>
                {this.props.value}
            </button>

 

리액트 불변성 지키기

불변성? 값이나 상태를 변경할 수 없는 것을 의미.

자바스크립트 타입을 통해서 알아본다면, <C#이나 java나 동일한?>

  • 원시타입 : 불변성 (immutable) - Boolean, String, Number, null, undefined, Symbol
  • 참조타입 : mutable - Object, Array

기본적으로 원시타입에 대한 참조 및 값을 저장하기 위해 call stack 메모리 공간 사용.

참조타입은 heap이란 별도 메모리 공간을 사용.

이 경우 개체 및 배열 값이 아닌, heap 메모리 참조 ID를 값으로 저장

원시타입  - 고정된 크기로 call stack메모리에 저장. 실제 데이터가 변수에 할당
- let name = "John"
  name = "Smith"
  name 변수를 Smith로 대체한 것이 아닌 메모리 영역 a에 있는 John을 그대로 두고, 메모리 영역 b에
  Smith를 새로 할당한 것 (불변성을 위해서 따로 신경써주지 않아도 된다)
참조타입 - 데이터크기가 정해지지 않고 call stack 메모리에 저장. 데이터값이 heap에 저장되며, 변수에 heap메모리의 주소값이 할당
- let arr = ['a', 'b', 'c']
  arr = ['d', 'e', 'f' ]
  call stack의 참조 ID는 동일하게 유지되고 heap 메모리에서만 변경된다.
  (불변성이 유지되지 않기에 리액트에서 따로 신경을 써줘야 한다)

불변성을 지켜야 하는 이유?

  1. 참조타입에서 객체, 배열의 값이 변할 때 원본 데이터가 변경되기에 이 원본 데이터를 참조하고 있는 다른 객체에서 예상치 못한 오류가 발생할 수 있어서 프로그래밍 복잡도가 상승
  2. 리액트에서 화면을 업데이트할 때 불변성을 지켜서 값을 이전값과 비교해서 변경된 사항을 확인한 후 업데이트하기에 불변성을 지켜줘야 한다

불변성을 지키는 방법.

- 참조타입에선 값을 바꿨을 때 call stack주소값은 같은데 heap값만 바꿔주기에 불변성을 유지할 수 없으므로 아예 새로운 배열을 반환하는 메서드를 사용한다.

spread operator, map, filter, slice, reduce

- 원본 데이터를 변경하는 메소드 : splice, push