ES6 템플릿 문자열로 리터럴 가져오기

Addy Osmani
Addy Osmani

JavaScript의 문자열은 역사적으로 제한되어 있어 Python이나 Ruby와 같은 언어에서 기대할 수 있는 기능이 없습니다. ES6 템플릿 문자열 (Chrome 41 이상에서 사용 가능)은 이를 근본적으로 바꿉니다. 도메인별 언어 (DSL)로 문자열을 정의하는 방법을 도입하여 다음을 개선합니다.

  • 문자열 보간
  • 삽입된 표현식
  • 해킹이 없는 멀티라인 문자열
  • 문자열 형식 지정
  • 안전한 HTML 이스케이프, 현지화 등을 위한 문자열 태그 지정

오늘날 알고 있는 것처럼 문자열에 또 다른 기능을 추가하는 대신 템플릿 문자열은 이러한 문제를 해결하는 완전히 다른 방법을 도입합니다.

구문

템플릿 문자열은 일반 문자열에 익숙한 작은따옴표나 큰따옴표 대신 백틱 (``)을 사용합니다. 따라서 템플릿 문자열은 다음과 같이 작성할 수 있습니다.

var greeting = `Yo World!`;

지금까지 템플릿 문자열은 일반 문자열보다 더 많은 것을 제공하지 않았습니다. 이를 변경해 보겠습니다.

문자열 대체

첫 번째 실질적인 이점 중 하나는 문자열 대체입니다. 대체를 사용하면 유효한 JavaScript 표현식 (예: 변수 추가)을 사용할 수 있으며 템플릿 리터럴 내에서 결과가 동일한 문자열의 일부로 출력됩니다.

템플릿 문자열은 아래와 같이 ${ } 문법을 사용하여 문자열 대체를 위한 자리표시자를 포함할 수 있습니다.

// Simple string substitution
var name = "Brendan";
console.log(`Yo, ${name}!`);

// => "Yo, Brendan!"

템플릿 문자열의 모든 문자열 대체는 JavaScript 표현식이므로 변수 이름 외에도 훨씬 더 많은 항목을 대체할 수 있습니다. 예를 들어 아래에서는 표현식 보간을 사용하여 읽기 쉬운 인라인 수학을 삽입할 수 있습니다.

var a = 10;
var b = 10;
console.log(`JavaScript first appeared ${a+b} years ago. Wow!`);

//=> JavaScript first appeared 20 years ago. Wow!

console.log(`The number of JS MVC frameworks is ${2 * (a + b)} and not ${10 * (a + b)}.`);
//=> The number of JS frameworks is 40 and not 200.

표현식 내 함수에도 매우 유용합니다.

function fn() { return "I am a result. Rarr"; }
console.log(`foo ${fn()} bar`);
//=> foo I am a result. Rarr bar.

${}는 멤버 표현식과 메서드 호출을 비롯한 모든 종류의 표현식과 잘 작동합니다.

var user = {name: 'Caitlin Potter'};
console.log(`Thanks for getting this into V8, ${user.name.toUpperCase()}.`);

// => "Thanks for getting this into V8, CAITLIN POTTER";

// And another example
var thing = 'template strings';
console.log(`Say hello to ${thing}.`);

// => Say hello to template strings

문자열 내부에 백틱이 필요한 경우 다음과 같이 백슬래시 문자 \를 사용하여 이스케이프 처리할 수 있습니다.

var greeting = `\`Yo\` World!`;

여러 줄 문자열

JavaScript의 여러 줄 문자열에는 한동안 해킹된 해결 방법이 필요했습니다. 이러한 문제에 대한 현재 해결 방법은 문자열이 단일 줄에 있거나 각 줄바꿈 앞에 \ (백슬래시)를 사용하여 여러 줄 문자열로 분할되어야 합니다. 예를 들면 다음과 같습니다.

var greeting = "Yo \
World";

이는 대부분의 최신 JavaScript 엔진에서 잘 작동하지만 동작 자체는 여전히 약간의 해킹입니다. 문자열 연결을 사용하여 여러 줄 지원을 가짜로 만들 수도 있지만 이 방법도 마찬가지로 바람직하지 않습니다.

var greeting = "Yo " +
"World";

템플릿 문자열은 여러 줄 문자열을 크게 단순화합니다. 필요한 위치에 줄바꿈을 포함하기만 하면 됩니다. 예를 들면 다음과 같습니다.

백틱 문법 내의 공백도 문자열의 일부로 간주됩니다.

console.log(`string text line 1
string text line 2`);

태그된 템플릿

지금까지 문자열 대체 및 여러 줄 문자열 만들기에 템플릿 문자열을 사용하는 방법을 살펴봤습니다. 태그 템플릿도 강력한 기능 중 하나입니다. 태그가 지정된 템플릿은 템플릿 문자열 앞에 함수 이름을 배치하여 템플릿 문자열을 변환합니다. 예를 들면 다음과 같습니다.

fn`Hello ${you}! You're looking ${adjective} today!`

태그가 지정된 템플릿 문자열의 시맨틱은 일반 템플릿 문자열의 시맨틱과 매우 다릅니다. 본질적으로, 이는 특수한 유형의 함수 호출입니다. 위의 코드는 다음과 같이 '디슈가링'됩니다.

fn(["Hello ", "! You're looking ", " today!"], you, adjective);

(n + 1)번째 인수가 문자열 배열의 n번째 항목과 (n + 1)번째 항목 간에 발생하는 대체에 해당하는 방식을 확인합니다. 이는 다양한 작업에 유용하지만 가장 간단한 방법은 보간된 변수를 자동으로 이스케이프 처리하는 것입니다.

예를 들어 다음과 같이 HTML 이스케이프 함수를 작성할 수 있습니다.

html`<p title="${title}">Hello ${you}!</p>`

적절한 변수가 대체된 문자열을 반환하지만 모든 HTML 안전하지 않은 문자는 대체됩니다. 그렇게 해 봅시다. HTML 이스케이프 함수는 사용자 이름과 댓글이라는 두 가지 인수를 사용합니다. 둘 다 HTML 안전하지 않은 문자 (예: ', ", <, >, &)를 포함할 수 있습니다. 예를 들어 사용자 이름이 'Domenic Denicola'이고 주석이 '& is a fun tag'인 경우 다음을 출력해야 합니다.

<b>Domenic Denicola says:</b> "&amp; is a fun tag"

따라서 태그가 지정된 템플릿 솔루션은 다음과 같이 작성할 수 있습니다.

// HTML Escape helper utility
var util = (function () {
    // Thanks to Andrea Giammarchi
    var
    reEscape = /[&<>'"]/g,
    reUnescape = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g,
    oEscape = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        "'": '&#39;',
        '"': '&quot;'
    },
    oUnescape = {
        '&amp;': '&',
        '&#38;': '&',
        '&lt;': '<',
        '&#60;': '<',
        '&gt;': '>',
        '&#62;': '>',
        '&apos;': "'",
        '&#39;': "'",
        '&quot;': '"',
        '&#34;': '"'
    },
    fnEscape = function (m) {
        return oEscape[m];
    },
    fnUnescape = function (m) {
        return oUnescape[m];
    },
    replace = String.prototype.replace
    ;
    return (Object.freeze || Object)({
    escape: function escape(s) {
        return replace.call(s, reEscape, fnEscape);
    },
    unescape: function unescape(s) {
        return replace.call(s, reUnescape, fnUnescape);
    }
    });
}());

// Tagged template function
function html(pieces) {
    var result = pieces[0];
    var substitutions = [].slice.call(arguments, 1);
    for (var i = 0; i < substitutions.length; ++i) {
        result += util.escape(substitutions[i]) + pieces[i + 1];
    }

    return result;
}

var username = "Domenic Denicola";
var tag = "& is a fun tag";
console.log(html`<b>${username} says</b>: "${tag}"`);
//=> <b>Domenic Denicola says</b>: "&amp; is a fun tag"

자동 이스케이프, 형식 지정, 현지화, 일반적으로 더 복잡한 대체 등 다른 용도로도 사용할 수 있습니다.

// Contextual auto-escaping
qsa`.${className}`;
safehtml`<a href="${url}?q=${query}" onclick="alert('${message}')" style="color: ${color}">${message}</a>`;

// Localization and formatting
l10n`Hello ${name}; you are visitor number ${visitor}:n! You have ${money}:c in your account!`

// Embedded HTML/XML
jsx`<a href="${url}">${text}</a>` // becomes React.DOM.a({ href: url }, text)

// DSLs for code execution
var childProcess = sh`ps ax | grep ${pid}`;

요약

템플릿 문자열은 Chrome 41 베타 이상, IE 기술 미리보기, Firefox 35 이상, io.js에 있습니다. 실제로 오늘날 프로덕션에서 사용하려면 Traceur 및 6to5를 비롯한 주요 ES6 트랜스파일러에서 지원됩니다. 사용해 보려면 Chrome 샘플 저장소에서 템플릿 문자열 샘플을 확인하세요. 오늘날 ES5를 사용하여 문자열 템플릿의 일부 문자열을 가공하는 방법을 보여주는 ES5의 ES6 등가 항목도 참고하세요.

템플릿 문자열은 JavaScript에 여러 가지 중요한 기능을 제공합니다. 여기에는 문자열 및 표현식 보간을 더 효과적으로 수행하는 방법, 여러 줄 문자열, 자체 DSL을 만드는 기능이 포함됩니다.

가장 중요한 기능 중 하나는 태그가 지정된 템플릿으로, 이러한 DSL을 작성하는 데 중요한 기능입니다. 템플릿 문자열의 일부를 인수로 수신하고 문자열과 대체를 사용하여 문자열의 최종 출력을 결정하는 방법을 결정할 수 있습니다.

추가 자료