JavaScript์์ eval()์ ๋์ฒดํ ์ ์๋ ๋ฐฉ๋ฒ
JavaScript์ eval()์ด ์ํํ ์ด์ ์ new Function()์ผ๋ก ์์ ํ๊ฒ ๋์ฒดํ๋ ๋ฐฉ๋ฒ์ ์ค์ฉ์ ์ธ ์์ ์ ํจ๊ป ์์๋ณด์ธ์. ๋ณด์๊ณผ ์ฑ๋ฅ์ ๋ชจ๋ ์ก๋ ํ!
JavaScript๋ฅผ ์ฌ์ฉํ๋ค ๋ณด๋ฉด ๋ฌธ์์ด๋ก ๋ ์ฝ๋๋ฅผ ์คํํด์ผ ํ ๋๊ฐ ์์ต๋๋ค. ์ด๋ด ๋ ๊ฐ์ฅ ๋จผ์ ๋ ์ค๋ฅด๋ ๊ฒ์ด eval() ํจ์์ฃ . ํ์ง๋ง eval()์ ๋ณด์ ์ทจ์ฝ์ ๊ณผ ์ฑ๋ฅ ๋ฌธ์ ๋ก ์
๋ช
์ด ๋์ต๋๋ค.
์ด ๊ธ์์๋ eval()์ ์ํ์ฑ์ ์ดํด๋ณด๊ณ , ๋ ์์ ํ ๋์์ธ new Function()์ ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์ค์ฉ์ ์ธ ์์ ์ ํจ๊ป ์์๋ณด๊ฒ ์ต๋๋ค.
eval()์ด๋ ๋ฌด์์ธ๊ฐ?
MDN ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด, eval()์ ๋ฌธ์์ด๋ก ํํ๋ JavaScript ์ฝ๋๋ฅผ ์คํํ๋ ํจ์์
๋๋ค. ๊ฐ๋จํ ์์ ๋ฅผ ํตํด ์๋ ๋ฐฉ์์ ์ดํด๋ณผ๊น์?
let a = 3;
let b = 5;
eval('a += ' + b + ' + 2');
console.log(a); // 10
์ ์ฝ๋์์ eval()์ ๋ฌธ์์ด 'a += 5 + 2'๋ฅผ ์ค์ JavaScript ์ฝ๋๋ก ์คํํฉ๋๋ค. ์ผํ ๋ณด๋ฉด ํธ๋ฆฌํด ๋ณด์ด์ง๋ง, ์ด ๋จ์ํจ ๋ค์๋ ์ฌ๊ฐํ ๋ฌธ์ ๋ค์ด ์จ์ด ์์ด์.
eval()์ ๋ณด์ ์ํ์ฑ
eval()์ caller์ ๊ถํ์ผ๋ก ์ฝ๋๋ฅผ ์คํํฉ๋๋ค. ์ด๊ฒ ๋ฌด์จ ์๋ฏธ์ผ๊น์? ๋ง์ฝ ์ฌ์ฉ์ ์
๋ ฅ๊ฐ์ eval()๋ก ์คํํ๋ค๋ฉด, ์
์์ ์ธ ์ฝ๋๊ฐ ๊ทธ๋๋ก ์คํ๋ ์ ์๋ค๋ ๋ป์
๋๋ค.
var userContent = getUserInput(); // ์ฌ์ฉ์๋ก๋ถํฐ ์
๋ ฅ๋ฐ์ ๊ฐ
eval(userContent); // ์ํ!
ํด์ปค๊ฐ "window.location = 'http://malicious-site.com'"์ ๊ฐ์ ์ฝ๋๋ฅผ ์
๋ ฅํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ์ฌ์ฉ์๋ ์
์ฑ ์ฌ์ดํธ๋ก ๋ฆฌ๋ค์ด๋ ํธ๋๊ฑฐ๋, ๋ ์ฌ๊ฐํ ๊ฒฝ์ฐ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๊ฐ ํ์ทจ๋ ์ ์์ต๋๋ค.
๋ํ eval()์ ํธ์ถ๋ ์ค์ฝํ(scope)์ ์ง์ ์ ๊ทผํ ์ ์์ด์. ์ด๋ ๋ก์ปฌ ๋ณ์๋ฅผ ์ฝ๊ฑฐ๋ ์์ ํ ์ ์๋ค๋ ์๋ฏธ์
๋๋ค:
function MyFunc() {
let secretToken = "abc123";
eval('console.log(secretToken); secretToken = "hacked";');
console.log(secretToken); // "hacked"
}
eval()์ ์ฑ๋ฅ ๋ฌธ์
eval()์ JavaScript ์ธํฐํ๋ฆฌํฐ๋ฅผ ์ง์ ํธ์ถํ๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ๋์๋ค๋ณด๋ค ๋๋ฆฝ๋๋ค. ํ๋ JavaScript ์์ง๋ค์ ์ฝ๋๋ฅผ ์ต์ ํํ๋๋ฐ, eval()์ ์ด๋ฌํ ์ต์ ํ๋ฅผ ๋ฐฉํดํฉ๋๋ค. ์์ง์ด ์ด๋ค ์ฝ๋๊ฐ ์คํ๋ ์ง ๋ฏธ๋ฆฌ ์ ์ ์๊ธฐ ๋๋ฌธ์ด์ฃ .
new Function()์ผ๋ก ๋ ์์ ํ๊ฒ
new Function()์ eval()๊ณผ ๋น์ทํ๊ฒ ๋ฌธ์์ด๋ก๋ถํฐ ํจ์๋ฅผ ์์ฑํ์ง๋ง, ํจ์ฌ ๋ ์์ ํฉ๋๋ค. ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ์ดํด๋ณผ๊น์?
const add = new Function('a', 'b', 'return a + b');
console.log(add(2, 3)); // 5
๋ฌธ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
let func = new Function([arg1, arg2, ...argN], functionBody);
์ฌ๊ธฐ์ ์ค์ํ ์ ์ new Function()์ผ๋ก ์์ฑ๋ ํจ์๋ ํญ์ ์ ์ญ ์ค์ฝํ์์ ์คํ๋๋ค๋ ๊ฒ์
๋๋ค. ๋ก์ปฌ ๋ณ์์ ์ ๊ทผํ ์ ์์ด์:
function MyFunc() {
let b = 123;
new Function('console.log(b);')(); // ReferenceError: b is not defined
}
์ด๋ฐ ์ ์ฝ์ด ์คํ๋ ค ๋ณด์์ ๊ฐํํฉ๋๋ค. ์ ์์ ์ธ ์ฝ๋๊ฐ ํจ์ ๋ด๋ถ์ ๋ฏผ๊ฐํ ๋ณ์์ ์ ๊ทผํ๋ ๊ฒ์ ์์ฒ์ ์ผ๋ก ์ฐจ๋จํ๋ ๊ฑฐ์ฃ .
eval()๊ณผ new Function() ๋น๊ตํ๊ธฐ
๋ ๋ฐฉ์์ ํต์ฌ ์ฐจ์ด์ ์ ์ ๋ฆฌํด๋ณผ๊ฒ์.
์คํ ์ปจํ ์คํธ์ ์ค์ฝํ
eval()์ ํ์ฌ ์คํ ์ปจํ
์คํธ์์ ์ฝ๋๋ฅผ ํ๊ฐํฉ๋๋ค:
function testEval() {
let x = 10;
eval('console.log(x); x = 20;');
console.log(x); // 20 - ๋ณ์๊ฐ ์์ ๋จ
}
testEval();
๋ฐ๋ฉด new Function()์ ์ ์ญ ์ปจํ
์คํธ์์๋ง ์คํ๋ฉ๋๋ค:
function testFunction() {
let x = 10;
const func = new Function('console.log(typeof x);'); // "undefined"
func();
console.log(x); // 10 - ๋ณ์๊ฐ ์์ ํ๊ฒ ๋ณดํธ๋จ
}
testFunction();
๋ณด์์ฑ
new Function()์ ์ ํ๋ ์ค์ฝํ ์ ๊ทผ์ ๋ณด์์ ํฐ ์ฅ์ ์
๋๋ค. ๋ก์ปฌ ๋ณ์์ ์ ๊ทผํ ์ ์์ผ๋ฏ๋ก, ์
์์ ์ธ ์ฝ๋๊ฐ ์คํ๋๋๋ผ๋ ํผํด ๋ฒ์๊ฐ ์ ํ์ ์ด์์.
์ค์ ์์ ๋ก ๋ฐฐ์ฐ๊ธฐ
์ค์ ๋ก ์ด๋ป๊ฒ eval()์ new Function()์ผ๋ก ๋์ฒดํ ์ ์์๊น์?
๊ฐ๋จํ ์์ ๊ณ์ฐ
// eval() ์ฌ์ฉ (๊ถ์ฅํ์ง ์์)
const result1 = eval('2 + 3 * 4');
// new Function() ์ฌ์ฉ (๊ถ์ฅ)
const calculate = new Function('return 2 + 3 * 4');
const result2 = calculate();
๋์ ํจ์ ์์ฑ
// ์ฌ์ฉ์๊ฐ ์
๋ ฅํ ํจ์ ๋ณธ๋ฌธ์ผ๋ก ํจ์ ์์ฑ
const functionBody = 'return x * 2';
const double = new Function('x', functionBody);
console.log(double(5)); // 10
์ธ๋ถ ๋ณ์ ์์ ํ๊ฒ ์ ๋ฌํ๊ธฐ
์ ์ญ ๋ณ์๋ new Function()์์๋ ์ ๊ทผ ๊ฐ๋ฅํ์ง๋ง, ๋ ์์ ํ ๋ฐฉ๋ฒ์ ๋งค๊ฐ๋ณ์๋ก ๋ช
์์ ์ผ๋ก ์ ๋ฌํ๋ ๊ฒ์
๋๋ค:
const multiplier = 3;
// ๋งค๊ฐ๋ณ์๋ก ๋ช
์์ ์ ๋ฌ
const multiply = new Function('x', 'multiplier', 'return x * multiplier');
console.log(multiply(5, multiplier)); // 15
JSON ํ์ฑ ๋์
์๊ฒฉํ JSON์ด ์๋ JavaScript ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ํ์ฑํ ๋๋ ํ์ฉํ ์ ์์ด์:
function looseJsonParse(obj) {
return Function('"use strict";return (' + obj + ")")();
}
const result = looseJsonParse("{a:(4-1), b:function(){}, c:new Date()}");
console.log(result.a); // 3
์ธ์ new Function()์ ์ฌ์ฉํด์ผ ํ ๊น?
new Function()์ด ์ ์ฉํ ์๋๋ฆฌ์ค๋ค์ ์ดํด๋ณผ๊ฒ์:
๋์ ์ฝ๋ ์์ฑ
์ค์ ํ์ผ์ด๋ ์ฌ์ฉ์ ์ ๋ ฅ์ ๊ธฐ๋ฐ์ผ๋ก ํจ์๋ฅผ ๋์ ์ผ๋ก ์์ฑํด์ผ ํ ๋ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ์ ์ ํํฐ๋ ์ ๋ ฌ ๋ก์ง์ ๊ตฌํํ ๋์ฃ .
์๋๋ฐ์ค ํ๊ฒฝ
์ ์ญ ์ค์ฝํ์์๋ง ์คํ๋๊ธฐ ๋๋ฌธ์, ํ๋ฌ๊ทธ์ธ ์์คํ ์ด๋ ์ฌ์ฉ์ ์คํฌ๋ฆฝํธ ์คํ ํ๊ฒฝ์ ๋ง๋ค ๋ ์ ํฉํฉ๋๋ค.
์ฑ๋ฅ์ด ์ค์ํ ๊ฒฝ์ฐ
๋ฐ๋ณต์ ์ผ๋ก ์คํ๋๋ ์ฝ๋๋ผ๋ฉด, ํ ๋ฒ new Function()์ผ๋ก ์ปดํ์ผํ ํ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด eval()์ ๋งค๋ฒ ํธ์ถํ๋ ๊ฒ๋ณด๋ค ํจ์จ์ ์
๋๋ค.
์ฃผ์์ฌํญ๊ณผ ํ๊ณ
new Function()๋ ์๋ฒฝํ ํด๊ฒฐ์ฑ
์ ์๋๋๋ค. ์ฌ์ ํ ๋ฌธ์์ด๋ก๋ถํฐ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด๋ฏ๋ก, ์ ๋ขฐํ ์ ์๋ ์
๋ ฅ์ ์ฒ ์ ํ ๊ฒ์ฆํด์ผ ํด์.
๋ํ ์ผ๋ถ ์ฃ์ง ์ผ์ด์ค์์๋ eval()์ด๋ new Function() ๋ชจ๋ ์ ํฉํ์ง ์์ ์ ์์ต๋๋ค. ๊ฐ๋ฅํ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋์์ ๋จผ์ ๊ณ ๋ คํด๋ณด์ธ์:
๊ฐ์ฒด ์์ฑ ์ ๊ทผ ์:
// eval() ์ฌ์ฉ (๋์จ)
const propName = 'username';
const value = eval('user.' + propName);
// ๋ธ๋ผ์ผ ํ๊ธฐ๋ฒ ์ฌ์ฉ (์ข์)
const value = user[propName];
์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ฑ๋ก ์:
// ์ธ๋ผ์ธ ๋ฌธ์์ด (๋์จ)
element.setAttribute("onclick", "handleClick()");
// ์ด๋ฒคํธ ๋ฆฌ์ค๋ (์ข์)
element.addEventListener("click", handleClick);
ํ์ด๋จธ ํจ์ ์ฌ์ฉ ์:
// ๋ฌธ์์ด ์ฝ๋ (๋์จ)
setTimeout("console.log('Hello')", 1000);
// ํจ์ ์ ๋ฌ (์ข์)
setTimeout(() => console.log('Hello'), 1000);
๋ ์์ ํ ์ฝ๋๋ฅผ ํฅํด
eval()์ ํธ๋ฆฌํด ๋ณด์ด์ง๋ง, ๋ณด์๊ณผ ์ฑ๋ฅ ์ธก๋ฉด์์ ์ฌ๊ฐํ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ ์ ์์ต๋๋ค. new Function()์ ์ ์ญ ์ค์ฝํ ์ ํ์ ํตํด ์ด๋ฌํ ์ํ์ ํฌ๊ฒ ์ค์ฌ์ฃผ๋ ๋ ๋์ ๋์์ด์์.
๋ฌผ๋ก ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๋์ ์ฝ๋ ์คํ ์์ฒด๋ฅผ ํผํ๋ ๊ฒ์
๋๋ค. ํ์ง๋ง ๋ถ๊ฐํผํ ์ํฉ์ด๋ผ๋ฉด, new Function()์ ์ ํํ๋ ์
๋ ฅ๊ฐ ๊ฒ์ฆ์ ์ฒ ์ ํ ํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
๋ณด์์ ํํํ ์ ์๋ ์์ญ์ ๋๋ค. ์ฝ๋ ํ ์ค์ด ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์ ์ข์ฐํ ์ ์๋ค๋ ์ ์ ํญ์ ๊ธฐ์ตํ๋ฉด์ ๊ฐ๋ฐํ์๊ธธ ๋ฐ๋๋๋ค :)