Strict Mode는 더 엄격한 버전의 자바스크립트입니다
자바스크립트는 역사가 오래된 만큼, 지금 와서 보면 고개를 갸웃하게 만드는 결정들을 잔뜩 떠안고 있습니다. 선언 없이 값을 할당하면 슬그머니 전역 변수가 만들어지고, this는 함수를 어떻게 호출했느냐에 따라 의미가 달라지며, 매개변수 이름이 중복돼도 그냥... 동작해 버립니다. 이걸 지금 와서 고치면 기존 웹이 전부 깨져 버리니까, 언어를 관리하는 위원회인 TC39는 다른 길을 택했습니다. 바로 원하는 사람만 켤 수 있는 모드를 만들어서, 이 위험한 부분들을 다듬어 놓은 거죠.
이렇게 선택적으로 켜는 모드가 바로 strict mode(엄격 모드) 입니다. 파일이나 함수 맨 위에 한 줄만 적으면 켜집니다:
이 코드를 실행하면 ReferenceError: x is not defined 에러가 납니다. 반면 이 지시어가 없으면 동일한 코드가 아무 문제 없이 x라는 전역 변수를 만들고 10을 출력하죠. 같은 언어인데 규칙이 두 가지로 나뉘는 셈입니다.
'use strict' 지시어란?
이 지시어는 그냥 문자열 리터럴입니다 — 'use strict'; 또는 "use strict"; 이렇게요. 중요한 건 스크립트나 함수의 첫 번째 문장이어야 한다는 점입니다. 앞에 뭐라도 — 심지어 의미 없는 표현식 하나라도 — 먼저 오면 엔진은 이걸 그냥 평범한 문자열로 보고 무시해 버립니다.
strict mode를 함수 하나에만 적용하고 싶다면 해당 함수 안쪽에 지시어를 넣으면 됩니다. 다만 요즘은 아무도 이렇게 쓰지 않아요. 기본적으로 strict인 모듈을 작성하거나, 아니면 파일 전체에 strict mode를 적용하는 식입니다.
strict mode가 실제로 바꾸는 것들
'use strict'는 하나의 규칙이 아니라 여러 동작을 한꺼번에 바꾸는 묶음입니다. 핵심만 추려보면:
- 선언하지 않은 변수에 값을 할당하면 전역 변수가 만들어지는 대신 에러가 납니다.
- 일반 함수 호출에서
this는 전역 객체가 아니라undefined가 됩니다. - 매개변수 이름이 중복되면(
function f(a, a) {}) 문법 에러가 됩니다. - 읽기 전용 속성에 값을 대입하면 조용히 실패하지 않고 에러가 발생합니다.
- 일반 변수나 함수를
delete하면 에러가 납니다. - 미래 예약어(
implements,interface,package,private,protected,public,static,yield) 몇 개는 변수 이름으로 쓸 수 없습니다.
간단한 예시로 살펴볼게요:
방금 본 예시들은 전부 "엔진이 실수 가능성을 더 일찍 잡아줬다"는 얘기예요. 결국 strict mode가 주는 가치는 이거 하나로 정리됩니다.
조용히 생기는 전역 변수 버그
사실 자바스크립트 strict mode가 존재하는 가장 큰 이유가 바로 이겁니다. strict mode를 켜지 않으면, 오타 하나가 그대로 전역 변수가 되어버리거든요:
// 비 strict 모드 (이렇게 하지 마세요)
function setup() {
usernmae = 'Ada'; // 오타 — window.usernmae 가 생성됨
}
setup();
console.log(username); // undefined — 원래 변수는 설정되지 않음
프로그램은 그대로 돌아갑니다. 에러도 안 납니다. 버그는 한참 뒤에야 드러나죠. username을 읽어야 할 자리에서 undefined가 튀어나오는 순간 말이에요. 자바스크립트 strict mode에서는 똑같은 오타가 실행되는 그 즉시 에러를 던져서, 몇 시간이 아니라 몇 초 만에 잡아낼 수 있습니다.
요즘 자바스크립트는 기본이 엄격 모드다
여기서 많은 분들이 헷갈려 합니다. 오늘날 작성하는 자바스크립트 코드는 대부분 이미 strict mode로 돌아가고 있어요. 'use strict'를 어디에도 적지 않았는데도요.
자동으로 엄격 모드가 적용되는 대표적인 두 가지 경우입니다:
- ES 모듈.
.mjs파일,<script type="module">, 그리고import/export로 불러오는 모든 코드는 strict mode로 실행됩니다. 별도의 지시어가 필요 없어요. - 클래스 본문.
class { ... }안의 모든 코드는 파일 전체가 비엄격 모드라도 자동으로 strict mode입니다.
그럼 실제로 'use strict';를 직접 써야 할 때는 언제일까요? 바로 _클래식 스크립트_에서입니다. 즉, 평범한 <script> 태그로 불러오는 옛날 방식의 JS 파일이나, 모듈 번들러 없이 require로 동작하는 구형 Node.js 파일 정도죠. 요즘 새로 짜는 코드라면 모듈이 알아서 처리해 주기 때문에 신경 쓸 필요가 없습니다.
strict mode에서 일반 함수의 this가 달라진다
초보자들이 특히 자주 당하는 동작 하나를 짚고 넘어가겠습니다. 비엄격 모드에서는 객체 없이 일반 함수를 그냥 호출하면 this가 전역 객체(브라우저에서는 window, Node에서는 global)에 바인딩됩니다. 반면 엄격 모드에서는 undefined로 바인딩됩니다:
대부분의 경우 이게 우리가 원하는 동작이에요. this가 undefined면 메서드 바인딩을 빼먹은 버그가 바로 드러나거든요. 반대로 조용히 전역 객체를 가리키고 있으면, 버그가 숨어 있다가 한참 뒤에야 다른 곳에서 터져 나옵니다.
strict mode가 해주지 않는 것들
자바스크립트 엄격 모드는 컴파일 타임과 런타임 단계에서 몇 가지를 조여주는 기능일 뿐, 타입을 붙여주거나 null 참조를 잡아주거나 사용하지 않는 변수를 경고해주진 않아요. 그건 TypeScript나 ESLint, 그리고 에디터가 할 일입니다. strict mode는 언어 차원의 특정 함정(footgun) 몇 가지를 막아주는 장치라고 생각하는 게 맞아요. 만능 안전망이 아닙니다.
그리고 "모던 자바스크립트"와 같은 말도 아닙니다. 엄격 모드에서도 엉망인 코드를 짤 수 있고, 'use strict' 없이도 훌륭한 코드를 짤 수 있어요. 그저 특정 실수를 저지르기 어렵게 만들어줄 뿐이죠.
핵심 정리
- 파일이나 함수 맨 위에
'use strict';를 넣으면 더 엄격한 버전의 자바스크립트로 실행됩니다. - 오타로 전역 변수가 만들어지는 일이 사라지고,
this가 슬그머니 전역 객체로 변하지도 않으며, 그 외 몇 가지 함정들이 에러로 바뀝니다. - ES 모듈과
class내부는 자동으로 엄격 모드예요. 그래서 이 지시어를 직접 쓸 일은 거의 없습니다. - 새 기능을 켜는 스위치가 아니라, 버그를 더 일찍 잡기 위한 장치입니다.
다음 주제: 주석
지금까지 지시어, 세미콜론, 그리고 엔진이 신경 쓰는 규칙들을 살펴봤어요. 이제는 여러분 이 미래의 독자를 위해 남기는 메모 차례입니다. 자바스크립트 주석이 어떻게 동작하고, 언제 쓸 가치가 있는지 알아볼게요.
자주 묻는 질문
자바스크립트 strict mode가 뭔가요?
strict mode는 조용히 넘어갔을 실수들을 진짜 에러로 바꿔주는 자바스크립트의 엄격 모드입니다. 파일이나 함수 맨 위에 'use strict'; 문자열을 넣으면 켜지고요. 켜면 언어가 좀 더 까다로워집니다. 선언 안 한 변수에 값을 할당하면 에러가 나고, 매개변수 이름이 중복되면 금지되고, 일반 함수 호출에서 this가 전역 객체 대신 undefined가 됩니다.
strict mode는 어떻게 켜나요?
스크립트나 함수의 가장 첫 문장으로 'use strict';를 넣으면 됩니다. 그 앞에 주석 아닌 뭔가가 한 줄이라도 있으면 그냥 평범한 문자열로 취급돼서 켜지지 않아요. 다만 요즘은 직접 쓸 일이 거의 없습니다. ES 모듈(.mjs 파일이나 <script type="module">), 그리고 모든 class 본문은 자동으로 strict mode이기 때문이죠.
왜 strict mode를 써야 하나요?
버그를 일찍 잡아주기 때문입니다. 예를 들어 usernmae = 'Ada' 같은 오타가 있으면 non-strict에서는 조용히 전역 변수를 하나 만들어버리는데, strict mode에서는 바로 ReferenceError가 납니다. 또 앞으로 예약어가 될 키워드를 미리 막아주고, 구버전 엔진에서는 중복 프로퍼티명도 금지하고, this가 예측 가능하게 동작하게 만들어서 코드를 훨씬 이해하기 쉬워집니다.
요즘 자바스크립트에서도 'use strict'를 꼭 써야 하나요?
보통은 안 써도 됩니다. ES 모듈과 class 본문은 기본이 strict mode이고, 요즘 프로젝트는 거의 다 둘 중 하나거든요. 'use strict';를 직접 써야 하는 건 옛날 방식의 클래식 스크립트 — 그러니까 type="module" 없이 그냥 <script> 태그로 불러오는 코드 — 뿐입니다.