JavaScript - eval 함수란 무엇이고, 왜 사용하지 말라고 하는가? (eval() is evil)

modolee·2020년 8월 30일
12
post-thumbnail
post-custom-banner

정의

  • 문자로 표현 된 JavaScript 코드를 실행하는 함수
eval(string)
  • 매개변수
    • string : 자바스크립트 표현식, 명령문, 또는 연속되는 다수의 명령문을 나타내는 문자열. 표현식은 이미 존재하는 객체의 변수나 속성을 포함할 수 있음
  • 반환값
    • 주어진 코드를 평가하여 얻은 값. 값이 없다면 undefined를 반환합니다.

기본 사용 예제

console.log(eval('2 + 2'));
// expected output: 4

console.log(eval(new String('2 + 2')));
// expected output: 2 + 2

console.log(eval('2 + 2') === eval('4'));
// expected output: true

console.log(eval('2 + 2') === eval(new String('2 + 2')));
// expected output: false

직접 호출 vs 간접 호출

  • ES5부터는 eval을 직접 호출하지 않고 간접적으로 사용한다면, 지역 범위가 아니라 전역 범위로 동작
function test() {
  var x = 2, y = 4;
  console.log(eval('x + y')); //  직접 호출, 지역 범위 사용, 결과값은 6
  var geval = eval; // ---------- eval을 전역 범위로 호출하는 것과 같음
  console.log(geval('x + y')); // 간접 호출, 전역 범위 사용, `x`가 정의되지 않았으므로 ReferenceError 발생
  (0, eval)('x + y'); // -------- 다른 방식으로 간접 호출
}

eval을 절대 사용하지 말 것! (eval is evil)

  • eval()은 인자로 받은 코드를 caller의 권한으로 수행하는 위험한 함수
  • 악의적인 영향을 받았을 수 있는 문자열을 eval()로 실행한다면, 해당 웹페이지나 확장 프로그램의 권함으로 사용자의 기기에서 악의적인 코드를 수행하는 결과를 초래
  • 제3자 코드가 eval()이 호출된 위치의 스코프를 볼 수 있으며, 이를 이용해 비슷한 함수인 Function으로는 실현할 수 없는 공격이 가능
  • 최신 JS 엔진에서 여러 코드 구조를 최적화하는 것과 달리 eval()은 JS 인터프리터를 사용해야 하기 때문에 다른 대안들보다 느림
    • 최신 자바스크립트 인터프리터는 코드를 기계 코드로 변환함. 즉, 변수명의 개념이 완전히 사라짐
    • eval()을 사용하면 브라우저는 기계 코드에 해당 변수가 있는지 확인하고 값을 대입하기 위해 길고 무거운 변수명 검색을 수행해야 함
    • eval()을 통해 자료형 변경 등 변수에 변화가 일어날 수 있으며, 브라우저는 이에 대응하기 위해 기계 코드를 재작성해야 함

eval을 쓸 필요가 없고, 사용을 지양해야 하는 경우

  • 속성 값 접근

    // eval을 사용한 코드
    var obj = { a: 20, b: 30 };
    var propname = getPropName();  // "a" 또는 "b"를 반환
    
    eval( "var result = obj." + propname );
    
    // eval을 사용하지 않은 코드
    var obj = { a: 20, b: 30 };
    var propname = getPropName();  // "a" 또는 "b"를 반환
    var result = obj[ propname ];  //  obj[ "a" ]는 obj.a와 동일함
  • 코드 수행

    setTimeout(" ... ", 1000) // 코드를 문자열로 넘김
    setTimeout(function() { ... }, 1000); // 함수로 작성해서 넘김
    
    elt.setAttribute("onclick", "...") // 코드를 문자열로 넘김
    elt.addEventListener("click", function() { ... } , false); // 함수로 작성해서 넘김

느낌점

  • 솔직히 eval의 사용 예시를 보면서 eval의 필요성을 전혀 못 느꼈고, 그 동안 프로그램을 만들었던 기억을 되새겨 봐도 '아~ 그때 eval을 이용했다면 편했을 텐데!' 라는 순간이 전혀 떠오르지 않음
  • 하지만 지금의 자바스크립트는 많이 발생 된 상태이기 때문에 eval의 필요성을 못 느끼는 것일 수도 있음. 정말 예전에 자바스크립트를 이용 했었다면 eval을 쓰지 않으면 해결되지 않는 사항들이 있지 않았을까라는 것이 나의 추측

출처

profile
기초가 탄탄한 백엔드 개발자를 꿈꿉니다.
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 12월 18일

옛날에 json같은것들 받을때 쓰이더라고요 보안성때문에 안쓰지만

답글 달기