private class field를 사용하는 이유는?

kkojae·2022년 3월 7일
0
post-thumbnail

해당 리뷰는 우아한테크코스 Level1 자동차 경주 게임 미션 STEP2의 피드백 중 일부이다.


public 필드는 클래스 내부, 자식 클래스 내부, 클래스 인스턴스를 통한 접근이 모두 허용된다.
private 필드는 클래스 내부에서만 접근이 가능하다.
즉, private 필드는 클래스 외부에서 직접 접근할 수 있는 방법은 없다. 다만 접근자 프로퍼티를 통해 간접적으로 접근하는 방법이 유효하다. 따라서 데이터를 조금 더 안전하게 보관할 수 있다.


은닉화를 약속하는 과거의 유산


접근 제어자를 지원하지 않는 과거 JS에서는 언더바(_)를 붙이는 컨벤션으로 private 변수, 메서드를 구분했었다.

2008년에 더글라스 크락포드가 제안했지만, 최근에는 지양하자는 이야기가 많다. 이유가 무엇인지 알아보자!

나이스 샵(#)

  • Stage-3 단계에 있는 스펙으로 특별한 결격 사유가 없는 한 표준 스펙이 될 것이다. 물론 변경되거나 개선될 여지는 있다.
  • private과 같은 키워드를 사용하지 않는다. 대신 # 즉 샵 프리픽스를 사용한다. 키워드가 아니라 프리픽스다. 속성 명 앞에 #이 붙으면 Private 필드로 동작한다.
  • public과 다른 점은 클래스의 필드 선언을 통해서만 만들 수 있다. 즉 동적으로 객체에 private 필드를 추가할 수 없다.
  • 메서드에는 제한적이다. 메서드 선언으로 사용할 수 없다. private 메서드를 만들려면 함수 표현식으로 정의해야 한다. (현재로서의 의미다.. 추후 스펙이 업데이트될 수도 있다.)
  • Computed Proprety Name을 사용할 수 없다. #foo 자체만 식별자로 허용되고 #[fooName] 이건 문법 오류다.
  • 모든 Private 필드는 소속된 클래스에 고유한 스코프를 갖는다.
  • 자바스크립트에서도 꼼수가 아닌 정상적인 방법으로 클래스에 private 속성을 만들 수 있게 되었다. TC39의 스펙 문서를 토대로 간단하게 요약하면 아래와 같다.

간단하게 # 프리픽스를 이용해서 Human 클래스에 #age 속성을 만들고 외부에서 접근해보자.

  class Human {
    #age = 10;
  }

  const person = new Human();

  console.log(person.#age); // Error : Property '#age' is not accessible outsied class 'Human' because it has a private identifier

#은 키워드가 아니라 프리픽스다. # 없이는 해당 클래스 내부에서도 접근할 수 없다.

  class Human {
    #age = 10;

    getAge() {
      return this.age; // Error : Property 'age' does not exist on type 'Human'. Did you mean '#age'?
    }
  }

정상적으로 private 속성을 클래스에서 정의하고 사용해보자.

  class Human {
    #age = 10;

    getAge() {
      return this.#age;
    }
  }

  const person = new Human();
  console.log(person.getAge()); // 10

외부의 getAge()라는 getter를 노출해 #age 값에 접근할 수 있게 했다.

  class Human {
    #age = 10;

    getAge() {
      return this.#age;
    }
  }

  class Person extends Human {
    #age = 20;

    getFakeAge() {
      return this.#age;
    }
  }

  const p = new Person();
  console.log(p.getAge()); // 10
  console.log([.getFakeAge()]); // 20

자바스크립트의 private 속성은 독특한 특징이 있다.
"모든 Private 필드는 소속된 클래스에 고유한 스코프를 갖는다."
#age 즉, private 속성은 그동안 우리가 알고 있던 this의 그 컨텍스트와는 다른 방식으로 저장된다. 기존처럼 인스턴스 별로 독립적인 공간을 갖지만, 추가로 클래스 별로 독립적인 공간을 갖는 것이다.
쉽게 말하면 Human 클래스 스코프의 #age와 Person 클래스 스코프의 #age는 다르다는 것이다. 그러므로 Human 클래스에 속한 getAge()가 실행될 때는 Human의 #age에 접근하고 Person의 getFakeAge()가 실행될 때는 Person의 #age에 접근하는 것이다.

바로 그게 "모든 Private 필드는 소속된 클래스에 고유한 스코프를 갖는다."라는 문장의 의미다.



참고 링크 : 은닉을 향한 자바스크립트의 여정

0개의 댓글