JavaScript의 this 키워드 작동 방식

장택진·2024년 8월 7일
0


사내 레거시 코드를 개선하던 중 발생한 트러블 슈팅 내용입니다.

문제 발생 원인

B2B 페이지의 상품 등록 및 수정 페이지를 리팩토링하면서 발생.

ProductForm로직과 UI를 분리하기 위해 UI를 컴포넌트 단위로 수정했습니다.
UI 컴포넌트에 propsstate를 변경하는 setProduct라는 함수를 Container에서 넘겨줍니다.

UI 컴포넌트에서는 받은 props를 사용할 때 아래 사진과 같은 에러 발생 !!

원인 추론

JS에서의 this

JS에서 this는 함수를 호출하는 방식에 따라 그 값이 결정됩니다. 객체의 메서드로 함수를 호출하면, this는 그 객체를 가리킵니다. 하지만, 단순히 함수로 호출하면, this는 전역 객체(브라우저에서는 window, Node.js에서는 global)를 가리키거나, 엄격 모드('use strict')에서는 undefined가 됩니다.

JS에서의 class

JS 클래스 컴포넌트 내의 메서드는 기본적으로 그 컴포넌트 인스턴스에 바인딩되지 않습니다. 따라서, 컴포넌트의 메서드를 다른 컴포넌트의 prop으로 전달하거나, 이벤트 핸들러로 설정할 때, 그 메서드 내부에서 this를 사용하면, this는 컴포넌트 인스턴스를 가리키지 않게 됩니다. 이는 this.statethis.setState 같은 컴포넌트의 state에 접근하려 할 때 문제를 일으킵니다.

문제 해결

해결책1 : 함수 바인딩

이 문제를 해결하기 위한 방법 중 하나는 생성자(constructor) 내에서 메서드를 컴포넌트 인스턴스에 명시적으로 바인딩하는 것입니다. 이를 통해, 메서드가 어디서 호출되든 간에 this가 항상 해당 컴포넌트 인스턴스를 가리키도록 할 수 있습니다.

constructor(props) {
    super(props);
    this.setProduct = this.setProduct.bind(this);
}

이 코드는 setProduct 메서드 내의 this가 항상 해당 컴포넌트 인스턴스를 가리키도록 보장합니다. 그래서 this.statethis.setState와 같은 state 관련 작업을 안전하게 수행할 수 있게 됩니다.

해결책2 : 화살표 함수

클래스 문법을 사용하여 메서드를 화살표 함수로 선언하는 것은 this가 인스턴스를 가리키게 하는 또 다른 방법입니다. 이 방식을 사용하면, 생성자에서 메서드를 바인딩할 필요가 없습니다.

setProduct = () => {
    // 이곳에서의 this는 컴포넌트 인스턴스를 가리킵니다.
}

이 방법은 코드를 좀 더 간결하게 만들어주며, 바인딩을 잊어버려서 발생할 수 있는 버그를 예방해 줍니다.

현재는 setProduct를 사용하지 않고 productInput 컴포넌트를 활용하는 방식으로 수정했습니다.

profile
필요한 것은 노력과 선택과 치킨

0개의 댓글