본문 바로가기
이론/Frontend

JavaScript의 위임 (Delegation of JavaScript)

by 유세지 2021. 11. 19.

이번 시간에는 자바스크립트의 위임 방식에 대해 알아보고자 합니다. 단, 여기에서 말하는 위임은 캡쳐링과 버블링을 포함하는 이벤트 위임(event delegation) 또는 전파(propaganation)가 아니라 지난 시간에 알아 본 프로토타입과 이어지는 작동 방식에서의 위임입니다.

 

 

클래스 vs 위임

추상화가 가능한 유사한 속성을 가진 객체들이 있다고 할때, 이를 앞에서 살펴봤던 클래스를 이용해 모델링 해보면 이런 모습이 됩니다.

 

class Person {
  name;
  age;

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

class Student extends Person {
  studentNumber;

  constructor(name, age, studentNumber) {
    super(name, age);
    this.studentNumber = studentNumber;
  }
}

class Teacher extends Person {
  subject;

  constructor(name, age, subject) {
    super(name, age);
    this.subject = subject;
  }
}

 

이 코드를 객체를 이용한 위임 방식으로 바꾸어봅시다. class extends 대신 Object.create()를 사용합니다.

 

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

Student = Object.create(Person);
Student.setStudentId = function(studentId) {
  this.studentId = studentId;
}
Student.getStudentId = function() {
  return this.studentId;
}

Teacher = Object.create(Person);
Teacher.setStudentId = function(subject) {
  this.subject = subject;
}
Teacher.getStudentId = function() {
  return this.subject;
}

 

 

 

이런식으로 위임을 이용해 객체와 객체를 연결한 스타일로 작성한 코드를 카일 심슨OLOO(Objects Linked to Other Objects)라고 부릅니다. 프로토타입을 이용한 이런 패턴은 자바스크립트의 근간을 이루는 방식이며 때때로 굉장히 강력한 힘을 발휘할 수 있기 때문에 잘 기억해두시면 좋겠습니다.

 

 

위임은 일방통행

위임을 흔히 연결한다고 표현하고 실제로도 그렇지만, 복수의 객체가 양방향으로 상호 위임을 하는 일은 자바스크립트에선 일어날 수 없습니다. 객체 A가 B에 연결된 상태에서, B를 A에 재연결시키려고 하면 에러가 발생하게 됩니다. 타겟 객체에 존재하지 않는 메서드나 프로퍼티를 참조하려고 하면 프로토타입 체인을 타고 해당 메서드나 프로퍼티를 찾아 나서는데, 이때 상호 위임이 되어있다면 사이클이 형성되어 영원히 빠져나오지 못하는 무한 루프에 갇히게 될 것입니다.


이를 방지하기 위해 자바스크립트 엔진 제작사는 상호 위임과 같은 양방향 참조를 금지하게 되었습니다. 확실한 레퍼런스가 있다면 사용할 수도 있었겠지만, 일일히 가드체크를 하는 것보다는 무한 순환 참조를 확인하여 사전에 방지하는게 성능적으로 이익이라고 판단한게 아닌가 싶습니다.

 

순환 값 오류

 

 

인트로스펙션

인스턴스를 통해 객체의 유형을 추론하는 것을 타입 인트로스펙션(Type Introspection)이라고 부릅니다. 자바스크립트에서도 instanceof 키워드를 통해 객체의 구조와 기능을 추론할 수 있습니다.

 

function a() {
  // some logics ...
}

let test = new a();

console.log(test instanceof a); // true

true

 

다만 instanceof 키워드로 얻은 결과는 클래스의 인스턴스라기 보다는, 단지 대상 객체와 위임 연결된 상태임을 나타냅니다. 객체와 클래스(객체) 사이의 관계를 조사하는게 아니라 객체와 prototype 사이의 관계를 알려주는 역할에 불과하죠.

 

자바스크립트의 특성 중 덕 타이핑(Duck Typing)이 있습니다. 오리처럼 생긴 동물이 오리처럼 운다면, 그것은 오리로 생각하겠다는 의미입니다. 코드적으로 풀어보면 instanceof 같은 키워드로 관계를 조사하는 대신에, 객체가 갖추고 있어야 할 일정한 조건을 만족하면 그것을 대상 객체처럼 사용하겠다는 뜻입니다. 확실히 덕 타이핑은 편리한 방법이지만 그만큼 잘못 사용될 위험도 가지고 있으니 조심해서 사용해야합니다.

 

대표적인 예로 프로미스(Promise)가 있습니다. then() 메서드를 가지고 있는 데너블(Thenable)한 객체라면 모두 프로미스로 간주하고 동작시키는 특성을 가지고 있습니다. 프로미스에 대해선 이후에 더 자세히 다루도록 하겠습니다.

 

 

 

정리

오늘은 자바스크립트의 위임에 대해서 알아보았습니다. 클래스 구조와 비교하여 어떤 형태를 갖는지, 자바스크립트의 근간을 이루는 방식이 어떻게 되어있는지 살펴보고 상황에 맞게 선택할 수 있게 되었습니다. 다음에는 콜백과 프로미스를 배우기 이전에, 간단히 비동기에 대해 공부해보겠습니다.

반응형

댓글