Front-end/React

태그드 템플릿 리터럴

mooyou 2025. 2. 27. 22:50
728x90
300x250
SMALL

태그드 템플릿 리터럴이란?

간단히 말해, 템플릿 리터럴 앞에 함수(예: myTag)를 붙여서 문자열을 가공할 수 있는 기능

const name = "철수";
console.log(myTag`${name}입니다.`);

위 코드에서 myTag는 태그 함수이다.

즉, 템플릿 리터럴을 가공할 함수를 지정하는 것이다.


2. 태그드 템플릿 리터럴 동작 방식

일반적인 템플릿 리터럴(`${name}입니다.`)을 쓰면, 그냥 변수가 문자열에 삽입된다.

하지만 태그 함수가 붙으면, 문자열과 변수를 따로 전달받아 가공할 수 있다.

function myTag(strings, ...values) {
  console.log(strings); // ['','입니다.']
  console.log(values); // ['철수']
}

const name = "철수";
myTag`${name}입니다.`;
  • string: 고정된 문자열 부분이 배열로 전달된다. [' ', '입니다.']
  • values : 삽입된 값들이 배열로 전달된다. ['철수']

즉, 템플릿 리터럴이 문자열 조각(strings) + 변수 값(values)으로 나뉘어 태그 함수로 전달된다.


3. 예제 코드

function highlight(strings, ...values) {
  return strings.reduce((prev, curr, i) =>
    `${prev}<b>${values[i - 1] || ""}</b>${curr}`
  );
}

const name = "철수";
console.log(highlight`${name}입니다.`);

 

highlight 함수 실행 과정

1) highlight(strings, ...values) 실행

템플릿 리터럴 ${name}입니다.가 highlight 함수에 전달된다.

이때, 문자열 부분(strings)과 변수 값(values)이 따로 전달된다.

전달되는 값

strings = ["", "입니다."]; // 템플릿 리터럴의 고정된 문자열 부분
//변수를 기준으로 앞 뒤로 구분 앞에 문자가 없으므로 첫번째 배열은 빈값
values = ["철수"];         // 변수 부분 (name의 값)

 

이렇게 분리되는 이유는 템플릿 리터럴이 태그드 템플릿 함수(highlight)를 만나면, 변수를 따로 추출하기 때문

 

2) string.reduce()실행

reduce()는 string배열을 순회하면서, 문자열을 조립하는 역할을 한다.

 

첫 번째 반복 (i = 0)

prev = ""     // 초기값
curr = ""     // 첫 번째 strings 요소 ("" - 비어 있음)
i = 0
values[i - 1] = values[-1] // values의 -1번째 배열은 존재하지 않으므로 undefined → 빈 문자열 "" 처리됨

 

두 번째 반복 (i = 1)

prev = "<b></b>" //누적 값
curr = "입니다."  // 두 번째 strings 요소 ("입니다.")
i = 1
values[i - 1] = values[0] = "철수"

 

  • 최종 결과: "<b></b><b>철수</b>입니다."

결과적으로 <b>철수</b>입니다. 가 출력된다.

즉, 템플릿 리터럴에서 변수 부분을 <b></b>태그로 감싸주는 코드이다.

 

여기서 앞부분에 <b></b>가 나오는 이유는 첫 번째 string 요소가 빈 문자열("")이기 때문이다.

즉, 변수 앞에 있는 빈 문자열도 <b></b>로 감싸지면서 처음에는 빈<b></b>가 추가된 것이다.

 

올바르게 동작하도록 수정하기

불필요한 빈<b></b>를 없애려면 첫 번째 루프에서 <b></b>태그를 붙이지 않으면 된다.

수정된 코드

function highlight(strings, ...values) {
  return strings.reduce((prev, curr, i) => 
    `${prev}${values[i] !== undefined ? `<b>${values[i]}</b>` : ""}${curr}`
  );
}

const name = "철수";
console.log(highlight`${name}입니다.`);

 

출력

<b>철수</b>입니다.

 


4. 태그드 템플릿 리터럴의 활용

보다 일반적인 활용 예제를 보면 이해하기 쉽다.

1) HTML 생성

템플릿 리터럴을 이용해 HTML을 동적으로 생성할 수 있다.

function html(strings, ...values) {
  return strings.reduce((prev, curr, i) => 
    `${prev}<span style="color: blue;">${values[i - 1] || ""}</span>${curr}`
  );
}

const user = "영희";
const age = 25;
console.log(html`이름: ${user}, 나이: ${age}`);

 

출력

<span style="color: blue;">영희</span>이름: , <span style="color: blue;">25</span>나이:

값에만 색상스타일 변경

 

2) SQL Injection 방지

태그드 템플릿을 활용해 SQL Injection 방지가 가능

function safeQuery(strings, ...values) {
  return strings.reduce((prev, curr, i) => 
    `${prev}${encodeURIComponent(values[i - 1] || "")}${curr}`
  );
}

const userInput = "DROP TABLE users;";
console.log(safeQuery`SELECT * FROM users WHERE name = '${userInput}'`);

 

 

3) 다국어 지원 (i18n)

태그드 템플릿을 이용하면 다국어 지원을 쉽게 처리할 수 있다.

const translations = {
  en: { hello: "Hello", world: "World" },
  ko: { hello: "안녕하세요", world: "세계" },
};

function i18n(strings, ...values) {
  const lang = "ko"; // 현재 언어 설정 (예: 'en' / 'ko')
  return strings.reduce((prev, curr, i) => 
    `${prev}${translations[lang][values[i - 1]] || values[i - 1]}${curr}`
  );
}

console.log(i18n`${"hello"} ${"world"}!`); 
// 출력: "안녕하세요 세계!"
728x90
반응형
LIST