Template Literal

김용현·2023년 11월 15일

[FE]

목록 보기
1/1

학습 배경 👨‍🏫

여러 곳에서 Template Literal은 꾸준하게 잘 사용해온 좋은 문자열 표기법입니다. 특히 vanilla Javascript로 렌더링하는 법을 연습할 때나 react의 styled-components를 사용할 때 Template Literal을 정말 많이 사용했습니다.

하지만 Template literal의 정확한 특징을 학습해본 적이 없었습니다. Template Literal은 어떤 기능들을 위해서 사용해야 할까요? 또 어떤 특징이 있기 때문에 Template Literal을 styled-components와 같은 형식으로 사용할 수 있는 걸까요? 이의 내용을 MDN 공식 문서를 기반으로 학습해 보았습니다.

Template Literal 이란?

Template Literal 은 backtick(`)으로 구분된 문자열 리터럴

ES6에서는 템플릿 리터럴(Template literal)이라고 불리는 새로운 문자열 표기법을 도입했습니다.

`string text`

`string text line 1
 string text line 2`

`string text ${expression} string text`

tag `string text ${expression} string text`

템플릿 리터럴은 일반적으로 큰 따옴표(”), 작은 따옴표(’)로 작성되는 문자열과는 다른 특징을 가지고 있고 이를 통해 여러 활용법으로 사용할 수 있습니다.

Multi-line Strings (다중선)

백틱(`)으로 표현된 문자열은 줄바꿈을 인식하고 그대로 표현하게 됩니다.

\n 을 적지 않고, 백틱 내에서 줄바꾼 내용을 그대로 출력할 수 있습니다.

// 아래의 두 코드는 동일한 값을 출력합니다.
console.log("first line 1\nsecond line 2")
console.log(`first line 1
second line 2`)

Expression Interpolation(표현식 삽입법)

표현식(expression)에 일반 문자열을 삽입하는 방법입니다.

${변수}의 표현을 통해 백틱(`) 안의 표현식에 변수의 값을 문자열로 넣어줄 수 있습니다.

표현식 삽입법을 활용하면 복잡한 문자 간의 연산 없이 변수를 넣은 문자열을 만들 수 있습니다.

var a = 5;
var b = 10;

// (")을 사용한 일반 표현법
console.log("Fifteen is " + (a + b) + " and\nnot" + (2 * a + b) + ".")

// (`)을 사용한 표현볍
console.log(`Fifteen is ${a + b} and
not ${2 * a + b).`);

Nesting Templates (중첩 템플릿)

Template Literal을 중첩하여 문자열을 표현함으로써, 읽고 쓰기 쉬운 코드를 작성하게 해줍니다.

${변수}의 변수에서 Template Literal을 작성함으로 중첩된 Template Literal을 작성할 수 있습니다.

// ES5 방식
var classes = "header"
classes += isLargeScreen()
    ? ""
    : item.isCollapsed
    ? " icon-expander"
    : " icon-collapser";

// ES2015, 중첩 없는 템플릿 리터럴
const classes = `header ${
    isLargeScreen() ? "" : item.collapsed ? "icon-expander" : "icon-collapser"
}`;

// ES2015, 중첩 템플릿 리터럴
const classes = `header ${
    isLargeScreen() ? "" : `icon-${item.collapsed ? "expander" : "collapser}`
}`;

Tagged templates

Tagged templates는 template literal의 더 발전한 형태입니다.

태그 함수는 parameter로 (”문자열의 배열”, 표현식 변수1, 표현식 변수2, …)의 값을 받아 내부에서 값을 연산하여 반환하게 됩니다.

  • 문자열의 배열 : 백틱 내 문자열을 ${변수} 로 잘라내어 만들어낸 배열
  • 표현식 변수 : ${변수}의 값으로 백틱 내 존재하는 만큼 표현식 변수가 존재
var hello = 11;
var world = "hello world";

function tagExample(strings, variable1, variable2) {
    var str0 = strings[0];
    var str1 = strings[1];
    var str2 = strings[2];
		// strings = ["this is ", " and ", " test"]
		
		var example;
		if (variable1 > 10) {
				example = "A"
    } else {
		    example = "B"
		}
		// variable1 : hello = 11
		// variable2 : world = "hello world

		return str0 + varibale2 + str1 + example + str2
}

var output = tagExample`this is ${hello} and ${world} test`

console.log(output)
// this is world and hello A test

태그 함수는 문자열 뿐만 아니라 함수와 같은 어떤 것이라도 반환할 수 있습니다.

  • 저희가 styled-components를 사용할 때 자주 사용하는 패턴입니다.
  • styled-components는 template literal로 작성한 style을 적용한 tag 생성 함수를 반환해주는 원리
// 함수를 반환
function template(strings, ...keys) {
  return function (...values) {
    var dict = values[values.length - 1] || {};
    var result = [strings[0]];
    keys.forEach(function (key, i) {
      var value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result.join("");
  };
}

var t1Closure = template`${0}${1}${0}!`;
t1Closure("Y", "A"); // "YAY!"
var t2Closure = template`${0} ${"foo"}!`;
t2Closure("Hello", { foo: "World" }); // "Hello World!"

Raw strings

템플릿의 raw() property를 사용한다면 escape sequence를 처리하지 않은 값 자체에 접근할 수 있습니다.

function tag(strings) {
	console.log(strins.raw[0]
}

tag`string text 1\n string line 2`;
// string text 1\n string line 2 이 출력된다.
// \n이 줄바꿈 처리 되지 않고 단어 그 자체로 출력

학습 후기

Template Literal은 그저 변수를 포함한 String을 동적으로 표현하기 좋은 문자열 표현 방식으로만 알고 있었습니다. 하지만 Tagged Templates라는 함수로의 활용 방식을 통해, 사용자들이 쉽게 구현할 수 있는 함수들을 만들기 좋은 방식이라는 것을 배울 수 있었습니다.(Styled-components라던가) 한번 기회가 된다면 Tagged Templates을 적절한 방식으로 활용해봐야 겠습니다.

참고 자료

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
https://poiemaweb.com/es6-template-literals

profile
함께 일하고 싶은 개발자가 되기위해 노력 중입니다.

0개의 댓글