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개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN