자바스크립트에서 작동 위임이란

Jin·2022년 3월 1일
0

Javascript

목록 보기
14/22

이 게시글은 기존의 클래스/상속 디자인 패턴에서 작동 위임 디자인 패턴으로 사고방식을 바꾸기 위함입니다.

자바스크립트 (이하 JS)의 무한한 가능성을 이끌어낼 가장 중요한 핵심 기능이자 실제적인 체계는 전적으로 '객체를 다른 객체와 연결하는 것'에서 비롯됩니다.

클래스 지향과 대비하여 객체를 다른 객체에 연결하는 코드 스타일을 OLOO (Objects Linked to Other Objects)라고 지칭하겠습니다. 이 코드 스타일에서 우리는 객체가 다른 객체에 작동을 위임하는 부분만 신경 쓰면 됩니다.

OLOO 스타일 코드의 특징은 다음과 같습니다.

  • 상탯값은 위임하는 쪽에 두고 위임받는 쪽에 두지 않는다.
  • 같은 명칭이 뒤섞이는 일이 될 수 있으면 피해야 한다.
  • 암시적 호출부에 따른 this 바인딩 규칙에 따라 위임하는 객체는 위임받은 객체의 기능을 제한없이 사용 가능하다.

작동 위임이란 찾으려는 프로퍼티/메서드 레퍼런스가 객체에 없으면 다른 객체로 수색 작업을 위임하는 것을 의미합니다. 이 디자인 패턴에서는 부모/자식 클래스, 상속, 다형성은 전혀 상관없고 객체들이 수평적으로 배열된 상태에서 링크가 체결되는 모습을 떠올리면 됩니다.

다만, 복수의 객체가 양방향으로 상호 위임을 하면 발생하는 사이클은 허용되지 않습니다.

이제 코드로 객체지향과 작동위임 스타일을 비교해보겠습니다.

function Foo(who) {
  this.me = who;
}

Foo.prototype.identify = function() {
  return `I am ${this.me}`;
}

function Bar(who) {
  Foo.call(this, who);
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.speak = function() {
  alert(`Hello, ${this.identify()}.`);
}

var b1 = new Bar('b1');
var b2 = new Bar('b2');

b1.speak();
b2.speak();

자식 클래스 Bar는 부모 클래스 Foo를 상속한 뒤 b1와 b2로 인스턴스화하였습니다.

다음은 정확히 같은 기능을 OLOO 스타일 코드로 구현한 코드입니다.

const Foo = {
  init: function init(who) {
    this.me = who;
  },
  identify: function identify() {
    return `I am ${this.me}`;
  }
}

const Bar = Object.create(Foo);
Bar.speak = function speak() {
  alert(`Hello, ${this.identify()}.`);
}

const b1 = Object.create(Bar);
b1.init('b1');
const b2 = Object.create(Bar);
b2.init('b2');

b1.speak();
b2.speak();

여기서 중요한 것은 잡다한 것들이 정리되고 단순해졌다는 사실입니다. 생성자, 프로토타입, new 호출을 하면서 클래스처럼 보이게 하려고 헷갈리는 장치들을 쓰지 않고 그냥 객체를 서로 연결해 주기만 하였습니다.

OLOO 관점에서는 Foo가 부모도, Bar가 자식도 아닙니다. Foo는 보통 객체로, 유틸리티 창고 역할을 맡는 것이고 Bar는 그냥 단독으로 존재하는 객체이면서 Foo와 위임 링크를 맺어졌을 뿐이므로 더 간단한 코드 아키텍처가 설계됩니다.

클래스 생성자로는 생성과 초기화를 한 번에 해야 하지만 OLOO 방식처럼 두 단계로 나누어 실행하면 더 유연해집니다.

생성 및 초기화 과정을 굳이 한 곳에 몰아넣고 실행하지 않아도 되니 OLOO는 관심사 분리의 원칙을 더 잘 반영한 패턴입니다.
클래스 인스턴스화나 부모/자식 관계를 억지로 맺을 필요가 없습니다. 또한, 다형성이라는 명목으로 메서드를 똑같은 이름으로 포함하지 않아도 되니 기능을 더 쉽게 이해할 수 있습니다.

위의 코드에서 저는 익명 함수가 아니라 함수에 이름을 지어서 선언하였습니다.

굳이 그렇게 한 이유는 아래의 이유들 때문입니다.

  • 호출 스택 추적을 통해 디버깅을 쉽게 하기 위해서
  • 재귀, 이벤트 바인딩 등에서 자기 참조를 쉽게 하기 위해서
  • 코드 가독성을 위해서

작동 위임 패턴은 객체를 부모/자식 클래스 관계가 아닌 동등한 입장에서 서로 위임하는 형태로 연결되어 있습니다. 객체만으로 구성된 코드를 구성한다면 사용 구문도 단순해질뿐더러 실제로 코드 아키텍처 또한 더 간단하게 가져갈 수 있습니다.

profile
배워서 공유하기

0개의 댓글