Language/Javascript (Typescript)

[Typescript] Typescript는 private을 js로 어떻게 구현할까? feat. 클로저

ooeunz 2020. 4. 26. 00:45
반응형

저는 요즘 Typescript의 매력에 빠져있습니다. 3월 11일에 페이스북에 타입스크립트 왜 쓰는지 모르겠다고 독설을 늘여놓았다가 1달 만에 우디르급 태세 전환을 했거든요ㅋㅋㅋ 밑에 이미지에서도 TMI로 구구절절 언급하고 있지만, JS의 가벼움을 그대로 가지면서도 트랜스파일링 시점에 에러를 잡아내 주는 이 녀석은 정말 물건입니다. bbb

 

 

그런데 문득 친구가 오늘 JS로 클로저 공부를 했다는 이야기를 듣고 뜻밖의 궁금증이 떠올랐습니다. 

TS는 private을 어떻게 구현할까?

 

처음 JS 책에서 클로저에 대해 공부할 때가 생각납니다. 대체 이놈은 왜 있는거지? 라는 생각이 들었고, 시간이 지남에 따라 private을 따로 지원하지 않는 javascript에서 정보은닉을 구현하기 위해 사용하지 않을까?라는 생각을 하게 되었습니다. 하지만 그러기엔 다른 언어에 비해서 코드도 지저분해지고 필자의 개발 실력이 부족했던 탓인지 딱히 JS로 개발하면서 클로저의 필요성을 느끼지 못했던 게 사실입니다.

 

여기서 클로저에 대해 잠깐 설명하자면 반환된 내부 함수가 자신이 선언되었을 때의 환경인 스코프를 기억하여 자신이 선언되었을 때의 환경 밖에서 호출되어도 그 환경에 접근할 수 있는 함수를 뜻합니다. 즉 쉽게 말하면 두 개의 함수를 이용해서 마치 private 필드를 갖고 있는 객체처럼 사용할 수 있도록 정보 은닉성을 활용할 수 있습니다.

 

그런데 Typescript에서는 알다시피 private을 지원합니다. 그렇다면 타입스크립트는 정말 클로저를 이용해 정보은닉을 구현할까?

궁금해서 바로 실험해봤습니다.

 

 

※ ES6 문법엔 class가 추가되어서 좀 더 깔끔한 코드로 트랜스파일링 할 수 있지만,

prototype에 값이 추가된다는 것을 보여드리기 위해 ES5로 트랜스파일링 했습니다.

(좌) Typescript / (우) Javascript Transpile

왼쪽은 타입스크립트, 그리고 오른쪽은 트랜스파일링된 자바스크립트 코드입니다. 저는 이 코드를 보는 순간부터 너무 흥미로워서 흥분에 도가니에 빠져버렸습니다. (ㅋㅋㅋ)

 

이 코드에서 유심히 보아야 할 부분은 바로 private memberId: string 입니다. 우리는 분명 ts 코드에 private으로 memberId라는 필드를 선언했습니다. 하지만... js 코드에선 어느 부분을 살펴봐도 memberId라는 undefined 값을 지는 프로퍼티가 존재하지 않습니다.

 

다만 getter, setter 함수가 선언될 때 prototype에 추가된 함수를 통해 프로퍼티를 추가하는 코드를 확인할 수 있습니다.

즉 어떻게 보면 ts에서의 private으로 선언된 memberId 필드는 개발자에게 심리적 안정감(?)을 주는 눈속임 코드인 셈이지요ㅋㅋㅋ.

 

 

※ prototype이 무엇인지 모른다면 아래 url을 참고하시기 바랍니다.

 

[JavaScript] Tutorial(2): 자바스크립트 Object(객체)

※ 이 포스팅은 스터디 강의 자료로 사용되었습니다. 자바스크립트는 다른 언어와 다른 객체의 특징이 있습니다. 흔히 이러한 특성 때문에 자바스크립트를 장난감 같다고 이야기 하기도 합니다. 처음 프로그래밍..

ooeunz.tistory.com

 

하지만 저를 정말 깜짝 놀라게 했던 부분은 js코드의 4번과 7번 라인. 그러니까 Member라는 즉시 실행 익명 함수에 (javascript에서 class를 구현한 방법) 프로퍼티로 값을 추가했다는 겁니다. 프로퍼티에!!! 즉, 누가 봐도 private은 구현되어 있지 않다고요!!!!!

 

아까 위에서 언급했듯이 클로저를 사용하면 코드는 좀 복잡해지지만 정보은닉을 구현할 수 있다고 했습니다. 그래서 저는 당연히 private을 클로저를 사용하여 복잡한 코드로 트랜스파일링 했을 것이라 생각했습니다. 그런데 그게 아니라 트랜스파일링된 자바스크립트는 그냥 객체에 프로퍼티로 값을 추가해버립니다.

 

정말 흥미로운 건 여기부터 입니다. 아마 자바스크립트를 조금이라도 다룰 줄 아시는 분이라면 프로퍼티에 접근하는 방법을 알고 계실 겁니다.

객체.프로퍼티 또는 객체[프로퍼티]의 방법이 그 예시입니다. 그런데 타입스크립트에서는 이 코드를 어떻게 생각할까요?

 

이 코드는 아까 위의 코드 밑에 추가적으로 작성한 코드입니다.

15번 라인은 Member class를 이용해 객체를 생성했고, 생성자로 memberId 필드에 '윤자이'라는 string 값을 할당해줬습니다.

 

그리고 위에서 선언한 getter 함수를 이용해서 Member 객체가 갖고 있는 private 필드를 출력하는 코드를 작성했습니다. 그 리 고 17번 라인에 위에서 말씀드린 대로 객체.프로퍼티 문법으로 log를 찍는 코드를 작성했습니다.

 

Typescript 코드

??????? 에러를 뱉습니다.

분명 위에서 우리는 트랜스파일링된 js코드에서 memberId가 Member 객체에 프로퍼티로 할당된 것을 보았습니다.

그런데 타입스크립트는 당당하게 error라며 memberId라는 프로퍼티는 private으로 선언되어 있으므로 접근할 수 없다고 빨간 줄까지 그어가며 에러라고 경고합니다.

 

ts코드에서 에러라고 하니까 어안이 벙벙합니다. 일단 에러라고 하니까 17번 라인을 지운 후에 트랜스파일링을 하고 이번엔 트랜스파일링된 js코드에서 member.memberId를 해보겠습니다.

 

Javascript 코드

보이시나요...? 역시 예상대로 member.memberId가 너무나도 잘 출력이 됩니다. 그러니까 쉽게 말해서 typescript는 실제로 private을 구현하지 않고 에디터 단에서 눈속임을 하고 있는 것입니다.

 

저는 이러한 마이크로소프트의 개발 철학이 신의 한 수라고 생각합니다.

이 포스팅 초반에 저는 클로저를 공부했지만 JS로 개발을 하며 한 번도 사용한 적이 없다고 했습니다. 그 이유는 너무나도 간단합니다. 그럴 바엔 Java로 개발했을 것이기 때문입니다ㅋㅋㅋ.

 

Javascript 생태계를 사랑하는 개발자들의 타겟층의 니즈는 너무나도 확실합니다. 가볍고도 빠른 생산성. 만약 javascript로 무겁고 생산성이 저하되는 개발을 해야 한다면 저는 기필코 자바스크립트 생태계를 떠날 것입니다. (왜냐면 저는 자바를 사랑하기 때문ㅎ)

 

처음 Typescript를 사용했을 때 길어지는 코드를 보며 생산성이 저하된다는 생각을 했습니다. 그만큼 자바스크립트 코드는 짧고 간결했기 때문입니다. 하지만 typescript를 조금 더 사용해보며 런타임이 아닌 트랜스파일링 시점에서 에러를 잡아주고, 직관적으로 타입을 알 수 있는 코드는 장기적으로 생산성을 훨씬 올려준다는 것을 경험하게 되었습니다.

 

타입스크립트의 성능은 필연적으로 자바스크립트의 코드에 의존합니다. 왜냐하면 타입스크립트는 머신코드로 번역되는 것이 아니라 자바스크립트로 트랜스파일링 되는 언어이기 때문입니다. 그러므로 타입스크립트가 트랜스파일링되는 속도는 전혀 무의미하며, 순전히 트랜스파일링된 자바스크립트 코드의 성능에 의존하게 되고, 당연히 타입스크립트 컴파일러의 번역 철학에 따라 자바스크립트의 성능에 직접적인 영향을 끼치게 됩니다.

 

그런데 위에서 알 수 있다시피 타입스크립트 컴파일러 정책은 굉장히 느슨합니다. 사실 저는 저 짧은 코드에 클로저와 프로퍼티 구현의 유의미한 성능 차이가 있을지는 잘 모르겠습니다. 다만 마이크로소프트가 자바스크립트 생태계의 니즈를 너무도 잘 파악했다는 것에 감탄을 할 수밖에 없을 것 같습니다. 

앞에서도 언급했듯이 타입스크립트는 자바스크립트의 런타임 시에 에러를 확인할 수 있는 불편함을 해결했습니다. 그런데 이러한 불편함을 자바스크립트의 코드의 구현이 아닌 에디터 단의 눈속임으로 구현함으로써 동시에 자바스크립트의 가볍고 유연함을 지켜냈다는 것.

 

왜 많은 자바스크립트 개발자들이 타입스크립트에 대해 열광하는지 조금은 알 것 같은 기분이 듭니다. 모든 자바스크립트 개발자들이 타입스크립트를 쓰는 날이 왔으면 좋겠습니다. 모두들 이 좋은 거 쓰세요 ㅠㅠ!!!

반응형