자바 스크립트 에서 ` globalThis ` 의 소름 끼치 는 폴 리필 | TOAST UI : : Make Your Web Delicious ! 
 자바 스크립트 에서 globalThis 의 소름 끼치 는 폴 리필 
 원문 : https : / / mathiasbynens . be / notes / globalthis 
 globalThis 제안 은 모든 자바 스크립트 환경 에서 전역 this 에 접근 할 수 있 는 메커니즘 을 도입 한다 . globalThis 의 폴 리필 은 매우 간단 할 것 같 지만 , 정확 하 게 만들 기 는 매우 어렵 다 . Toon 이 창조 적 인 해결책 으로 나 를 깜짝 놀래키 기 전 까지 나 는 그것 이 가능 하 다고 생각 조차 못 했 다 . 
 이 글 은 globalThis 의 적절 한 폴 리필 작성 이 어렵 다는 것 을 설명 한다 . 폴 리필 은 아래 의 요구 사항 을 따라야 한다 . 
 브라우저 , 브라우저 의 워커 , 브라우저 의 확장 프로그램 , Node . js 그리고 standalone ( 이하 독립 형 ) 자바 스크립트 엔진 바이너리 에서 모두 동작 해야 한다 . 
 sloppy mode ( 이하 느슨 한 모드 ) , strict mode ( 이하 엄격 한 모드 ) 그리고 자바 스크립트 모듈 을 모두 지원 해야 한다 . 
 코드 가 실행 되 는 컨텍스트 에 관계없이 동작 해야 한다 . ( 즉 , 빌드 할 때 폴 리필 이 엄격 한 모드 인 함수 로 래핑 된 경우 에 도 정확 하 게 동작 해야 한다 . ) 
 먼저 용어 에 대해서 정리 하 겠 다 . globalThis 는 전역 스코프 의 this 값 을 제공 한다 . 이것 은 복잡 한 이유 로 브라우저 의 전역 객체 와 는 다르 다 . 
 자바 스크립트 모듈 에서 모듈 스코프 는 전역 스코프 와 당신 의 코드 사이 에 개입 되 어 있 다는 점 에 유의 해야 한다 . 모듈 스코프 는 글로벌 스코프 의 this 를 숨기 기 때문 에 모듈 스코프 의 최 상단 에서 this 는 undefined 이 다 . 
 즉 , globalThis 는 " 전역 객체 " 가 아니 며 , 단지 전역 스코프 의 this 를 의미 한다 . 이 중요 한 뉘앙스 를 이해 시켜 준 Domenic 에게 감사 한다 . 
 globalThis 의 대안 
 브라우저 에서 globalThis 와 동일 한 것 은 window 이 다 . 
 frames 도 동일 하 게 동작 한다 . 
 하지만 , window 와 frames 는 ( 웹 워커 와 서비스 워커 와 같 은 ) 워커 컨텍스트 안 에서 undefined 이 다 . 운 좋 게 도 self 는 모든 브라우저 컨텍스트 에서 동작 하 므로 더 강력 한 대안 이 다 . 
 Node . js 에서 는 window , frames , self 을 사용 할 수 없 지만 , global 을 사용 할 수 있 다 . 
 jsvu 으로 설치 하 는 것 과 같 은 독립 형 자바 스크립트 엔진 쉘 에서 는 위 에서 설명 한 모든 것 ( window , frames , self , global ) 을 사용 할 수 없 다 . 여기 서 는 전역 this 에 접근 할 수 있 다 . 
 게다가 느슨 한 모드 함수 는 그 들 의 this 를 전역 this 로 설정 할 수 있 기 때문 에 , 코드 를 전역 스코프 에서 실행 할 수 없 더라도 전역 this 에 접근 할 수 있 다 . 
 하지만 , 자바 스크립트 모듈 에서 최 상단 의 this 는 undefined 이 고 , 엄격 한 모드 의 함수 안 에서 this 는 undefined 이 다 . 그래서 이 접근 방법 은 여기 서 동작 하 지 않 는다 . 
 일단 엄격 한 모드 의 컨텍스트 안 에서 임시 로 엄격 한 모드 를 깨 고 나올 수 있 는 방법 은 오직 하나 다 . Function 생성자 는 느슨 한 함수 를 생성 한다 . 
 음 , eval 도 같 은 효과 를 내 기 때문 에 두 가지 방법 이 있 다 . 
 브라우저 에서 Function 생성자 와 eval 을 사용 하 는 것 은 컨텐츠 보안 정책 ( Content Security Policy ( CSP ) ) 때문 에 종종 허락 되 지 않 는다 . 웹 사이트 는 종종 이런 정책 을 옵션 으로 가져가 지만 , 예 를 들 어 크롬 확장 프로그램 안 에서 는 시행 하 고 있 다 . 불행 하 게 도 , 이것 은 적절 한 폴 리필 이 Function 생성자 와 eval 에 의존 할 수 없 다는 것 을 의미 한다 . 
 간단 한 폴 리필 
 위 의 기법 들 을 결합 하 여 아래 와 같이 하나 의 폴 리필 을 만들 수 있 다 . 
 / / 네이티브 globalThis 보강 판 . 이것 은 사용 하 지 마세요 ! 
 / / 주의 : 전역 스코프 에서 실행 될 때 ` globalThis ` 를 전역 객체 로 만들 기 위해 
 / / ( 어휘 적 ( lexical ) 범위 의 최 상단 변수 와 는 대조 적 으로 ) 
 / / ` const ` 대신 에 ` var ` 를 사용 했 다 . 
 하지만 이 코드 는 엄격 한 모드 의 함수 나 브라우저 가 아닌 환경 의 자바 스크립트 모듈 안 에서 는 동작 하 지 않 는다 . ( globalThis 를 지원 하 는 경우 는 제외 ) . 게다가 getGlobal 은 잘못 된 결과 를 반환 할 수 있 다 . 왜냐하면 this 에 의지 하 는데 , this 는 컨텍스트 에 의존 적 이 고 번 들러 에 의해서 변경 될 수 있 기 때문 이 다 . 
 강력 한 폴 리필 
 globalThis 의 강력 한 폴 리필 을 작성 할 수 있 을까 ? 다음 과 같 은 환경 이 있 다고 가정 해 보 자 . 
 globalThis , window , self , global , this 에 의존 할 수 없 다 . 
 Function 생성자 와 eval 을 사용 할 수 없 다 . 
 하지만 다른 자바 스크립트 내장 기능 의 무결 성 에 의존 할 있 다 . 
 해결책 은 찾 았 지만 방식 이 아름답 지 는 않 다 . 이것 에 대해서 잠시 생각 해 보 자 . 
 전역 this 에 직접 접근 하 는 방법 을 모른 채 전역 this 에 어떻게 접근 할 수 있 을까 ? 만약 globalThis 에 함수 프로 퍼티 를 어떻게 든 지정 하 고 , 그것 을 globalThis 의 함수 로써 호출 한다면 , 그 함수 안 에서 this 를 접근 할 수 있 다 . 
 globalThis 나 globalThis 를 참조 하 는 바인딩 없이 어떻게 그것 이 가능 한가 ? 다음 코드 는 실행 할 수 없 다 . 
 foo ( ) 는 더 이상 함수 로 호출 되 어 질 수 없 고 , 또한 위 에서 언급 했 듯이 엄격 한 모드 나 자바 스크립트 모듈 에서 이 함수 안 의 this 는 undefined 이 다 . 엄격 한 모드 의 함수 는 그 들 의 this 를 undefined 로 설정 한다 . 하 지만 getter 와 setter 의 경우 는 아니 다 . 
 configurable : true / / 이것 은 나중 에 getter 를 ` delete ` 가능 하 게 한다 . 
 // ( 어휘 적 ( lexical ) 범위 의 최 상단 변수 와 대조 적 으로 ) 
 / / ` const ` 대신 에 ` var ` 가 사용 되 어 진다 . 
 위 의 코드 에서 globalThis 에 getter 를 설정 하 고 getter 를 통해서 globalThis 의 참조 를 가저 온 다음 , 더 이상 필요 없 는 getter 는 삭제 한다 . 이 기법 은 원 하 는 모든 상황 에서 globalThis 에 접근 할 수 있 지만 , 첫 번 째 라인 에서 여전히 ( 여기 서 는 globalThis 라고 부르 는 ) 전역 this 참조 에 의존 하 고 있 다 . 이 의존 성 을 피할 수 있 을 까 ? globalThis 에 직접 접근 하 지 않 고 getter 를 전역 적 으로 설정 할 수 있 을 까 ? 
 globalThis 에 getter 를 설정 하 는 것 대신 에 , 전역 this 객체 를 Object . prototype 으로 상속 받 아서 getter 를 설정 할 수 있 다 . 
 주의 : 사실 ECMAScript 스펙 에 전역 this 가 Object . prototype 을 상속 받 는다는 내용 은 없 고 , 단지 객체 여야 한다고 명시 되 어 있 다 . Object . create ( null ) 은 Object . prototype 을 상속 받 지 않 은 객체 를 만든 다 . 자바 스크립트 엔진 은 Object . prototype 를 상속 받 지 않 는 객체 를 this 로 사용 하 더라도 스펙 에 위배 되 지 않 으며 , 이 경우 위 와 같 은 코드 는 여전히 동작 하 지 않 을 것 이 다 . ( 실제로 IE 7 은 그렇 게 한다 . ) 운 좋 게 , 좀 더 최신 의 자바 스크립트 엔진 은 전역 this 가 Object . prototype 을 prototype 체인 으로 가져야만 한다고 동의 한 것 으로 보인다 . 
 globalThis 를 이미 사용 할 수 있 는 최신 의 환경 에서 는 Object . prototype 가 변화 ( mutating ) 하 는 것 을 막 기 위해서 폴 리필 을 아래 와 같이 수정 할 수 있 다 . 
 / / 이제 코드 에서 ` globalThis ` 를 사용 할 수 있 다 . 
 혹은 __ defineGetter __ 를 사용 할 수 있 다 . 
 이것 은 지금 까지 본 폴 리필 중 가장 끔찍 한 것 이 다 . 소유 하 지 않 은 객체 ( object ) 는 변경 하 지 않 는 것 이 관행 인데 , 이 폴 리필 은 이런 관행 을 완전히 무시 한다 . 자바 스크립트 엔진 의 기본 원리 인 프로토타입 최적화 에서 설명 하 듯이 내장 된 프로토타입 을 변경 하 는 것 은 일반 적 으로 나쁜 생각 이 다 . 
 반면 에 이 폴 리필 을 깨뜨릴 유일 한 방법 은 폴 리필 이 실행 되 기 전 에 누군가 가 Object 또는 Object . defineProperty ( 또는 Object . prototype . __ defineGetter __) 를 변경 하 는 것 이 다 . 나 는 이 보다 더 강력 한 폴 리필 을 생각 해낼 수 없 다 . 여러분 은 어떠 한가 ? 
 폴 리필 테스트 
 이 폴 리필 은 범용 적 인 자바 스크립트 의 흥미 로운 예 이 다 . 폴 리필 은 순수 한 자바 스크립트 코드 로 호스트 빌트인 기능 에 의존 하 지 않 고 ECMAScript 가 구현 된 어느 환경 에서 나 실행 될 수 있 다 . 이것 은 애초 에 폴 리필 의 목표 중 하나 였 다 . 실제로 이것 이 동작 하 는지 확인 해 보 자 . 
 여기 에 이 폴 리필 을 위한 HTML 데모 페이지 가 있 다 . 이 데모 에서 는 고전 적 인 스크립트 인 globalthis . js 와 동일 한 코드 로 모듈 방식 인 globalthis . mjs 를 사용 하 여 globalThis 를 출력 한다 . 이 데모 는 폴 리필 이 브라우저 에서 동작 하 는지 확인 하 는 데 사용 될 수 있 다 . globalThis 는 기본 적 으로 Chrome 71 / V 8 v 7 . 1 , Firefox 65 , Safari 12 . 1 , iOS Safari 12 . 2 에서 지원 한다 . 폴 리필 의 흥미 로운 부분 을 테스트 하 기 위해서 는 이전 버전 의 브라우저 에서 데모 페이지 를 열 어야 한다 . 
 Node . js 와 독립 형 자바 스크립트 엔진 에서 테스트 하 기 위해서 는 동일 한 자바 스크립트 파일 을 다운로드 한다 . 
 # 폴 리필 과 데모 코드 를 모듈 로 다운로드 해라 
 # 이 파일 을 고전 적 인 자바 스크립트 파일 로 사용 할 수 있 도록 복사 ( 즉 , symlink ) 해라 
 이제 node 에서 테스트 할 수 있 다 . 
 독립 형 자바 스크립트 엔진 쉘 에서 테스트 하 기 위해서 는 jsvu 를 사용 해서 원 하 는 엔진 을 설치 하 고 스크립트 를 바로 실행 할 수 있 다 . 예 를 들 어 ( globalThis 를 지원 하 지 않 는 ) V 8 의 7 . 0 버전 과 ( globalThis 를 지원 하 는 ) 7 . 1 버전 에서 테스트 하 기 위해서 는 아래 와 같이 하 면 된다 . 
 이 와 같 은 기술 로 JavaScriptCore , SpiderMonkey , Chakra 그리고 XS 와 같 은 다른 자바 스크립트 엔진 에서 테스트 할 수 있 다 . 여기 JavaScriptCore 를 사용 한 예제 가 있 다 . 
 자바 스크립트 를 사용 하 는 것 은 까다롭 고 , 종종 독창 적 인 방법 을 요구 한다 . globalThis 는 전역 this 에 쉽 게 접근 할 수 있 게 해준다 . 정확 하 게 동작 하 는 globalThis 폴 리필 은 보 기 보단 좀 더 도전 적 이 지만 , 동작 하 는 해결책 이 있 다 . 
 정말로 필요 할 때 만 이 폴 리필 을 사용 해라 . 자바 스크립트 모듈 은 전역 상태 를 변경 하 지 않 고 기능 을 쉽 게 가져오 거나 내보낼 수 있 다 . 대부분 의 최신 자바 스크립트 코드 는 전역 this 에 접근 을 필요 로 하 지 않 는다 . globalThis 는 라이브러리 와 폴 리필 에서 만 유용 하 다 . 
 npm 에 있 는 globalThis 폴 리필 
 이 글 을 게시 한 이후 에 다음 과 같 은 npm 패키지 가 이 기술 을 이용 해서 globalThis 폴 리필 을 제공 하 기 시작 했 다 . 
 참고 : 나 는 이 패키지 들 중 어떠 한 것 의 저자 도 관리자 도 아니 다 . 
 이소희 , FE Development Lab 2019 . 05 . 03 Back to list