데브코스에서 진행한 개인 프로젝트 - 노션 클론을 리팩토링하면서 생성자 함수로 작성된 컴포넌트를 클래스 문법으로 변경했습니다
리팩토링하면서 클래스는 어떤 특징들이 있는지 공부한 내용을 공유합니다
new
키워드와 함께 사용해서 객체를 생성하는 함수를 생성자 함수라고 합니다
생성자 함수는 일반적으로 대문자로 시작하도록 이름을 짓습니다
new를 붙이면 빈 객체를 만들어 this에 할당한 후 함수 내용을 실행합니다
this에 함수 내용대로 프로퍼티를 추가하고 마지막에 this를 반환합니다
기존 코드는 컴포넌트를 생성자 함수로 생성했습니다
function Component({ $target, initialState }) {
this.state = initialState;
const $div = document.createElement('div');
$target.appendChild($div);
this.setState = (nextState) => {
this.state = nextState;
this.render();
}
this.render = () => {
$div.innerHTML = `${this.state}에 따라 바뀜!`
}
this.render();
}
이런식으로 어느 위치에, 어떤 초기값을 가지고 있을지 입력받은 후에는
setState()로 상태를 바꾸면 렌더링도 같이 됩니다
위 생성자 함수로 만든 컴포넌트 코드를 클래스로 변경한다면 아래처럼 바꿀 수 있습니다
class Component {
constructor({ $target, initialState }) {
this.state = initialState;
const $div = document.createElement('div');
$target.appendChild($div);
this.render();
}
setState(nextState) {
this.state = nextState;
this.render();
}
render() {
this.$div.innerHTML = `${this.state}에 따라 바뀜!`
}
}
new
키워드 방어가 가능합니다생성자 함수를 new 키워드를 쓰지 않고 사용할 수도 있습니다
따라서 생성자 함수로 작성된 컴포넌트는 이에 대한 에러를 띄우는 방어 코드가 필요합니다
하지만 클래스 문법은 new 키워드와 함께 사용하지 않으면 에러가 발생하기 때문에 따로 방어 코드를 작성할 필요가 없습니다
클래스로 만들어진 객체는 특수 프로퍼티가 붙고, 이를 확인하는 과정이 있기 때문에 반드시 new 키워드를 사용해야 합니다
엄격모드가 무조건 좋은것은 아니라는 사람도 있지만
개발 단계에서 일어날 수 있는 실수 (없는 속성을 삭제, 전역에서 변수 선언 등)를 어느정도 방지할 수 있기 때문에 엄격모드를 사용하는것은 장점이 될 수 있습니다
이 특징은 장점인지 현재 써본적이 없어서 모르겠습니다
참고용으로만 보시는걸 추천드립니다
생성자 함수로 생성한 객체를 순회할 때 메소드가 포함되지만
클래스로 만든 객체를 순회할 때는 메소드가 포함되지 않습니다
클래스의 프로토타입에 추가된 메소드는 순환가능여부 플래그가 false가 되어 for문을 돌아도 제외됩니다
리액트 클래스 문법의 경우 리액트에서 정의한 Component를 상속받아서 확장해 사용합니다
클래스 상속, 확장은 클래스로 컴포넌트를 만들 때 장점입니다
위 특징들만 보면 클래스가 무조건 좋은것으로 보일수도 있지만, 꼭 그렇지많은 않습니다
자바스크립트는 객체 지향 언어로 설계되지 않았기 때문에 클래스라는 개념을 그대로 가져올 수 없었고, 현재 클래스 문법도 자바스크립트와 어울리지 않는다는 일부 의견이 존재합니다
리액트가 초기 클래스 문법에서 Hooks를 출시한것 이유에 클래스의 불편함 역시 포함됩니다
Stop using class in javascript
로 구글링해보면 클래스 사용을 반대하는 많은 글을 볼 수 있습니다
대표적으로 이런 글이 있겠습니다
클래스 상속 및 확장이 용이하지만, 이는 문제가 되기도 합니다
모든 프로퍼티를 상속받기 때문에 내가 원하지 않는 프로퍼티가 생길 수 있습니다
정리
제가 생성자 함수로 작성된 컴포넌트를 클래스로 변경한 이유는 new 키워드 방어에 도움이 되는 것 외에도
생성자 함수와 클래스 문법 모두 사용할 수 있음을 보여주기 위해서 변경했습니다
상태 관련 전체적 구조도 변경해야 하지만, 클래스로 작성하니 constructor() 부분에서 초기 동작과 메소드별 동작을 명확히 할 수 있어서 더 좋다고 느낍니다
참고
노션 클론 프로젝트 깃허브
David Fekke 블로그 - Why You Should Not Use Classes in JavaScript
어반베이스 기술블로그 - 생성자 함수 vs 클래스