ES6 Class의 메소드 (feat. Constructor Functions, 그리고 prototype)

02·2023년 5월 5일
0

JavaScript

목록 보기
1/3

'ES6 클래스'(이하 클래스)가 도입되면서 JavaScript 에서 OOP 방식 코딩을 하는 것이 수월해졌어요.

이전에는 OOP 구현에 Constructor Functions 를 이용했는데 이를 위해서는 Constructor Functions 자체의 동작 원리를 알아야 했어요.
초보 개발자는 물론 다른 언어에서 넘어온 개발자들에게도 적잖은 불편함이 있었죠.
클래스는 바로 이 Constructor Functions 에 문법 설탕을 씌워, 원리보다는 OOP 구현 자체에만 신경쓸 수 있도록 해준 문법적 설탕이예요.

그리고 이제는 VSCode 를 비롯한 코드에디터에서 Constructor Functions 를 작성하면 대신 클래스를 이용하라는 제안을 해줄 정도로 대체 과정은 원활하게 진행되고 있어요.하지만 Constructor Functions 의 원리를 이해하려는 노력은 JavaScript를 능숙하게 다루고 싶은 모든 개발자에게 여전히 유효해요.

클래스의 내부 원리를 학습하는 것에 큰 어려움은 없을 거예요.
Constructor Functions 에서 클래스로 넘어오는 과정에서 유의미한 기능이 분리 혹은 추가된 경우, 보통은 코드상에 명시적으로 드러나는 부분을 함께 만들어 놓았기 때문에 거기에 대해서 하나씩 찾아보는 것이 수월하거든요. (예컨대 private 프로퍼티(#.프로퍼티), constructor 메소드)
유의할 부분이 있다면, 겉에서 보기엔 별다를게 없는, 평범한 메소드 선언이예요.

Behind The Scene of 클래스 메소드

간단한 코드를 통해 알아볼거예요.

function AppThis() {
  this.메롱 = function () {
    console.log("메롱");
  };
}
function AppPrototype() {}

AppPrototype.prototype.메롱 = function () {
  console.log("메롱");
};
class AppClass {
  메롱() {
    console.log("메롱");
  }
}

이 코드블럭들은 모두 new operator 를 통해 호출시 동일한 동작을 하는 메롱 메소드를 실행할 수 있는 인스턴스(object)를 생성해요.

const appThis = new AppThis();
const appPrototype = new AppPrototype();
const appClass = new AppClass();
// 모두 동작합니다.
appThis.메롱(); // "메롱"
appPrototype.메롱(); // "메롱"
appClass.메롱(); // "메롱"

이렇게 인스턴스에서 쓰일 메소드는 그 인스턴스(this)에 정의됐을 수도 있고, Constructor Functionsprototype 에서 정의됐을 수도 있다는걸 알아야해요.
여기서 둘 사이의 차이점은

  • this 를 이용한 메소드 선언 방식은 Constructor Functions 에서 인스턴스를 찍어낼때마다 해당 메소드를 새로 만들어내게 된다는 것이고,
  • prototype 을 이용한 메소드 선언 방식은 prototype inheritance 로 모든 인스턴스에서 이미 정의된 하나의 원본 메소드를 참조한다는 것인데요.

즉, this 방식으로 메소드를 정의할 경우 프로젝트가 커질수록(= 인스턴스가 늘어날수록) 성능에 부하를 일으켜요.
그래서 마땅한 이유가 없다면 메소드는 꼭 prototype 에 선언하죠.

더 자주 쓰는 방식이 작성에는 더 품이 드는데 ES6를 추진하는 과정에서 이런 부분을 염두에 둔 것 같아요.
Enhanced Object Literal 등 다양한 함축을 허용해준 것 처럼 클래스에서도 메소드 선언시 prototype inheritance 를 이용하는 것이 디폴트가 되도록 해줬거든요.
아래 코드를 보면 우리가 따로 지정해주지 않았는데도 메롱 메소드가 prototype 안에 들어가 있는 것을 확인할 수 있어요.

// 클래스.prototype
console.log(AppThis.prototype); //{constructor: ƒ}
console.log(AppPrototype.prototype); // {메롱: ƒ, constructor: ƒ}
console.log(AppClass.prototype); //{constructor: ƒ, 메롱: ƒ}

// 인스턴스
console.log(appThis); //AppThis {메롱: ƒ}
console.log(appPrototype); // AppPrototype {}
console.log(appClass); // AppClass {}

마치며

라떼개발자들은 Constructor Functions 를 쓸 때 일일이 최적화를 해줬기에 자연스럽게 배우는 내용이지만, 클래스를 먼저 배우는 경우 놓치기 쉬운 지점을 간단히 알아보았습니다.

주의: 자동으로 prototype 에 선언하려면 위처럼 Function Declarations 방식으로 작성해야해요.
Function Expressions 혹은 Arrow Functions 방식을 사용하면 함수가 this 에 선언되거든요.

class AppClass {
  메롱 = function () {
    console.log("메롱");
  } 
}
profile
코스피 9000 기원, 내 취직도 기원

0개의 댓글