본문으로 건너뛰기
yceffort
PostsSeriesTagsAbout🧪 Research
EN

Tweaks

theme
accent palette
film grain
minimal mode
BACK TO INDEX
◆ ESSAY
--min
--year
KOoriginal

mailMail icongithubtwitter
yceffort
•
© 2026
•
https://yceffort.kr
BACK TO INDEX
◆ ESSAY

자바스크립트의 private

avatar
yceffort
2020-05-08 · 4분
4min
2020year
KOoriginal
javascript

이 글은 은닉을 향한 자바스크립트의 여정을 요약한 글입니다.

History

자바스크립트에서는 객체에 private 한 속성을 만들 수가 없었다. 그래서 보통 자바스크립트 개발자는 private한 것이다 라는 약속으로 _ prefix를 붙여서 사용하고는 했었다.

function Hello() {
  this.publicProp = 'public'
  this._privateProp = 'private'
}

물론 자바스크립트 개발자들은 _의 존재로 해당 속성을 건들지 말아야겠다는 것을 암묵적으로 공유했지만, 어디까지나 암묵적인 것일 뿐, 실제로는 밖에서 얼마든지 접근 할 수 있다.

좀 더 이 문제를 자바스크립트스럽게 해결하기 위해서는, 클로저를 활용하면 된다.

function Hello() {
  this.publicProp = 'public'
  const privateProp = 'private'

  _doWithPrivateProp = () => {
    // do something
  }
}

비록 this와 const가 짬뽕이 되면서, 가독성이 떨어지긴 하지만, 효과적으로 데이터를 격리 시켰다. 위와 같은 방법을 사용해서 메소드도 숨길 수 있다.

function Hello() {
  const publicProp = 'public'
  const privateProp = 'private'

  _doWithPrivateProp = () => {
    // ...
  }

  const publicMethod = () => {
    _doWithPrivateProp()
    // ...
  }

  return {
    publicProp,
    publicMethod,
  }
}

Symbol을 사용해 볼 수도 있다.

const privateMethodName = Symbol()
const privatePropName = Symbol()

class Hello {
  [privatePropName] = 'private'
  publicProp = 'public';

  [privateMethodName]() {
    // ...
  }

  publicMethod() {
    this[privateMethodName](this[privatePropName])
  }
}

Symbol은 생성될 때 마다 고유의 값을 가지므로, 외부에서는 이를 export하지 않는 이상 접근할 수 없다.

# 의 등장

해당 제안 내용은 여기에서 자세히 확인할 수 있다.

class Hello {
  #message = 'hello'
}

const hello = new Hell()
hello.#message
Uncaught SyntaxError: Private field '#message' must be declared in an enclosing class

private 하기 때문에 접근 할 수 없다는 메시지가 뜬다.

여기에서 #은 prefix이기 때문에 꼭 접근시에 #을 써야 한다.

class Hello {
  #message = 'hello'

  getMessage() {
    return this.message // 안됨
  }
}

상속을 받는다 하더라도 접근이 되지 않는다.

class Hello {
  #message = 'hello'

  getMessage() {
    return this.#message
  }
}

class Hi extends Hello {
  getHiMessage() {
    return this.#message
  }
}

const hi = new Hi()
hi.getHelloMessage() // Uncaught SyntaxError: Private field '#message' must be declared in an enclosing clas

추가로 모든 private 필드는 클래스 별로 독립된 고유한 스코프를 갖는다.

class Hello {
  #message = 'hello'

  getMessage() {
    return this.#message
  }
}

class Hi extends Hello {
  #message = 'hi'

  getHiMessage() {
    return this.#message
  }
}

const hi = new Hi()
const hello = new Hello()
console.log(hello.getMessage()) // hello
console.log(hi.getHiMessage()) // hi

타입스크립트에서는?

https://www.typescriptlang.org/docs/handbook/classes.html#ecmascript-private-fields https://www.typescriptlang.org/docs/handbook/classes.html#understanding-typescripts-private

위에서 언급한 # 문법과 더불어 (3.8부터) private 키워드 도 지원한다.

https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#ecmascript-private-fields

여기에 좋은 내용이 정리되어 있다.

  • Private 필드는 #으로 시작된다.
  • 모든 private 필드는 속한 클래스에서 고유한 스코프를 가지고 있다.
  • #은 타입스크립트의 public private과 함게 사용할 수 없다.
  • Private 필드는 클래스 밖에서 접근하거나 알아챌 수 없다. (JS도 마찬가지)

관련 글

  • #turbopack#nextjs#bundler

    Next.js turbopack에서 싱글톤이 두 개가 됐다: scope hoisting 버그와 순환 import

    Next.js 16 turbopack 프로덕션 빌드에서 모듈 스코프 싱글톤이 런타임에 두 개가 됐다. 같은 동기 구간에서 조건 판정이 뒤집히고, 응답이 도착해도 타임아웃이 나는 증상을 번들 산출물로 추적한 기록. scope hoisting의 부분 병합, 순환 import, 이미 고쳐져 있던 upstream 버그, 그리고 뒤늦게 돌린 단일 변수 실험까지.

    2026-08-19·28분
  • #javascript#animation#web-animations-api

    number-flow를 구형 브라우저로 이식하기: 다섯 가지 결정과 두 가지 번복

    number-flow가 애니메이션을 켜는 최소 버전은 Chrome 125, Safari 17.2다. 이 하한을 Chrome 66과 WebKit 16.4까지 내리는 포크를 만들면서 내린 결정들과, 뒤집게 된 판단 두 가지, 그리고 자동 강등을 포기한 Safari 버그 조사의 기록.

    2026-08-11·44분
  • #nodejs#security#javascript

    Node.js vm 모듈의 함정: 샌드박스가 아닌 이유

    집필 중인 Node.js Deep Dive의 5.2장(vm 모듈의 함정) 일부를 미리 공개합니다.

    2026-02-27·25분
  • #nodejs#javascript

    Node.js Deep Dive (가제) 베타 리더를 모십니다.

    많관부22

    2026-02-19·5분

새 글을 놓치고 싶지 않으시다면 RSS로 구독해 주세요.

RSS 구독 →

yceffort — 프론트엔드 엔지니어입니다. 발표·기술 자문·기고 문의는 이곳에서 받고 있습니다.

← Back to the blogIssue on GitHub →