캡슐화

Frontend SELF KO
레벨 40 , 레슨 2
사용 가능

9.1 주요 개념

캡슐화는 객체 지향 프로그래밍(OOP)의 주요 개념 중 하나로, 객체의 내부 구현 세부 사항을 숨기고 이러한 세부 사항에 접근할 수 있는 철저히 정의된 인터페이스를 제공하는 것을 말해. 이로 인해 보안이 강화되고 코드 관리가 쉬워져.

캡슐화의 장점:

  1. 데이터 은닉: 캡슐화는 내부 구현 세부 사항을 숨기고 필요한 메소드와 속성에만 접근할 수 있도록 해줘. 이는 객체의 잘못된 사용을 방지하고 코드의 보안을 향상시켜줘.
  2. 접근 제어: 캡슐화는 데이터와 메소드에 대한 접근을 제어할 수 있게 해주고, 특정 메소드를 통해서만 객체의 내부 상태를 변경할 수 있게 해줘.
  3. 유지보수성: 캡슐화는 코드의 유지보수성을 높여주는데, 구현 변경이 클래스의 외부 인터페이스에 영향을 미치지 않도록 해줘. 덕분에 클래스를 사용하는 코드를 변경하지 않고도 구현을 수정할 수 있어.
  4. 테스트 용이성: 캡슐화는 객체의 내부 구현을 격리시켜주는데, 이로 인해 모듈 테스트가 쉬워지고 부작용 발생 가능성이 줄어들어.

JavaScript에서는 메소드와 속성을 사용하여 캡슐화를 구현하고, ES2022부터는 private 필드와 메소드도 사용 가능해졌어.

9.2 클로저를 통한 캡슐화

ES2022에서 private 필드가 도입되기 전에는, JavaScript에서는 주로 클로저를 사용하여 캡슐화를 달성했어.

예시:

  • 변수 count는 함수 createCounter 내부에서만 접근 가능하고 외부에서는 접근이 불가능해
  • 메소드 increment, decrement, getCount는 private 변수 count와 상호작용할 수 있어
JavaScript
    
      function createCounter() {
        let count = 0; // private 변수

        return {
          increment() {
            count++;
            console.log(count);
          },
          decrement() {
            count--;
            console.log(count);
          },
          getCount() {
            return count;
          }
        };
      }

      const counter = createCounter();
      counter.increment(); // 1
      counter.increment(); // 2
      console.log(counter.getCount()); // 2
      counter.decrement(); // 1
    
  

9.3 ES2022의 프라이빗 필드

ES2022에서는 # 기호를 사용하여 private 필드와 메소드가 도입되었어. Private 필드와 메소드는 클래스 외부에서 접근하거나 변경할 수 없어.

예시:

  • Private 필드 #name#age# 기호를 사용하여 선언되어 있어
  • 메소드 getName, getAge, setName, setAge는 private 필드와 상호작용할 수 있어
  • 클래스 외부에서 private 필드에 접근하려고 하면 오류가 발생해
JavaScript
    
      class Person {
        #name; // private 필드
        #age; // private 필드

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

        getName() {
          return this.#name;
        }

        getAge() {
          return this.#age;
        }

        setName(name) {
          this.#name = name;
        }

        setAge(age) {
          if (age > 0) {
            this.#age = age;
          }
        }
      }

      const person = new Person('Alice', 30);
      console.log(person.getName()); // "Alice"
      console.log(person.getAge()); // 30
      person.setName('Bob');
      person.setAge(25);
      console.log(person.getName()); // "Bob"
      console.log(person.getAge()); // 25
      
      console.log(person.#name); // 오류: private 필드에 접근 불가능
    
  

9.4 프라이빗 메소드

프라이빗 메소드는 # 기호를 사용하여 선언될 수 있고 클래스 외부에서 접근할 수 없어.

예시:

  • 프라이빗 필드 #balance와 프라이빗 메소드 #logTransaction는 객체 BankAccount의 상태를 관리하는 데 사용돼
  • 프라이빗 메소드 #logTransaction는 공개 메소드 depositwithdraw 내에서 호출되어 거래를 기록해
JavaScript
    
      class BankAccount {
        #balance;

        constructor(initialBalance) {
          this.#balance = initialBalance;
        }

        deposit(amount) {
          if (amount > 0) {
            this.#balance += amount;
            this.#logTransaction('deposit', amount);
          }
        }

        withdraw(amount) {
          if (amount > 0 && amount <= this.#balance) {
            this.#balance -= amount;
            this.#logTransaction('withdraw', amount);
          }
        }

        getBalance() {
          return this.#balance;
        }

        #logTransaction(type, amount) {
          console.log(`Transaction: ${type} ${amount}`);
        }
      }

      const account = new BankAccount(1000);
      account.deposit(500); // "Transaction: deposit 500"
      console.log(account.getBalance()); // 1500
      account.withdraw(200); // "Transaction: withdraw 200"
      console.log(account.getBalance()); // 1300
      
      account.#logTransaction('test', 100); // 오류: private 메소드에 접근 불가능
    
  
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION