1. 보안성과 처리 방식의 차이
웹 개발에서 JSON 데이터를 객체로 변환할 때 가장 권장되는 방법은 JSON.parse()입니다. 과거에는 eval() 함수를 사용하기도 했으나, 두 방식 사이에는 결정적인 보안적 차이가 존재합니다.
JSON.parse()는 오직 유효한 JSON 형식의 문자열만 해석하며, 구문이 올바르지 않으면 즉시 에러를 발생시킵니다. 반면 eval()은 전달받은 문자열을 일반적인 자바스크립트 코드로 간주하여 실행합니다. 이는 외부에서 유입된 악성 스크립트가 실행될 수 있는 심각한 보안 취약점(XSS 등)을 야기할 수 있습니다.
// eval을 사용한 위험한 사례
const dangerousPayload = "alert('시스템 해킹 시도!')";
eval(dangerousPayload); // 경고창이 실행됨
// JSON.parse를 사용한 안전한 사례
const dataStr = '{"key": "value"}';
const secureObj = JSON.parse(dataStr); // 정상 파싱
// JSON.parse(dangerousPayload); // SyntaxError 발생으로 안전함
위 코드에서 볼 수 있듯이 eval()은 문자열 내부의 코드를 그대로 수행하므로, 신뢰할 수 없는 데이터를 처리할 때 매우 위험합니다. JSON.parse()는 데이터의 구조만 분석하므로 이러한 위험으로부터 안전합니다.
2. 문법적 엄격함과 표현식 처리
JSON.parse()는 엄격한 JSON 표준을 따릅니다. 키(key)와 값(value)은 반드시 쌍따옴표(double quotes)로 감싸야 하며, 연산식이나 함수 호출을 포함할 수 없습니다. 하지만 eval()은 자바스크립트 엔진의 유연성을 그대로 활용하므로 더 넓은 범위의 문자열을 해석할 수 있습니다.
let baseScore = 100;
const rawString = '{"user": "Alice", "score": baseScore + 50}';
// eval은 내부 연산을 수행함
const evalResult = eval('(' + rawString + ')');
console.log(evalResult.score); // 150 출력
// JSON.parse는 연산식을 허용하지 않음
// JSON.parse(rawString); // SyntaxError 발생
실제 서비스 환경에서는 데이터의 무결성을 보장하기 위해 JSON.parse()를 사용하는 것이 원칙입니다.
3. eval() 사용 시 괄호가 필요한 이유
eval()을 사용하여 JSON 형태의 문자열을 파싱할 때는 eval('(' + jsonString + ')')와 같이 소괄호로 감싸주는 기법이 필요합니다. 자바스크립트 엔진은 중괄호 {}를 만나면 이를 객체 리터럴이 아닌 '코드 블록(Statement Block)'으로 오해할 수 있기 때문입니다.
소괄호를 추가하면 중괄호 내부의 내용을 단순한 문장이 아닌 하나의 '표현식(Expression)'으로 강제 변환하여, 결과적으로 자바스크립트 객체를 반환하게 만듭니다.
4. JSON.stringify(): 객체를 문자열로 변환
파싱의 반대 과정인 JSON.stringify()는 자바스크립트 객체를 네트워크 전송이나 저장에 용이한 JSON 포맷의 문자열로 직렬화합니다.
const memberInfo = {
id: "tech_writer",
role: "admin",
active: true
};
const jsonOutput = JSON.stringify(memberInfo);
console.log(jsonOutput);
// 출력 결과: '{"id":"tech_writer","role":"admin","active":true}'
최신 브라우저와 Node.js 환경에서는 JSON.parse()와 JSON.stringify()가 내장 객체로 잘 구현되어 있으므로, 보안 위험이 큰 eval()이나 외부 라이브러리 의존성 없이 표준 메서드를 사용하는 것이 가장 바람직합니다.