자바스크립트에서 Private과 친해지기.
동기
- 우아한테크코스 Level 1, 자동차 경주 게임 1단계 과정 중 클래스 내부에서만 사용하는 메서드와 변수를 구분하기 위해 언더바를 활용하여 비공개 멤버를 구분.
- 이후 피드백을 통해 "언더바를 활용한 비공개 멤버 구분을 지양하라"라는 내용 확인.
과정
1. 왜 사용하면 안될까?
-
IDE가 발달하기 전에 쓰던 머나먼 옛날(2008년)의 "약속"이고, 현재에 들어서는 IDE의 발달로 소스 트리를 간편하게 볼 수 있고 VSCode의 다양한 확장 프로그램들으로 구분이 어렵지 않다.
-
개발자들의 "약속"일뿐이지, 실제로 은닉이 되지 않고 외부에서 손쉽게 접근할 수 있다. 접근이 가능하다면 추후 유지/보수 과정에서 분명 접근하는 케이스가 생길 것이다!
-
시간이 지나서 아래와 같은 더 나은 방법이 등장하고 있다.
2. 그렇다면 대체제는?
1. 함수에서는 클로저의 특징 활용
const counter = () => {
let privateNumber = 0;
const changeBy = (value) => {
privateNumber += value;
}
return {
increment: () => {
changeBy(1);
},
decrement: () => {
changeBy(-1);
},
value: () => privateNumber
}
}
console.log(counter.value()); // 0
counter.increment();
console.log(counter.value()); // 1
counter.decrement();
console.log(counter.value()); // 0
console.log(counter.privateNumber); // undefined
1. 왜 사용하면 안될까?
-
IDE가 발달하기 전에 쓰던 머나먼 옛날(2008년)의 "약속"이고, 현재에 들어서는 IDE의 발달로 소스 트리를 간편하게 볼 수 있고 VSCode의 다양한 확장 프로그램들으로 구분이 어렵지 않다.
-
개발자들의 "약속"일뿐이지, 실제로 은닉이 되지 않고 외부에서 손쉽게 접근할 수 있다. 접근이 가능하다면 추후 유지/보수 과정에서 분명 접근하는 케이스가 생길 것이다!
-
시간이 지나서 아래와 같은 더 나은 방법이 등장하고 있다.
2. 그렇다면 대체제는?
1. 함수에서는 클로저의 특징 활용
const counter = () => {
let privateNumber = 0;
const changeBy = (value) => {
privateNumber += value;
}
return {
increment: () => {
changeBy(1);
},
decrement: () => {
changeBy(-1);
},
value: () => privateNumber
}
}
console.log(counter.value()); // 0
counter.increment();
console.log(counter.value()); // 1
counter.decrement();
console.log(counter.value()); // 0
console.log(counter.privateNumber); // undefined
문제 탐색
- 해당 객체를 여러개 만든다면, 생성될 때마다 서로 다른 클로저 함수가 만들어져 메모리 관리에 좋지 않다.
2. ES2015의 Symbol()을 활용하여 이름을 은닉하라
const privateNumber = Symbol('여러분은 지금 변수의 이름을 비공개 하여 접근을 막는 과정을 보고 계십니다.');
class Counter {
constructor() {
this[privateNumber] = 0;
}
increment() {
this[privateNumber] += 1;
}
decrement() {
this[privateNumber] -= 1;
}
value() {
return this[privateNumber];
}
}
const counter = new Counter();
counter.increment()
console.log(counter.value()); // 1
counter.decrement()
console.log(counter.value()); // 0
문제 탐색
- ES6의 import/export 방식을 통해서만 비공개 멤버를 사용할 수 있다. 다른 파일에서는 Symbol으로 선언된 privateNumber 변수를 export 하지 않는 한 접근할 수 없지만, 반대로 내부 파일에 다른 코드가 있을 시 접근이 가능해진다.
- Object.getOwnPropertySymbols(Object) 방식으로 심볼의 키를 얻을 수 있기에 실제로 접근이 완전히 불가능한 것은 아니다.
console.log(Object.getOwnPropertySymbols(counter)); // Array [ Symbol("여러분은 지금 변수의 이름을 비공개 하여 접근을 막는 과정을 보고 계십니다.") ]
3. 기다리고, 기다린 "#"
- 현재 TC39 Stage 3 상태인, 클래스에서 변수 또는 메서드에 #을 Prefix로 추가해 비공개 멤버를 선언할 수 있게 되었다.
class counter {
#privateNumber = 0;
increment() {
this.#privateNumber += 1;
}
decrement() {
this.#privateNumber -= 1;
}
value() {
return this.#privateNumber;
}
}
const counter = new Counter();
counter.increment()
console.log(counter.value()); // 1
console.log(counter.#privateNumber); // undefined
counter.decrement()
console.log(counter.value()); // 0
3-2. 하지만! ESLint에서는 계속 문법 오류가 뜬다? EsLint에 # 붙이기.
- 아쉽게도 ESLint는 TC39 후보 상태(스테이지 3)의 기능은 지원하지 않는다.
TC39의 스테이지 3 후보 단계는 완성 단계에 가깝고, 구현 주체나 사용자들로부터 피드백을 좀 더 받아보는 일만이 남은 상태다.
그렇기에 표준에 포함되어도, 그 전에 심각한 문제가 발견되지 않는 이상 문법, 동작 방식은 변경이 없는 편이다. - 하지만 아래와 같이 패키지를 설치하고, ESLint 설정과 바벨 설정을 수정하면 ESLint에서도 TC39 상태의 기능들을 허용할 수 있다.
패키지 설치
npm i @babel/core @babel/eslint-parser @babel/preset-env -D
ESLint 설정 파일(.eslintrc)에서 parser 옵션 설정
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": "eslint:recommended",
**"parser": "@babel/eslint-parser",**
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {
}
}
babel 구성 파일(.babelrc) 설정
{
"presets": [
["@babel/preset-env",
{
"shippedProposals": true
}]
]
}
결과
- 자동차 경주 게임 2단계에서는 TC39 Stage 3의 Private class(#)를 사용하여 비공개 메서드와 변수를 구현을 진행.
- 3-2 단계를 진행하여 ESLint를 활성화하여도 문법 오류가 더 이상 발생되지 않음.
- "#"을 활용한 Private 처리는 최신 브라우저들 대부분을 지원하지만, 브라우저의 호환성을 많이 고려하여야 하는 환경이라면 클로저 사용을 권장.
참조
- 은닉을 향한 자바스크립트의 여정
- MDN - Private class fields
02.18 - 오류 정정
MDN 한국어 문서에서는 "#"은 ES2019부터 도입되어있다! 라고 표기되어있는데, 확인 결과 아직 TC39 Stage 3 상태의 기능이다.
영문 문서에는 해당 내용이 표기되지 않는다!
- 자바스크립트의 Private
- EsLint에서 Private class fields 활성화 (영문)
- 자바스크립트 언어의 표준인 ECMAScript와 TC39에 대해 소개합니다.
틀린 내용, 피드백이 있으시다면 댓글 남겨주시면 감사하겠습니다! 🙇♂️
Author And Source
이 문제에 관하여(자바스크립트에서 Private과 친해지기.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@compy/자바스크립트에서-Private과-친해지기
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
- 은닉을 향한 자바스크립트의 여정
- MDN - Private class fields
02.18 - 오류 정정
MDN 한국어 문서에서는 "#"은 ES2019부터 도입되어있다! 라고 표기되어있는데, 확인 결과 아직 TC39 Stage 3 상태의 기능이다.
영문 문서에는 해당 내용이 표기되지 않는다! - 자바스크립트의 Private
- EsLint에서 Private class fields 활성화 (영문)
- 자바스크립트 언어의 표준인 ECMAScript와 TC39에 대해 소개합니다.
틀린 내용, 피드백이 있으시다면 댓글 남겨주시면 감사하겠습니다! 🙇♂️
Author And Source
이 문제에 관하여(자바스크립트에서 Private과 친해지기.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@compy/자바스크립트에서-Private과-친해지기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)