본문으로 바로가기

[JavaScript] Factory Pattern, 생성자 함수, class(클래스) 

Object (객체)를 생성하는 방법은 많이 있습니다. 그 중에서 해당 게시글에서는 Factory function, 생성자 함수, class 로 객체를 만드는 방법을 알아보도록 하겠습니다. 해당 게시글은 뭐가 좋고 나쁘고의 중점을 두는 것이 아니라 각각이 뭔지에 대해 간단하게 알아봅니다.

Factory Pattern, 생성자 함수, 클래스 class

동일한 객체를 계속 만들어야 한다고 가정 해보겠습니다. 예를들어 Person 객체를 계속 만들어야 한다고 가정해보겠습니다. 그럼 기존 Factory Pattern에서는 아래와 같이 코드를 작성하였습니다.

function createPersonObject(name, gender, age) {
  return {
    name,
    gender,
    age
  };
}

const person1 = createPersonObject("홍길동", 0, 50);
const person2 = createPersonObject("강짱구", 1, 30);

코드를 보면 깔끔해보입니다. 객체를 return 해주는 함수를 만들어 사용하고 있습니다. 또 많이 사용하는 방법으로는 생성자 함수가 있습니다. 아래 코드를 확인해봅시다.

function Person(name, gender, age) {
  this.name = name;
  this.gender = gender;
  this.age = age;
}

const person1 = new Person("홍길동", 0, 50);
const person2 = new Person("강짱구", 1, 30);

생성자 함수의 경우 new를 붙이게 되면 this는 새로운 객체의 자기 자신이 됩니다. 이 코드도 깔끔해보입니다. 큰 문제가 없어보이죠. 사실 어떤 방법도 문제는 없는데 개발자가 실수를 하면 큰 문제가 생깁니다 (사실 실수만 안하면 뭐 ...). 실수로 new를 빼고 적었다고 가정해봅시다. 그럼 this는 기본 window가 되어 버립니다. 그럼 window의 속성을 바꾸게 되는 것이죠. 이러한 실수는 누구나 할 수 있습니다. 아래는 new를 빼고 작성한 코드입니다.

function Person(name, gender, age) {
  this.name = name;
  this.gender = gender;
  this.age = age;
}

const person1 = Person("홍길동", 0, 50);
const person2 = Person("강짱구", 1, 30);
</div

위 코드의 this 값은 새로 생성하는 Person 객체가 아닌 window 입니다. 따라서 window의 name, gender, age 속성을 변경하고 있습니다. 즉 우리가 원하는 결과랑 전혀 다른 결과가 나오게 되는 것이죠. 그렇다면 어떻게 해야할까요? 해결방법은 너무 쉽습니다. 그냥 개발자가 실수만 안하면 됩니다. 따라서 생성자 함수를 사용하는 개발자는 this의 값이 window 되지 않도록 생각하며 구현을 해야했습니다. 그런데 이러한 생각 조차 하지 않도록 new를 빼고 사용할 때 error가 발생하면 어떨까요? 그것이 바로 class 입니다.

class

class는 어떻게 사용할 수 있을까요? 이해하기 쉽도록 위에서 살펴본 코드들을 class로 변경해보겠습니다.

class Person {
  constructor(name, gender, age) {
    this.name = name;
    this.gender = gender;
    this.age = age;
  }
}

const person1 = new Person("홍길동", 0, 50);
const person2 = new Person("강짱구", 1, 30);

코드를 확인해보면 생성자 함수와 굉장히 유사합니다. 그냥 constructor에 생성자 함수에서 사용한 코드를 넣어두면 동일합니다. 그러나 class의 장점은 new keyword를 개발자가 실수로 빼먹고 작성했을 때 에러가 표시된다는 점입니다. 그리고 this는 무조건 새로 생성되는 객체(자시 자신)이기 때문에 고민할 필요가 없다는 것입니다. 또한 함수를 생성할 때도 많은 이점이 있습니다. 이전 Factory Pattern과 생성자 함수의 경우 먼저 확인해보겠습니다.

Factory Pattern

Factory Pattern은 아래처럼 사용할 수 있습니다.

function createPersonObject(name, gender, age) {
  return {
    name,
    gender,
    age,
    updateName(name) {
      this.name = name;
    },
    updateGender(gender) {
      this.gender = gender;
    },
    updateAge(age) {
      this.age = age;
    }
  };
}

return 할 때 updateName, updateGender, updateAge 가 추가된 것을 확인할 수 있습니다. 그럼 생성자 함수의 경우 어떻게 될까요?

생성자 함수

생성자 함수는 Factory Pattern 보다 더 복잡합니다. 아래 코드를 확인해보겠습니다.

function Person(name, gender, age) {
  this.name = name;
  this.gender = gender;
  this.age = age;
}

Person.prototype.updateName = function (name) {
  this.name = name;
};

Person.prototype.updateGender = function (gender) {
  this.gender = gender;
};

Person.prototype.updateAge = function (age) {
  this.age = age;
};

prototype을 추가하여서 Factory Pattern 보다 더 복잡해졌습니다. 그리고 복잡한 것 외에 또 단점이 있습니다. 코드를 순서대로 적지 않은 경우, 내가 updateName 함수를 구현하였는 지 아닌 지 헷갈릴 때가 있는데 이러한 경우 같은 함수를 2번 생성하는 불상사가 일어날 수 있습니다. 이런 것을 방지하기 위해 class를 사용하는 것입니다. 아래 class를 사용했을 때 얼마나 단순해지는 지 알아보겠습니다.

클래스 class

class를 사용하면 아래처럼 작성할 수 있습니다.

class Person {
  constructor(name, gender, age) {
    this.name = name;
    this.gender = gender;
    this.age = age;
  }

  updateName(name) {
    this.name = name;
  }

  updateGender(gender) {
    this.gender = gender;
  }

  updateAge(age) {
    this.age = age;
  }
}

class를 사용하는 경우 생성자 함수를 사용하는 것보다 더 직관적입니다. 그리고 함수도 class 내에 모두 구현을 해야하기 때문에 실수로 여러 개 구현하는 문제가 발생할 가능성이 훨씬 줄어듭니다.

◆ 간단정리

객체를 생성할 땐, 여러 방법이 있을 수 있습니다. 무엇이 꼭 정답이다 라는 것이 아니라 다양한 방법을 알고 있으면 상황에 맞게 사용할 수 있으니 많이 아는 것이 좋은 것 같습니다. 이후 시간이 나면 Factory Patternclass에 대해 조금 더 자세히 알아보도록 하겠습니다.

마지막

해당 내용은 틀릴 수도 있다는 것을 감안하여 봐주세요. 틀린 내용 및 오탈자 수정 요청 환영입니다.

반응형