게시: 기존 깃블로그 2023년 06월 29일 글
엄격모드 개요 및 기능, 사용법
일반적으로 React를 사용해본 경험이 있다면 index.js
에서 <React.StrictMode/>
또는 <StrictMode/>
를 본 적이 있을 것이다. 이는 개발 환경에서 애플리케이션 내 문제를 조기에 발견하도록 돕는 기능이다.
주로 컴포넌트 트리 내부에서 발생할 수 있는 부작용을 탐지하고, deprecated에 대한 경고나 hook 콜백의 정리가 제대로 이루어졌는지 등을 확인한다.
자바스크립트에서도 React와 같이 엄격 모드(Strict Mode)를 사용할 수 있는데, 이는 ES5(2009)에 등장했다.
기본적으로는 느슨한 모드(Sloppy Mode)이기 때문에 엄격 모드에 대한 별도의 선언이 필요하다.
사용법은 간단하게 'use strict;'
를 코드 최상단에 추가하는 것으로 끝난다.
주요 기능
- 기존에 무시되던 에러를 throw함
- JS 엔진 최적화를 어렵게 하는 실수를 잡아주며, 가끔 느슨한 모드보다 빠르게 실행
- 향후 ECMA 표준에 적용될 문법 사용을 제한
- 전체 스크립트 또는 부분 함수에 적용이 가능
-> 전체 스크립트 : eval, function, event handler, setTimeout 등 전달된 문자열 - 블럭문 {}, 컨텍스트에는 적용이 불가
- ES6의 JS 모듈의 전체 콘텐츠는 자동으로 엄격 모드가 적용
- 엄격 모드는 구문과 런타임의 동작을 변경-> 런타임 동작 변경: this 바인딩 규칙 변경, 변수 선언 규칙 강화 등
-> 구문 변경: 특정 키워드 사용 제한 (예: with 문 사용 금지)
이 외에도 암묵적 변수 선언 금지, 중복 키 사용 방지 등 여러 규칙을 적용하여 코드의 안정성과 보안을 높이고 최적화된 코드 작성을 도와준다.
실수를 에러로 throw
- 변수 생성 시, 선언이 없을 경우
- 기존에는 var 또는 let or const 선언 없이도
변수명=값
을 지정하고 변수를 호출하면 값이 정상적으로 나왔다. 하지만, 엄격 모드에서는 변수에 대한 선언 없이는 에러를 호출한다.
기본 x=5;
x; // 5 출력
// 엄격 모드
'use strict';
x=5;
x; // 참조에러 발생, not defined`
=> 꼭 선언을 해줘야 함
- 동일한 이름의 파라미터가 있을 경우
- 하나 이상의 파라미터명이 같으면 에러가 발생
'use strict'; const testFunc = (a,a,c) => { return a+b+c; }; console.log(testFunc(1,2,3)); // 에러 발생
- 기본 모드에서 마지막으로 중복된 인수가 이렇게 지정된 인수를 숨기는데 이러한 인수들은 arguments[i]를 통해 접근이 가능
- => 이는 코드의 명확성을 해치는 문제가 있음
- 변수 또는 함수 등 선언 후에 삭제하려고 할 때, 에러 발생
- 선언 후에 delete하려고 하면 에러가 발생함=> function 또한 동일한 에러 발생
// IIFE를 통한 예시 (() => { 'use strict'; let x = 5; delete x; // SyntaxError 발생 })();
※ IIFE (Immediately Invoked Function Expression, 즉시 실행 함수 표현)
- 정의되자마자 즉시 실행하는 함수로서 익명함수이다.
- 삭제할 수 없는 프로퍼티를 삭제하려고 하는 경우
- 프로퍼티 삭제 시, 에러 발생
delete Object.prototype // TypeError
- 예외를 발생시키는 에러
- NaN은 쓸 수 없는 전역 변수이며, NaN에 할당하는 일반적인 코드는 아무것도 하지 않는다. 하지만, 엄격 모드에서 NaN에 할당하면 에러가 발생한다. 또한, 쓸 수 없는 전역 프로퍼티, getter-only 프로퍼티, 확장 불가 객체에 프로퍼티를 할당하는 경우 예외-에러 발생
'use strict'; // undefined
let undefined = 5 // TypeError
// getter-only
let obj = { get x() {return 17;} };
obj.x = 5; // Error
// 확장 불가 객체
let fixed = {}
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // Error
- 8진수 구문 및 이스케이프 문자 사용
- 8진수를 그대로 사용하는 것은 에러를 발생
// 8진수
let oct1 = 010
// 이스케이프 문자 사용
let oct2 = "/010"; // 유효하지만 8진수로 해석 X
=> ECMA2015에서는 접두사에 "0o"를 붙여서 8진수를 지원
- 숫자 앞에 0 사용
- 정렬하려고 숫자를 사용하는 경우가 있는데, 이럴 경우 에러가 발생
'use strict';
let num1 = 012 +
345 +
678;
// Error 발생
- 원시값에 프로퍼티 설정 금지
- 기본 모드(느슨한 모드)에서는 되지만, 엄격 모드에서는 TypeError를 발생시킨다.
'use strict';
// primitive
false.true = "";
(14).sailing = "home";
- 실수로 글로벌 변수 생성
- 일반 JS에서 변수를 잘못 입력하면 전역 객체에 대한 새 속성이 생성되고 동작을 한다. 이렇게 전역 변수를 생성하는 할당은 엄격 모드에서는 에러를 발생하게 한다.
보안 증가
- this로 함수에 전달된 값은 객체가 되지 않음
- 일반적인 함수에서 this는 언제나 객체인데, 이러한 자동 박싱은 성능 비용뿐만 아니라 전역 객체가 노출되어 위험하다.
- -> 엄격모드에서는 this가 boxed된 객체가 아니며, 정의가 되지 않은 경우
undefined
로 나온다.function test() { return this; }; console.assert(test() === undefined); // undefined console.assert(test.call(2) === 2); // 2 console.assert(test.apply(undefined) === undefined); // undefined console.assert(test.bind(true)() === true); // true
- -> 엄격모드에서는 this가 boxed된 객체가 아니며, 정의가 되지 않은 경우
- 특정 this를 명세하기 위해서는 .call, .apply, .bind 메서드를 통해 가능
- -> 더 이상 window 객체를 this로 참조가 불가능
- 더 이상 스택을 따라 올라가는 것이 불가능
- 엄격 모드에서는
arguments.caller
와arguments.callee
에 접근할 수 없다. 이는 함수 호출 스택을 탐색하는 것을 방지하여 보안을 강화한다.
* 실행 코드
'use strict';
function restricted() {
console.log(restricted.caller); // TypeError
console.log(arguments.callee); // TypeError
}
restricted();
* 실행 결과
VM245:3 Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
at restricted (<anonymous>:3:25)
at <anonymous>:6:1
- 인수는 더 이상 해당 함수의 호출 변수에 대한 접근을 제공하지 않음
- 엄격 모드에서는
arguments
객체가 함수 내부의 변수와 동기화되지 않는다. 이는 코드의 예측 가능성을 높이고 최적화를 용이하게 한다.
'use strict';
function f(a) {
a = 2;
return [a, arguments[0]];
}
console.log(f(1)); // [2, 1]
마치며
엄격 모드는 자바스크립트 코드의 안정성과 보안을 향상시킬 수 있는 중요한 기능으로서 잠재적인 오류나 안전하지 않은 작업을 방지하고 코드의 최적화를 도와준다.
기존에 사용하지 않던 스크립트나 프로젝트에는 검토한 후에 추가해야겠지만 새로운 프로젝트에는 추가해서 개발해보는 것도 좋을 것 같다. 일반 라이브러리에서도 많이 사용하고 있으니 직접 넣어보고 테스트해봐야겠다.