프로그래밍풀스택 개발자

TypeScript의 비공개 필드(프라이빗 필드) 메커니즘은 어떻게 작동하나요? private 수정자와 # 기호를 사용하는 비공개 필드는 어떤 차이가 있으며, 적용의 특징과 제한은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

질문 배경

TypeScript에서 비공개 필드는 처음에 private 수정자를 통해 도입되었고, ECMAScript 2021부터는 JavaScript에서 # 기호를 통해 진정한 비공개 필드가 지원됩니다. 주요 목표는 데이터 캡슐화로, 클래스의 내부 세부 정보를 외부에서 접근하지 못하도록 보호하는 것입니다.

문제점

TypeScript의 private 수정자는 컴파일 단계에서만 비공개성을 보장하지만, 컴파일된 JavaScript에서는 이러한 필드가 객체의 속성에 직접 접근하여 여전히 접근 가능할 수 있습니다. 이는 객체의 상태가 의도치 않게 변경되는 결과를 초래할 수 있습니다. ES 비공개 필드(#)는 클래스 외부에서는 JS 런타임 수준에서도 완전히 접근할 수 없으며, 이는 데이터의 진정한 보호를 보장합니다.

해결책

TypeScript는 두 가지 접근 방식을 모두 지원합니다. 둘 중에서 선택할 때는 필요한 보호 수준과 JS 버전과의 호환성 제한을 고려하십시오.

코드 예시:

class Example { private hidden: number; #trulyHidden: string; constructor() { this.hidden = 42; this.#trulyHidden = 'secret'; } getHidden() { return this.hidden; } getTrulyHidden() { return this.#trulyHidden; } } const x = new Example(); // x.hidden — TS에서는 오류, 그러나 JS에서는 x['hidden']을 통해 동작할 수 있음 // x.#trulyHidden — JS에서도 문법 오류

주요 특징:

  • private는 TypeScript의 컴파일 단계에서만 비공개성을 보장함
  • #field는 JavaScript 실행 단계에서 진정한 비공개성을 제공함
  • #를 사용하는 것은 최신 JS 지원이 필요함 (ES2021+)

함정 질문.

TypeScript 클래스의 private 필드에 JS에서 직접 접근할 수 있나요?

네, 컴파일 단계에서만 비공개성이 구현되므로 가능합니다. 원래 JS에서는 해당 필드가 객체의 일반적인 속성이 됩니다. 예:

class A { private x = 1; } const a = new A(); console.log((a as any)["x"]); // 1

인터페이스나 type을 사용해 # 비공개 필드를 설명할 수 있나요?

아니요, #private 필드는 클래스의 구현의 일부일 뿐, 인터페이스나 타입에서 설명될 수 없으며 클래스 외부에서 사용할 수 없습니다. 인터페이스는 공개 멤버만 설명합니다.

#로 선언된 비공개 필드를 상속할 수 있나요?

아니요, 이러한 필드는 상속된 클래스에서도 전혀 접근할 수 없습니다. 오직 해당 클래스만이 접근할 수 있습니다:

class Parent { #foo = 123; } class Child extends Parent { // this.#foo = 444; // 오류 }

일반적인 오류 및 안티 패턴

  • 중요한 데이터를 보호하기 위해 private를 사용하는 것은 직접 접근 시 취약점으로 이어질 수 있음
  • 타입 수준과 런타임 수준의 비공개성 혼동
  • 이전 버전의 JS에서 #fields를 사용하려고 시도

실생활 예시

부정적인 케이스

비밀번호를 저장하는 프로젝트에서 User 클래스에 private password 필드가 사용되었습니다. 개발자 중 한 명이 디버깅을 위해 우연히 user['password']를 통해 접근하게 되고, 필드가 외부 모듈에 의해 변경됩니다.

장점:

  • TypeScript와의 간단한 통합

단점:

  • JS 런타임에서 실제 보호 없음
  • 비공식적으로 비공개성을 쉽게 회피할 수 있음

긍정적인 케이스

개발자가 ES 비공식 필드 #password를 사용하게 되었습니다. 이제 인덱싱이나 상속된 클래스에서 필드에 접근하려는 시도가 실패하며, 외부 라이브러리와 도구를 사용하더라도 데이터 보안이 확보되었습니다.

장점:

  • 진정한 비공식성
  • 민감한 속성에 대한 신뢰할 수 있는 보호

단점:

  • 최신 JS 지원 필요 (ES5와 호환되지 않음)
  • 비공식 필드는 인터페이스에서 보이지 않고, 상속에서 재정의할 수 없음