시스템아 미안해
Chapter 3 - Item 27. 문자열 보다 클로저로 코드 캡슐화하기를 선호하라 본문
과거 자바스크립트 API 중 일부는 문자열로 코드를 받아서 실행하는 기능
(eval, new Function, setTimeout의 문자열 인자 등) 을 제공했다.
setTimeout("doSomething()", 1000);
new Function("a", "b", "return a + b;")
element.setAttribute("onclick", "alert('clicked')");
이 방식은 내부적으로 eval 과 유사하게 동작한다.
즉, 문자열을 런타임에 파싱·컴파일해서 실행하므로 아래와 같은 문제가 있다.
1. 보안 취약점 (XSS)
- 문자열로 코드를 만들면 외부 입력이 그대로 실행될 수 있다.
- 악의적인 스크립트를 심으면 그대로 브라우저에서 돌아감
2. 성능 저하
매번 문자열을 파싱 → AST(구문 트리)로 변환 → 실행해야 해서 느림.
3. 스코프 예측 불가
- 문자열로 실행된 코드는 정의 당시의 스코프를 기억하지 않는다.
- 항상 전역 컨텍스트나 새로운 실행 컨텍스트에서 실행됨.
- 결과적으로 지역 변수나 this를 전혀 쓸 수 없음.
let msg = "Hello";
setTimeout("console.log(msg)", 1000); // ReferenceError: msg is not defined
그리하여 책에서는 다음과 같이 권장한다.
- 문자열로 코드 전달하지 말 것
- 클로저(함수)로 감싸서 전달할 것 -> 외부 변수를 그대로 캡처하고 실행 환경을 보존할 수 있음
setTimeout(function () {
console.log('Hello');
}, 1000);
여기서 말하는 "클로저"는 정의 당시의 스코프(변수 환경)를 기억하는 함수를 뜻한다.
이렇게 하면 함수가 정의될 때 참조한 지역 변수나 this를 실행 시점에도 그대로 쓸 수 있다.
ES6 이후 화살표 함수로 클로저를 더욱 간결하게 작성 가능하다.
// ES5
setTimeout(function () {
console.log(msg);
}, 1000);
// ES6+
setTimeout(() => console.log(msg), 1000);
화살표 함수는 자신만의 this를 만들지 않고 바깥 스코프의 this를 그대로 사용하기 때문에,
이벤트나 비동기 콜백에서 this가 꼬이는 문제도 줄여준다.
- eval 계열 API와 문자열 실행은 전면 금지
- 클로저 기반 함수 전달이 기본 원칙
- 문자열 실행이 필요한 경우는 없다고 가정하고 설계
'책 > Effective JavaScript' 카테고리의 다른 글
| Chapter 3 - Item 29. 비표준 스택 검사 속성 사용을 피하라 (1) | 2025.08.10 |
|---|---|
| Chapter 3 - Item 28. 함수의 toString() 결과에 의존하지 말라 (1) | 2025.08.10 |
| Chapter 3 - Item 26. bind로 함수를 커링하라 (0) | 2025.08.10 |
| Chapter 3 - Item 25. this를 고정하기 위해 bind로 메서드를 추출하라 (1) | 2025.08.10 |
| Chapter 3 - Item 24. arguments 객체는 변수에 저장해서 사용하라 (1) | 2025.08.09 |