완벽한 캡슐화와 메소드 캡슐화하기

MANG·2024년 6월 24일
post-thumbnail

자바스크립트에서는 객체 지향 프로그래밍에서 중요한 개념인 캡슐화를 클로저를 이용해 구현할 수 있습니다. 이번 글에서는 캡슐화의 개념과 이를 적용하는 방법을 알아보겠습니다.

1. 완벽한 캡슐화하는 법

이전에는 다음과 같은 코드로 캡슐화를 배웠습니다:

class User {
  constructor(email, birthdate) {
    this.email = email;
    this.birthdate = birthdate;
  }

  buy(item) {
    console.log(`${this.email} buys ${item.name}`);
  }

  get email() {
    return this._email;
  }

  set email(address) {
    if (address.includes('@')) {
      this._email = address;
    } else {
      throw new Error('invalid email address');
    }
  }
}

const user1 = new User('chris123@google.com', '1992-03-21');
user1.email = 'newChris123@google.com';
console.log(user1.email);

이 코드에서 _email 프로퍼티를 직접 접근하지 않고, email이라는 getter/setter 메소드로 접근하도록 하였습니다. 하지만 _email 프로퍼티에 직접 접근할 수 있기 때문에 완벽한 캡슐화가 되지 않았습니다:

console.log(user1._email);
user1._email = 'chris robert';

자바스크립트에는 private 키워드가 없기 때문에 클로저(closure)를 이용해 완벽한 캡슐화를 할 수 있습니다. 아래는 클로저를 사용한 예시입니다:

function createUser(email, birthdate) {
  let _email = email;

  const user = {
    birthdate,

    get email() {
      return _email;
    },

    set email(address) {
      if (address.includes('@')) {
        _email = address;
      } else {
        throw new Error('invalid email address');
      }
    },
  };

  return user;
}

const user1 = createUser('chris123@google.com', '19920321');
console.log(user1.email); // 'chris123@google.com'
console.log(user1._email); // undefined

클로저를 이용하면 _email 변수에 직접 접근할 수 없으며, getter와 setter를 통해서만 접근할 수 있습니다.

2. 메소드도 캡슐화할 수 있어요

캡슐화는 프로퍼티뿐만 아니라 메소드에도 적용할 수 있습니다. 다음은 메소드를 캡슐화한 예시입니다:

function createUser(email, birthdate) {
  let _email = email;
  let _point = 0;

  function increasePoint() {
    _point += 1;
  }

  const user = {
    birthdate,

    get email() {
      return _email;
    },

    get point() {
      return _point;
    },

    buy(item) {
      console.log(`${this.email} buys ${item.name}`);
      increasePoint();
    },
  };

  return user;
}

const item = {
  name: '스웨터',
  price: 30000,
};

const user1 = createUser('chris123@google.com', '19920321');
user1.buy(item);
user1.buy(item);
user1.buy(item);
console.log(user1.point); // 3
user1.increasePoint(); // 에러: user1.increasePoint is not a function

위 코드에서 increasePoint 함수는 클로저로 캡슐화되어 user1 객체에서는 직접 접근할 수 없습니다. buy 메소드에서만 호출이 가능합니다.

결론

자바스크립트에서는 클로저를 사용하여 프로퍼티와 메소드를 완벽하게 캡슐화할 수 있습니다. 캡슐화를 통해 객체의 내부 상태를 보호하고, 외부에서 직접 접근할 수 없도록 할 수 있습니다. 이는 객체 지향 프로그래밍의 중요한 개념으로, 코드의 안정성과 유지보수성을 높이는 데 큰 도움이 됩니다.


실습

JavaScript에서 객체 캡슐화하기

이번 글에서는 자바스크립트에서 객체를 캡슐화하는 방법에 대해 알아보겠습니다. 특히 BankAccount 클래스를 예시로 들어서 프로퍼티와 메소드를 안전하게 보호하는 방법을 살펴보겠습니다.

실습 설명

현재 BankAccount 클래스는 _balance라는 프로퍼티를 통해 계좌의 잔액을 관리합니다. 이 프로퍼티에 직접 접근해서 값을 수정하는 것은 매우 위험하기 때문에, 이를 캡슐화하려고 합니다.

이미 balance라는 getter 함수는 정의되어 있으며, 이제 balance라는 setter 함수도 정의해 보겠습니다. 이 setter 함수는 다음과 같은 기능을 합니다:
1. 파라미터로 전달된 금액이 0 이상일 때만 _balance 프로퍼티의 값으로 설정한다.
2. 음수일 때 'You cannot set negative number for balance'라는 문장을 출력한다.

코드 구현

먼저, BankAccount 클래스에 setter 메소드를 추가하여 캡슐화를 구현해보겠습니다.

class BankAccount {
  constructor(name, money) {
    this.holder = name;
    this._balance = money;
  }

  get balance() {
    return this._balance;
  }

  set balance(money) {
    if (money >= 0) {
      this._balance = money;
    } else {
      console.log('You cannot set negative number for balance');
    }
  }

  deposit(money) {
    this.balance += money;
  }

  withdraw(money) {
    if (this.balance - money < 0) {
      console.log('Insufficient balance');
    } else {
      this.balance -= money;
    }
  }

  transfer(money, anotherAccount) {
    const account = anotherAccount;
    if (this.balance - money < 0) {
      console.log('Insufficient balance');
    } else {
      this.balance -= money;
      account.balance += money;
    }
  }
}

const account1 = new BankAccount('Michael', 10000);
account1.balance = 20000;
account1.balance = -5000;

이렇게 하면 _balance 프로퍼티에 직접 접근하지 못하고, setter 메소드를 통해서만 접근할 수 있게 됩니다.

테스트 코드

위 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다:

You cannot set negative number for balance

이제 _balance에 직접 접근하는 것을 막기 위해 클로저를 이용해 완벽한 캡슐화를 구현해 보겠습니다.

클로저를 이용한 완벽한 캡슐화

클로저를 사용하면 _balance 변수를 외부에서 직접 접근하지 못하도록 완벽하게 보호할 수 있습니다. 이를 위해 createBankAccount라는 팩토리 함수를 사용합니다.

function createBankAccount(name, money) {
  const holder = name;
  let _balance = money;

  const account = {
    get balance() {
      return _balance;
    },

    set balance(money) {
      if (money >= 0) {
        _balance = money;
      } else {
        console.log('You cannot set negative number for balance');
      }
    },

    deposit(money) {
      this.balance += money;
    },

    withdraw(money) {
      if (this.balance - money < 0) {
        console.log('Insufficient balance');
      } else {
        this.balance -= money;
      }
    },

    transfer(money, anotherAccount) {
      const account = anotherAccount;
      if (this.balance - money < 0) {
        console.log('Insufficient balance');
      } else {
        this.balance -= money;
        account.balance += money;
      }
    },
  };
  return account;
}

const account1 = createBankAccount('Michael', 10000);
console.log(account1._balance); // undefined 출력
account1.balance = 20000;
account1.balance = -5000; // 'You cannot set negative number for balance' 출력

결론

자바스크립트에서는 클로저를 사용하여 프로퍼티와 메소드를 완벽하게 캡슐화할 수 있습니다. 이렇게 하면 객체의 내부 상태를 외부에서 직접 접근할 수 없게 보호할 수 있으며, 이는 보다 안정적이고 유지보수하기 쉬운 코드를 작성하는 데 큰 도움이 됩니다. 캡슐화는 객체 지향 프로그래밍의 중요한 개념으로, 이를 이해하고 적절히 활용하는 것이 중요합니다.

profile
대학생

0개의 댓글