create 구현 : immutable

SPANKEEE·2023년 3월 15일
0

리액트-시작

목록 보기
26/30

immutable

"원본을 바꾸지 않는다" 라고 하는 개념을 불변성, 영어로 immutable 이라고 한다.

concat() 을 사용할 수도 있지만
concat() 의 경우 모든 연산에 대해서 불변인지 가변인지를 판단 해야 한다.

간단하게 Array.from() API를 사용하면 새로운 배열이 만들어진다.

var a = [1,2];
var b = Array.from(a);
console.log(a,b,a==b);
---
> (2) [1, 2] | (2) [1, 2] | false

위 코드 실행 결과를 확인하면 a와 b의 출력은 동일하지만 a와 b는 같지 않는 것을 확인할 수 있다.

즉, a와 b는 내용이 같을 뿐 완전히 다른 배열이다.

var a = [1,2];
var b = Array.form(a);
b.push(3); // 이번엔 push 넣기
console.log(a,b,a==b);
---
> (2) [1, 2] | (3) [1, 2, 3] | false

위 코드처럼 b.push(3) 코드를 추가하여 b배열에 3을 넣게 될 때 b 배열에만 추가되는 것이다.

Array.from() 을 사용한 경우에는 push() 를 해도 원본 배열인 a 에 영향을 주지 않는다.

이전 챕터에 만든 애플리케이션에서 concat() 대신 Array.from() 을 적용할 수 있다.

  • App.js > else if(mode === create) 구문
_article = <CreateArti onSubmit = {function(_title, _desc){
  this.max_content_id = this.max_content_id + 1;
  var newContents = Array.from(this.state.contents); 
  // 임시 변수에 원본값 복사
  newContents.push(
  // 임시변수.push활용 새로운 값 주입
    {id:this.max_content_id, title:_title, desc:_desc}
  );
  this.setState({
    contents: newContents // 임시 변수를 입력
  });
  console.log(_title, _desc);
}.bind(this)}><CreateArti>
  • 실행결과

    <Navi> 영역에 새로운 컨텐츠가 추가되고,
    다른 목록을 클릭해도 해당 <Navi> 영역의 컨텐츠는 그대로 유지한다.

변경하고자 하는 데이터인 this.state.contents 데이터를 Array.from() 을 통해 복사하고

이렇게 복제한 newContents 에 새로 추가하고 싶은 datapush() 하도록 변경한다.

변경한 코드를 실행시키면 정상적으로 동작하고, 다른 목록을 클릭할 경우 render() 함수가 호출되지 않는 것을 확인할 수 있다.


Array.from() 은 배열의 경우에만 쓸 수 있다.

객체인 경우에 객체 내용을 바꾸지 않고 새로운 복제된 객체를 만들고 싶다면

Object.assign() 을 사용한다.


Object.assign()

var a = {name : 'kim'};
var b = Object.assign({},a);
console.log(a,b,a===b);
---
▶︎ {name: 'kim'} | {name: 'kim'} | false

Object.assign() 첫 번째 인자로는 빈 객체 혹은 새로운 객체를 주고, 두 번째로 a 객체를 준다.
콘솔 입력 결과 a 와 b 의 출력 내용은 동일하지만 서로 같은 것은 아닌 것을 확인할 수 있다.


  • 즉, Object.assign() 을 통해서 객체를 복제할 수 있고,
  • 배열은 Array.from() 을 통해서 할 수 있다.

추가로 첫번째 인자가 빈 객체가 아닌 경우의 출력도 확인해보자.

var a = {name:'kim'};
var b = Object.assign({left:1,right:2},a);
// b = {left: 1, right: 2, name: kim} 을 가진 상태다
b.name = 'lee';
console.log(a,b,a===b);
---
▶︎ {name: 'kim'} | {left: 1, right: 2, name: 'lee'} | false

첫번째 인자로 객체 {left:1,right:2}가 들어가고 두번째 인자는 a 객체의 name 이 추가된 것을 확인할 수 있다.

이렇게 배열과 객체를 복제할 수 있는 다양한 방법이 있다.


현재 애플리케이션의 state를 변경한 방식을 살펴보자.

  • App.js > render() > return
render() {
  // 렌더 체크
  console.log('App Render!');
  // console.log('render', this);
  return (
    <div className='App'>
      <Subject
        title={this.state.subject.title}
        sub={this.state.subject.sub}
        onChangePage={function () {
          // alert('myfcn!');
          this.setState({ mode: 'welcome' }); // <== 해당 코드
        }.bind(this)}

  );
}
  • 위 코드에서 this.setState({ mode: 'welcome' }) 와 같은 코드는 원본을 교체하는 방식이다.
  • this.state.contents.push() 를 수행한 것은 contents의 원본에 내용을 추가한 것이다.
  • this.state.contents.concat() 을 사용한 방식은 원본을 교체한 것이다.
  • Array.from() 을 사용한 것도 원본을 복제하여 그것으로 변경한 것이기 때문에 원본을 교체한 것이다.

이처럼 까다로운 내용은 immutable, immutable.js 를 검색해봐야 겠다.

자바스크립트의 배열을 사용할 때 push() 는 원본을 바꾸고 concat() 은 원본의 복제본으로 바꾸는 등 명령어들의 일관성이 떨어져서 해당 내용을 기억해야 하는 필요성이 있다.

이때 immutable.js 와 같은 라이브러리를 쓰면 유사 배열 유사 객체 같은 것을 만들고 이를 제어하는 방식은 반드시 immutable 한다.

무조건 불변이며, 무조건 원본을 바꾸지 않고 복제한 결과로 교체한 것을 리턴해준다.

profile
해야되요

0개의 댓글