Skip to content

Latest commit

 

History

History
153 lines (117 loc) · 5.48 KB

File metadata and controls

153 lines (117 loc) · 5.48 KB

Safe Template String Parser

이 라이브러리는 안전하고 유연한 템플릿 문자열 파싱 및 평가 기능을 제공합니다. 복잡한 수학 표현식, 변수 참조, 함수 호출, 배열 인덱싱 등을 지원하며, eval() 또는 new Function()을 사용하지 않아 보안상 안전합니다.

설치

npm을 통한 설치

npm install safe-template-parser

직접 다운로드

최신 릴리스에서 safe-template-parser.min.js 파일을 다운로드하여 프로젝트에 포함할 수 있습니다.

주요 기능

  • 변수 참조 및 중첩 객체 속성 접근
  • 배열 인덱싱 및 배열 요소의 속성 접근
  • 기본 산술 연산 (+, -, *, /, %, ^)
  • 비교 연산 (==, !=, <, <=, >, >=, ===, !==)
  • 논리 연산 (&&, ||, !)
  • 삼항 연산자 (? :)
  • 배열 리터럴 및 객체 리터럴
  • 내장 함수 호출 (min, max, abs, round, floor, ceil)
  • 사용자 정의 함수 호출 지원 (화이트리스트 방식)
  • 괄호를 사용한 복잡한 표현식
  • 안전한 평가 (no eval, no new Function)

사용 방법

1. 라이브러리 가져오기

// ESM
import { parseTemplateString } from 'safe-template-parser';

// CommonJS
const { parseTemplateString } = require('safe-template-parser');

2. 템플릿 문자열 정의

템플릿 문자열 내에서 {{ }} 를 사용하여 표현식을 작성합니다.

const template = "안녕하세요, {{name}}님. 당신의 나이는 {{age}}세이고, {{address.city}}에 살고 계시네요. " +
                 "5년 후의 나이는 {{age + 5}}세입니다. " +
                 "나이의 제곱근은 {{round(abs(age) ^ 0.5)}}입니다. " +
                 "첫 번째 친구의 이름은 {{friends[0].name}}이고, " +
                 "가장 나이 많은 친구는 {{max(friends[0].age, friends[1].age)}}세입니다. " +
                 "사용자 정의 함수 결과: {{customFunc(age)}}세입니다. " +
                 "복잡한 계산: {{complexCalc(age, 10)}}입니다.";

3. 데이터 객체 및 허용된 함수 준비

템플릿에서 사용할 변수들을 포함하는 데이터 객체와, 템플릿에서 호출을 허용할 함수들을 포함하는 allowedFunctions 객체를 준비합니다.

const data = {
  name: "홍길동",
  age: 30,
  address: {
    city: "서울"
  },
  friends: [
    { name: "김철수", age: 28 },
    { name: "이영희", age: 32 }
  ]
};

// 템플릿에서 호출을 허용할 사용자 정의 함수들을 정의합니다.
// 이 객체에 명시적으로 정의된 함수만 템플릿 내에서 호출될 수 있습니다.
const allowedFunctions = {
  customFunc: (age) => age * 1.5,
  complexCalc: (a, b) => (a + b) * 2,
  // 여기에 안전하다고 판단되는 다른 함수들을 추가합니다.
};

4. 템플릿 파싱 및 결과 출력

parseTemplateString 함수를 사용하여 템플릿을 파싱하고 결과를 출력합니다. allowedFunctions 객체를 세 번째 인자로 전달합니다.

const result = parseTemplateString(template, data, allowedFunctions);
console.log(result);

지원되는 연산자 및 함수

연산자

  • 덧셈: +
  • 뺄셈: -
  • 곱셈: *
  • 나눗셈: /
  • 모듈로(나머지): %
  • 거듭제곱: ^
  • 비교: ==, !=, <, <=, >, >=, ===, !==
  • 논리: &&, ||, !
  • 삼항 연산자: ? :

내장 함수

  • min(a, b, ...): 최솟값 반환
  • max(a, b, ...): 최댓값 반환
  • abs(x): 절댓값 반환
  • round(x): 반올림
  • floor(x): 내림
  • ceil(x): 올림

사용자 정의 함수 (보안 강화)

parseTemplateString 함수에 세 번째 인자로 allowedFunctions 객체를 전달하여 템플릿 내에서 호출할 수 있는 사용자 정의 함수를 명시적으로 허용합니다. data 객체에 포함된 함수는 더 이상 템플릿에서 직접 호출되지 않습니다. 이는 임의 코드 실행을 방지하여 보안을 강화합니다.

// 템플릿에서 호출을 허용할 함수 목록
const mySafeFunctions = {
  greet: (name) => `Hello, ${name}`,
  calculate: (x, y) => x * y,
};

const data = { userName: "Alice" };
const template = "{{ greet(userName) }}. Result: {{ calculate(5, 10) }}";

// parseTemplateString 호출 시 allowedFunctions를 전달
const result = parseTemplateString(template, data, mySafeFunctions);
console.log(result); // 출력: "Hello, Alice. Result: 50"

배열 및 객체 접근

  • 배열 인덱싱: array[index] (범위를 벗어나면 undefined 반환)
  • 객체 속성 접근: object.property (존재하지 않으면 undefined 반환)
  • 배열 요소의 속성 접근: array[index].property

주의사항

  • 템플릿 내의 표현식은 {{ }} 안에 작성해야 합니다.
  • 존재하지 않는 변수를 참조하면 오류가 발생합니다.
  • allowedFunctions에 명시적으로 등록되지 않은 함수는 템플릿 내에서 호출할 수 없습니다. data 객체에 함수를 포함하더라도 실행되지 않습니다.
  • 잘못된 형식의 숫자 리터럴 (예: 1.2.3)은 파싱 오류를 발생시킵니다.

에러 처리

파싱 또는 평가 중 오류가 발생하면, 콘솔에 오류 메시지가 출력되고 원래의 표현식이 그대로 반환됩니다.

const template = "잘못된 표현식: {{ nonexistent_function() }}";
const result = parseTemplateString(template, {});
// 결과: "잘못된 표현식: {{ nonexistent_function() }}"
// 콘솔에 오류 메시지 출력