TypeScript의 private와 #

InnomDB·2022년 5월 20일
0

Nest

목록 보기
1/6

TS에서 private는 불완전한 private입니다.
그 이유를 살펴보면 ts의 private는 ts에서만 동작하기 때문입니다.
하지만 ts는 결국 js로 변환되고 변환된 js에서는 이제 더 이상 private속성은 없습니다.

js에서도 private를 유지하고 싶으시다면 #을 쓰세요

#은 내가 예상하지 못한 결과를 막아줄 수 있습니다.

Nest를 기준으로 설명코드를 작성하겠습니다.

ex)

class User {
 @Exclude()
  private _name: string;
  
  set name(name: string) {
  	this._name = name;
  }
  
  get name() {
  	return this._name;
  }
}

위의 코드를 역직렬화한다고 가정해보겠습니다.

const data = {
 name: 'user1' 
}

console.log(plainToInstance(User, data));

출력 결과는 어떻게 나올까요?

User { _name: user1 }

예상하신 결과가 잘 나오셨나요?
왜 이런 결과가 나왔을까요?
저는 처음에 이것이 버그인줄 알았습니다. 왜냐 @Excldue 데코레이터를 추가해주어 노출이 안되게 해주었는데 어째서 _name이 출력이 될까? 이것에 대한 이유를 찾았는데 그것은 바로 setter 때문이였습니다.

데코레이터들이 선언 되었을 때 그것은 metadata에 저장이 됩니다. class-transformer의 함수인
plainToInstance는 @Excldue 속성인 프로퍼티를 제외하여 _name를 Local this에 포함시키지 않았지만 값이 세팅될 때에 setter가 호출되며 _name에 값을 지정하게 되면서 Local this에 _name이 추가가 되어 결과적으로 _name이 출력되게 된것입니다.

이것이 어떻게 가능하냐!! private는 js에서는 private가 아니기 때문에 가능합니다.
반면 #을 이용한다면

class User {
 #name: string;
  
  set name(name: string) {
  	this.#name = name;
  }
  
  @Expose()
  get name() {
  	return this.#name;
  }
}
const data = {
 name: 'user1' 
}

console.log(plainToInstance(User, data));  // User { }

private속성이 js까지 잘 전달되었기 때문에 @Exclude() 데코레이터가 없더라도 출력이 되지 않습니다!

언제 # / private를 써야 할까에 대한 질문은 아래의 문서를 참고하시면 됩니다.
TypeScript

profile
이노오오옴

0개의 댓글