1.5 엄격 모드 (Strict Mode)
엄격 모드란?
JavaScript의 **엄격 모드(Strict Mode)**는 ES5에서 도입된 기능으로, JavaScript의 느슨한(sloppy) 기본 동작 대신 더 엄격한 규칙을 적용하는 모드입니다.
"use strict"; // 이 한 줄이 엄격 모드를 활성화
// 이제 더 엄격한 규칙이 적용됩니다
엄격 모드 활성화 방법
전역 수준 (파일 전체)
"use strict";
// 파일 전체에 엄격 모드 적용
function example() {
// 이 함수도 엄격 모드
}
함수 수준
function strictFunction() {
"use strict"; // 이 함수에만 적용
// 엄격 모드
}
function normalFunction() {
// 비엄격 모드
}
ES 모듈 (자동 적용)
// .js 파일에서 import/export를 사용하면 자동으로 엄격 모드
import { something } from './module.js';
// "use strict" 없어도 엄격 모드!
클래스 (자동 적용)
class MyClass {
// 클래스 내부는 자동으로 엄격 모드
method() {
// 엄격 모드
}
}
비엄격 vs 엄격 모드 차이점
1. 미선언 변수 금지
// ❌ 비엄격 모드: 미선언 변수가 전역 변수로 생성됨 (버그의 원인!)
function nonStrict() {
x = 10; // 선언 없이 할당 → 전역 변수 x가 생성됨
console.log(x); // 10
}
nonStrict();
console.log(x); // 10 (전역 오염!)
// ✅ 엄격 모드: ReferenceError 발생
function strict() {
"use strict";
y = 20; // ReferenceError: y is not defined
}
strict();
2. this 바인딩 차이
// 비엄격 모드: 일반 함수의 this는 전역 객체 (브라우저: window, Node.js: global)
function showThis() {
console.log(this); // window (브라우저) or global (Node.js)
}
showThis();
// 엄격 모드: 일반 함수의 this는 undefined
function showThisStrict() {
"use strict";
console.log(this); // undefined
}
showThisStrict();
// 실용적인 예: 메서드를 변수에 담으면 this가 달라짐
class Button {
constructor(label) {
this.label = label;
}
handleClick() {
console.log(this.label); // undefined (this가 달라짐)
}
}
const btn = new Button('제출');
const handler = btn.handleClick;
handler(); // 비엄격: window.label (undefined), 엄격: TypeError
3. 중복 파라미터 금지
// ❌ 비엄격 모드: 중복 파라미터 허용 (마지막 값이 사용됨)
function duplicate(a, a, b) {
console.log(a, b); // 두 번째 a 값이 사용됨
}
duplicate(1, 2, 3); // 2 3
// ✅ 엄격 모드: SyntaxError
function strictDuplicate(a, a, b) { // SyntaxError: Duplicate parameter name
"use strict";
}
4. with 문 금지
const obj = { x: 10, y: 20 };
// ❌ 비엄격 모드: with 문 사용 가능 (성능과 가독성 문제)
with (obj) {
console.log(x + y); // 30 (obj.x + obj.y)
}
// ✅ 엄격 모드: SyntaxError
"use strict";
with (obj) { // SyntaxError: Strict mode code may not include a with statement
console.log(x + y);
}
5. delete 제한
// 비엄격 모드: delete 실패 시 false 반환
var x = 10;
console.log(delete x); // false (조용히 실패)
// 엄격 모드: TypeError 발생
"use strict";
var y = 20;
delete y; // SyntaxError: Delete of an unqualified identifier in strict mode
// 변수 삭제 vs 객체 프로퍼티 삭제
const obj = { a: 1, b: 2 };
delete obj.a; // OK: 객체 프로퍼티 삭제는 엄격 모드에서도 가능
console.log(obj); // { b: 2 }
// 설정 불가 프로퍼티 삭제
const obj2 = {};
Object.defineProperty(obj2, 'permanent', {
value: 42,
configurable: false,
});
delete obj2.permanent; // 비엄격: false, 엄격: TypeError
6. eval 스코프 격리
// 비엄격 모드: eval이 현재 스코프에 변수 추가 가능
eval("var leaked = 'I am leaked!'");
console.log(leaked); // 'I am leaked!' (스코프 오염)
// 엄격 모드: eval은 자신만의 스코프를 가짐
"use strict";
eval("var notLeaked = 'isolated'");
console.log(notLeaked); // ReferenceError: notLeaked is not defined
7. 읽기 전용 프로퍼티 쓰기 금지
// 비엄격 모드: 조용히 실패
const obj = {};
Object.defineProperty(obj, 'readOnly', {
value: 42,
writable: false,
});
obj.readOnly = 100; // 조용히 실패
console.log(obj.readOnly); // 42 (변경 안됨)
// 엄격 모드: TypeError 발생
"use strict";
obj.readOnly = 100; // TypeError: Cannot assign to read only property
엄격 모드를 사용해야 하는 이유
버그 예방
// 흔한 실수: 오타로 새 전역 변수 생성
"use strict";
let userName = "김철수";
userNmae = "이영희"; // ReferenceError! (오타: userNmae)
// 엄격 모드 없으면 조용히 전역 변수 생성 → 디버깅 어려움
보안 강화
"use strict";
function secureFunction() {
// 엄격 모드에서 this는 undefined (전역 객체 접근 불가)
if (this) {
// 이 코드는 실행되지 않음
globalThis.secretKey = '해킹';
}
}
secureFunction();
미래 JavaScript와의 호환성
엄격 모드는 미래 ECMAScript 버전에서 키워드가 될 예약어 사용을 금지합니다:
"use strict";
// 다음 식별자들은 엄격 모드에서 예약어
// implements, interface, let, package, private, protected, public, static, yield
let implements = 1; // SyntaxError (예약어)
실전 패턴: 엄격 모드 + 모던 JS
현대 JavaScript 개발에서는 다음 이유로 항상 엄격 모드가 적용됩니다:
// 1. ES 모듈 (import/export) → 자동 엄격 모드
import { helper } from './utils.js';
// 2. 클래스 → 자동 엄격 모드
class MyService {
process() { /* 엄격 모드 */ }
}
// 3. TypeScript → 항상 엄격 모드로 컴파일
// 4. Vite, webpack 같은 번들러 → 보통 엄격 모드 활성화
레거시 .js 파일(모듈이 아닌 스크립트)을 작성할 때는 파일 상단에 "use strict"를 명시하는 것이 좋습니다.
엄격 모드 전체 제약 요약
| 제약 | 비엄격 | 엄격 |
|---|---|---|
| 미선언 변수 | 전역 변수 생성 | ReferenceError |
| 함수의 this | 전역 객체 | undefined |
| 중복 파라미터 | 허용 | SyntaxError |
| with 문 | 허용 | SyntaxError |
| 변수 delete | false (조용히 실패) | SyntaxError |
| 읽기 전용 프로퍼티 쓰기 | 조용히 실패 | TypeError |
| eval 스코프 | 현재 스코프 오염 | 격리된 스코프 |
| arguments.callee | 허용 | TypeError |
| 8진수 리터럴 (0123) | 허용 | SyntaxError |
고수 팁
엄격 모드 없는 코드 마이그레이션
기존 비엄격 모드 코드를 엄격 모드로 전환할 때 주의점:
// 1. 전역 변수 누수 수정
// 전: x = 10 → 후: let x = 10
// 2. with 문 제거
// 전:
with (obj) { console.log(name); }
// 후:
const { name } = obj;
console.log(name);
// 3. arguments.callee 대체
// 전:
function factorial(n) {
return n <= 1 ? 1 : n * arguments.callee(n - 1);
}
// 후:
function factorial(n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
ESLint로 엄격 모드 강제
// eslint.config.js
export default [
{
rules: {
'strict': ['error', 'global'], // 전역 엄격 모드 강제
},
},
];