게으른 개발자의 끄적거림

JavaScript .eval() 함수란? (feat. 쓰면 안되는 이유)

끄적잉 2024. 5. 29. 21:34
반응형

### JavaScript의 `eval()` 함수: 상세 개요 및 사용 금지 이유

JavaScript의 `eval()` 함수는 문자열 형태로 전달된 JavaScript 코드를 실행할 수 있게 해주는 강력한 함수입니다. 이 함수는 JavaScript 언어의 일부로, 특히 동적인 코드 실행이 필요한 경우 유용할 수 있습니다. 그러나 그 사용에는 심각한 보안 및 성능 문제가 따르기 때문에, 대부분의 상황에서 사용이 권장되지 않습니다. 아래에서는 `eval()` 함수의 동작 원리와 문제점에 대해 자세히 살펴보겠습니다.

 


#### 1. `eval()` 함수의 기본 동작

`eval()` 함수는 다음과 같은 형태로 사용됩니다:

```javascript
eval(string);
```

여기서 `string`은 유효한 JavaScript 코드가 포함된 문자열입니다. `eval()`은 이 문자열을 실행하여, 문자열이 표현하는 코드에 따라 결과를 반환합니다.

예를 들어, 다음 코드는 `eval()` 함수를 사용하여 문자열로 표현된 JavaScript 코드를 실행합니다:

```javascript
let x = 10;
let y = 20;
let result = eval("x + y");
console.log(result); // 30
```

위의 코드는 `eval()` 함수를 통해 `x + y`라는 표현식을 실행하여 `result` 변수에 그 결과를 할당합니다.

 

 


#### 2. `eval()` 함수의 활용 예

`eval()` 함수는 주로 다음과 같은 상황에서 사용됩니다:

1. **동적 코드 실행**: 사용자 입력에 따라 동적으로 코드를 생성하고 실행해야 하는 경우.
2. **컴파일러나 인터프리터 구현**: JavaScript 코드를 해석하고 실행해야 하는 도구를 만드는 경우.
3. **기존 코드와의 호환성 유지**: 레거시 시스템에서 동적으로 생성된 코드를 실행해야 하는 경우.

예를 들어, JSON 포맷이 도입되기 전에는 서버에서 받은 데이터를 객체로 변환하기 위해 `eval()`을 사용하기도 했습니다:

```javascript
let jsonData = '{"name": "John", "age": 30}';
let obj = eval('(' + jsonData + ')');
console.log(obj.name); // John
```

그러나 현재는 `JSON.parse()` 함수를 사용하는 것이 표준입니다.

 

 


#### 3. `eval()` 함수의 문제점

`eval()` 함수의 주요 문제점은 보안과 성능에 관한 것입니다. 다음은 각각의 문제에 대한 상세한 설명입니다.

##### 보안 문제

1. **코드 인젝션**: `eval()`은 전달된 문자열을 코드로 실행하므로, 악의적인 사용자가 입력을 조작하여 악성 코드를 실행할 수 있습니다. 예를 들어, 웹 애플리케이션이 사용자 입력을 `eval()`로 실행하면 다음과 같은 상황이 발생할 수 있습니다:

    ```javascript
    let userInput = "alert('Hacked!')";
    eval(userInput); // 이 코드는 사용자 브라우저에서 alert 창을 띄웁니다.
    ```

    만약 사용자가 SQL 인젝션과 유사하게 JavaScript 코드를 삽입할 수 있다면, 이는 심각한 보안 취약점을 초래할 수 있습니다.

 

2. **신뢰할 수 없는 소스**: `eval()`로 실행되는 코드가 신뢰할 수 없는 소스로부터 온다면, 해당 코드가 악의적일 가능성이 큽니다. 이는 데이터 유출, 시스템 손상 등의 심각한 결과를 초래할 수 있습니다.

3. **네임스페이스 오염**: `eval()`은 글로벌 네임스페이스를 오염시킬 수 있습니다. 이는 변수의 충돌을 일으키고, 코드의 예측 가능성을 감소시킵니다.

 

반응형


##### 성능 문제

1. **최적화 방해**: 대부분의 JavaScript 엔진은 코드를 최적화하여 빠르게 실행하도록 설계되어 있습니다. 그러나 `eval()`을 사용하면 엔진이 코드의 내용을 미리 알 수 없기 때문에 최적화를 수행할 수 없습니다.

2. **추가적인 파싱 및 컴파일 비용**: `eval()`은 문자열을 파싱하고 컴파일하는 과정을 거쳐야 합니다. 이는 정적 코드에 비해 추가적인 성능 부담을 초래합니다.

3. **디버깅의 어려움**: `eval()`을 사용한 코드는 디버깅이 어렵습니다. 코드가 문자열로 전달되기 때문에, 디버거가 해당 코드를 제대로 해석하고 추적하기 어렵습니다.

 

 


#### 4. `eval()` 사용을 대체할 수 있는 안전한 방법

위에서 설명한 문제점들을 피하기 위해, `eval()` 함수 대신 다른 방법을 사용하는 것이 좋습니다. 다음은 `eval()`의 안전한 대안들입니다.

##### 동적 코드 실행 대체

동적 코드 실행이 필요한 경우, 가능한 한 정적 코드를 사용하고, 함수나 객체를 통해 동작을 분기하는 방법을 사용합니다:

```javascript
let actions = {
    add: (a, b) => a + b,
    subtract: (a, b) => a - b,
};

let operation = "add";
let result = actions[operation](10, 20);
console.log(result); // 30
```

##### JSON 처리

JSON 데이터를 객체로 변환할 때는 `JSON.parse()` 함수를 사용합니다:

```javascript
let jsonData = '{"name": "John", "age": 30}';
let obj = JSON.parse(jsonData);
console.log(obj.name); // John
```

##### 사용자 입력 검증

사용자 입력을 실행할 필요가 있는 경우, 반드시 입력을 철저히 검증하고 필터링합니다. 또한, 가능한 한 코드 실행을 피하고 안전한 방식으로 데이터를 처리합니다.

##### `Function` 생성자

경우에 따라 동적으로 함수를 생성해야 한다면, `Function` 생성자를 사용할 수 있습니다. 이는 `eval()`보다는 약간 더 안전한 대안이지만, 여전히 위험성이 따릅니다:

```javascript
let func = new Function('a', 'b', 'return a + b');
console.log(func(10, 20)); // 30
```

이 방법은 코드가 독립된 함수 스코프 내에서 실행되므로, 글로벌 네임스페이스 오염을 줄일 수 있습니다.

 


#### 5. 결론

JavaScript의 `eval()` 함수는 그 강력함 때문에 매력적으로 보일 수 있지만, 심각한 보안 및 성능 문제를 초래할 수 있기 때문에 사용을 피해야 합니다. 보안 취약점과 최적화 방해, 그리고 디버깅의 어려움 등을 고려할 때, `eval()` 대신 안전하고 성능이 보장된 대안을 사용하는 것이 좋습니다. 동적 코드 실행이 꼭 필요한 경우에도, 가능한 한 정적 코드로 해결하고, 사용자 입력을 철저히 검증하는 것이 중요합니다.

이러한 이유로 대부분의 JavaScript 개발자들은 `eval()` 사용을 피하고, 대체 방법을 사용하여 보다 안전하고 효율적인 코드를 작성하는 것을 선호합니다.

반응형