리액트 이벤트 핸들러 에러코드와 this 그리고 바인딩 이슈

태현·2021년 5월 27일
1
post-thumbnail

리액트의 this는 무엇이고 바인딩은 무엇인가?

🙋🏻‍♂️안녕하세요, 이번 포스팅에서는 리액트 프로젝트에서 자주 사용되는 this에 대해서 공유해 볼까 합니다. 많은 도움이 되었으면 좋겠습니다.

문제는 여기서부터 시작되었습니다.

리액트 공식문서: 이벤트 처리하기

드리는 말씀

위의 사진은 리액트 프로젝트를 진행하면서 this바인딩 이슈를 잘 모르고 있다면 나올 수 밖에 없는 에러 코드입니다.
그래서 오늘은 이 전체적인 이야기를 해보겠습니다.

시작

리액트를 공부하기 이전에 저는 this 라는 것은 어느 정도는 알고 있었습니다.
이 때 어느 정도라는 말의 수준이 거의 없었어요.
하지만, this를 잘 알지 못해도 콘솔창에 한 번 찍어 볼 수는 있겠죠?
우리가 웹 브라우저에서 콘솔창에 this 라는 것을 한 번 출력해 보면, window 객체가 나옵니다.
그래서 저는 단순히 '개발자를 위해서 window 객체에 대한 정보를 알려주기는 해야 하는데 마땅히 이름을 지을게 없어서 this 로 지정해 놓았구나'😅 라는 생각만 하고는 그냥 넘어갔었어요. 2개월 전에는 자바스크립트도 할 줄 모르는 수준이었습니다. 그리고 이러한 부분에 대해서 전혀 깊게 생각하지 않았었죠.
아시겠지만 이건 단순히 넘어갈 부분이 아니더라구요.

예제를 만들어 볼게요.

//예시
const person = {
  name: "태현",
  age: 21,
  saySomeThing: function() {
    console.log(this.name);
  }
}
person.saySomeThing() // 태현

//변수에 담아서 출력이 안되기 때문에
const ref = person.saySomeThing()
ref(); // undefine

//saySomeThing에서 person까지 바인딩 해 줍니다.
const reft = person.saySomeThing.bind(person)
ref(); // 태현

자바스크립트에서 this는 단순히 window객체만을 출력하는 것이 아니라,
this는 상황에 따라 가르키고 있는 것이 바뀔 수 있습니다.
콘솔에 적힌 이 this라는 것은 그 메소드가 포함된 제가 만든 person을 가르켜요.

그런데, 제가 이 부분을 다시 변수 ref에다가 참조값 연결시키면, 값이 출력이 안됩니다. 당연하다고 생각하시는 분들도 있겠죠? 바로 person과의 관계가 없어지기 때문입니다.
이 때 우리가 바인딩 이 필요하다, 혹은 바인딩 해야한다. 라고 말할 수 있어요.

  • 상황 정리
    -상황에 따라서 바뀌는 this는 결국 객체 내부 등이나, 명시적으로 bind 시에 따라서 바뀜
    -this는 person객체가 되서 person.name을 출력할 수 있게 됨
    -this를 window가 아닌 다른 객체로 바꿔주는 함수는 call, apply, bind가 있음

리액트의 바인딩 이슈


리액트의 클래스 컴포넌트에서 이런 식으로 로직을 작성하여 버튼을 클릭 해 보면,

TypeError: Cannot read property 'setState' of undefined

라는 에러코드가 발생해요.
결국 this 가 가리키고 있는 것이 바인딩 이슈 가 있어서 불가합니다.
읽어올 수 없어요. 라는 뜻이라고 볼 수 있어요.

그래서 우리는 이러한 에러코드를 여러가지 방법으로 해결할 수 있습니다.
그건 다음과 같아요.

  • 컴포넌트의 생성자에서 바인딩

    하나, 생성자 밑에서 바인드 해 줍니다.

  • autobind-decorator를 import 후 사용

둘, 'autobind-decorator' 라는 것을 가져다 알맞게 씁니다.

  • ES6에서 추가된, arrow function 사용

셋, arrow function을 사용합니다.
arrow function이 this를 자동적으로 바인딩 해 준다고 해요.
대신 babel-preset-stage-2 패키지가 필요합니다.
const 등이 없는 실험적인 문법이라고 하지만 굉장히 유용할 것 같습니다.

  • 클래스 필드 문법을 사용하고 있지 않다면, 콜백에 화살표 함수를 사용

넷, 콜백에 화살표 함수를 쓰는 것입니다.
콜백에 화살표 함수를 쓰는 이러한 방법을 통해서 에러코드를 잡을 수 있지만 대가가 있어요, 단점이 있습니다.
대체로 많이 일어나지 않는데 해당하는 컴포넌트가 랜더링 될 때마다 다른 콜백이 생깁니다.
그래서 하위 컴포넌트에 props로 데이터가 전달된다면 추가적으로 자식 컴포넌트들이 다시 렌더링을 수행할 수 있어요. 이게 리액트 성능에 안 좋습니다.

결국

결국 이러한 부분들 때문에 함수형 컴포넌트를 쓰는 것 같다는 생각도 듭니다.
arrow function을 잘 쓰면 되는 것 아닌가 생각할 수도 있지만 이러한 바인딩 이슈 때문에 functional programming을 지향하는 사람들도 생겨날 것 같다는 생각이 들었어요.

그럼 이번 포스팅은 여기서 마치겠습니다. 프론트엔드 개발자가 되길 준비하는 사람으로서 동작 원리까지 다루지 못했는데 코어 자바스크립트 책을 한 번 사볼까 하는 생각이 들었습니다.
그럼 더 유익한 포스팅으로 찾아 뵙겠습니다.

출처: https://ko.reactjs.org/docs/handling-events.html

profile
안녕하세요, 지식을 공유하는 공간입니다.

2개의 댓글

comment-user-thumbnail
2021년 6월 18일

태현님 블로그 즐겨찾기 등록완료⭐

1개의 답글