템플릿 문자열(template literal)은 따옴표 대신 백틱(backtick)으로 감싼 문자열입니다. ${} 자리에 이름이나 식의 값이 들어가고, 수를 꾸밀 때는 toLocaleString()으로 천 단위 쉼표를, toFixed()로 소수 자리를 맞춘 글자를 만듭니다.
'커피 2잔' 같은 문구를 +로 만들면 item + ' ' + qty + '잔'처럼 따옴표와 기호가 늘어 읽기 어렵고, 빈칸 하나를 빠뜨리기 쉽습니다.
템플릿 문자열은 찍을 글을 한 덩어리로 쓰고 값이 들어갈 자리만 ${}로 비워 둡니다. 영수증처럼 모양이 정해진 출력을 쓸 때 가장 많이 씁니다. 자료에 따라 템플릿 리터럴이라고도 부릅니다.
이 단원(문자열 다루기)을 이미 안다면 단원 연습 문제부터 풀고 틀린 레슨만 보세요. 건너뛸지 볼 때는 힌트를 펴지 않고 풉니다.
파이썬을 배웠다면 — 이 단원에서 다른 곳
파이썬을 배웠다면 이 단원에서 다른 곳: f-문자열 대신 백틱과 $를 쓰고, $를 빼면 {item}원이 그대로 찍힙니다 — 이 레슨. s[-1]은 끝 글자가 아니라 undefined이고, 끝 글자는 s.at(-1)입니다 — 인덱스와 자르기.
1백틱과 값이 들어가는 자리
백틱(`)은 자판 왼쪽 위, 숫자 1 왼쪽 키로 칩니다.
Mac에서 한글 입력 상태로 치면 ₩가 쳐질 수 있으니 영문 입력으로 바꿔(한/영 전환) 칩니다. ₩로 감싸면 '알 수 없는 글자'라는 문법 오류(Invalid or unexpected token)로 멈춥니다.
백틱으로 감싼 문자열 안의 ${item}은 글자 그대로 찍히지 않고, 그 자리에 이름 item이 붙은 값이 들어갑니다. ${} 밖은 쓴 글자 그대로입니다.
const item = '커피';
const qty = 2;
const msg = `${item} ${qty}잔`;
console.log(msg);
console.log(`${4000 * qty}원`);
커피 2잔
8000원3번 줄의 템플릿 문자열은 실행되는 순간 '커피 2잔'이라는 문자열 하나가 되고, 이름 msg가 그 값에 붙습니다(규칙 2). qty는 수량(quantity)을 줄인 이름이고, 수 2도 String() 없이 글자로 적혀 들어갑니다.
${} 안에는 식도 쓸 수 있습니다. 5번 줄의 4000 * qty는 먼저 8000으로 계산된 뒤 그 자리에 들어갑니다.
그림에서 본 것처럼 작은따옴표나 큰따옴표로 감싼 문자열의 ${}는 쓴 그대로의 글자입니다. 값을 채우는 것은 백틱일 때뿐입니다.
닫는 백틱을 빠뜨리면 그 뒤의 글이 모두 템플릿 안 글자로 읽힙니다.
const item = '커피';
console.log(`${item}원);
console.log('끝');
main.js:4 SyntaxError: Unexpected end of inputUnexpected end of input은 '뜻밖에 입력이 끝났다', 곧 열린 백틱을 닫기 전에 파일이 끝났다는 뜻입니다. 그래서 자리 main.js:4가 세 줄짜리 파일의 끝을 가리킵니다. 파일 끝에 줄바꿈이 없으면 마지막 줄 번호 main.js:3과 그 줄 코드가 찍히는데, 어느 쪽이든 파일의 끝을 가리킵니다.
빠뜨린 곳은 2번 줄인데 오류 자리는 파일 끝이니, 이 오류를 보면 위로 올라가며 닫히지 않은 백틱이나 따옴표를 찾습니다. 문법 오류라 1번 줄도 실행되지 않고 '끝'도 찍히지 않습니다.
2천 단위 쉼표: toLocaleString()
수 뒤에 .toLocaleString()을 붙이면 천 단위마다 쉼표를 찍은 새 문자열이 나옵니다.
const n = 14500;
const won = n.toLocaleString();
console.log(won);
console.log(`합계 ${won}원`);
console.log(n);
14,500
합계 14,500원
14500won은 글자 '14,500'에 붙고, n은 그대로 수 14500에 붙어 있습니다. toLocaleString()은 꾸민 글자를 새로 만들 뿐, 수를 바꾸지 않습니다.
쉼표 모양은 컴퓨터의 언어 설정을 따릅니다. 한국어·영어 설정에서는 14,500이지만, 독일어 설정이면 14.500처럼 찍힙니다. 어느 컴퓨터에서나 같은 모양이 필요하면 n.toLocaleString('ko-KR')처럼 언어를 적습니다.
이 과목의 다른 레슨은 코드 줄을 짧게 두려고 금액을 쉼표 없이 찍습니다(14500원).
3소수 자리: toFixed()
toFixed(1)은 소수 첫째 자리까지 반올림한 글자를 만듭니다. 세 사람이 준 별점의 합이 14점일 때의 평균을 찍어 봅니다. 4번 줄은 무엇을 찍을까요?
const avg = 14 / 3;
const text = avg.toFixed(1);
console.log(text);
console.log(text + 1);
실행 결과 보기
4.7
4.71예상과 다르면 그곳이 배울 곳입니다. toFixed()가 돌려주는 것은 수가 아니라 글자 '4.7'입니다. 그래서 4번 줄의 +는 1을 이어 붙여 '4.71'을 만듭니다.
avg는 그대로 4.666…에 붙어 있습니다. 계산은 수인 avg로 하고, toFixed()는 찍기 바로 앞에서 씁니다.
끝자리가 5인 값은 학교에서 배운 반올림과 다르게 찍히기도 합니다. (1.45).toFixed(1)은 '1.5'가 아니라 '1.4'입니다. 1.45가 컴퓨터 안에서는 2진수로 담겨 1.4499…에 가까운 값이기 때문입니다.
예제
글자를 수로: Number와 NaN 레슨의 '글을 수로 바꿔 계산'을 템플릿 문자열로 찍습니다. 글 받기 → 수로 바꾸기 → 계산하기 → 찍기 네 걸음은 같고, 찍기 줄만 바뀝니다.
const price = 4000;
// 1. 글 받기
const text = '3';
// 2. 수로 바꾸기
const qty = Number(text);
// 3. 계산하기
const total = price * qty;
// 4. 찍기
console.log(`커피 ${qty}잔`);
console.log(`합계 ${total}원`);
커피 3잔
합계 12000원9번 줄은 ${qty} 자리에 3을, 10번 줄은 ${total} 자리에 12000을 넣습니다. 둘 다 수지만 String()이 필요 없습니다.
자주 틀리는 곳
틀린 생각: ${}로 감싸기만 하면 그 자리에 값이 들어간다.
값이 들어갈 자리를 ${}로 표시하니 그것만 기억하기 쉽지만, 작은따옴표 문자열에서는 ${}도 쓴 글자 그대로입니다. item이 '커피'여도 '${item}원'은 ${item}원을 찍고, 백틱으로 감싼 것만 '커피원'을 찍습니다.
맞는 규칙: 자바스크립트는 백틱으로 감싼 문자열에서만 ${} 자리를 값으로 채웁니다. 값을 넣으려면 감싼 따옴표가 백틱인지부터 봅니다.
틀린 생각: toFixed()는 수를 돌려준다.
(0.1 + 0.2).toFixed(2)가 꼬리 없는 0.30을 찍으니 수를 다듬은 것 같지만, 돌려주는 값은 글자입니다.
const sum = 0.1 + 0.2;
const text = sum.toFixed(2);
console.log(text);
console.log(typeof text);
0.30
string글자라서 3절처럼 +를 만나면 이어 붙이기가 됩니다.
맞는 규칙: toFixed()·toLocaleString()은 수를 꾸민 새 문자열을 돌려줍니다. 계산은 꾸미기 전의 수로 하고, 꾸미기는 찍기 바로 앞에서 합니다.
틀린 생각: 백틱 안에서 줄을 바꿔 쓰면 코드만 보기 좋게 나뉜다.
긴 문구를 두 줄로 나눠 적으면 코드만 나뉠 것 같지만, 백틱 안의 줄바꿈은 그대로 문자열의 글자가 됩니다.
const item = '커피';
const receipt = `주문
${item} 2잔`;
console.log(receipt);
주문
커피 2잔2~3번 줄은 한 문장이고, '주문' 뒤의 줄바꿈이 글자로 들어가 두 줄로 찍힙니다.
맞는 규칙: 백틱 안의 줄바꿈은 \n처럼 문자열 속 줄바꿈 글자 하나가 됩니다. 한 줄로 찍을 문구는 백틱 안에서 줄을 바꾸지 않습니다.
확인 문제
1. 예제의 3번 줄을 const text = '12';로 바꿨습니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
const price = 4000;
// 1. 글 받기
const text = '12';
// 2. 수로 바꾸기
const qty = Number(text);
// 3. 계산하기
const total = price * qty;
// 4. 찍기
console.log(`커피 ${qty}잔`);
console.log(`합계 ${total}원`);
힌트
4000 곱하기 12를 먼저 계산하고, 그 값이 들어가는 ${} 자리를 찾으세요.
정답
커피 12잔
합계 48000원12잔이면 48000이고, ${total} 자리에 그대로 들어갑니다. 쉼표를 찍는 toLocaleString()을 쓰지 않았으니 48000입니다.
흔한 오답은 합계 48,000원입니다. 템플릿 문자열이 저절로 쉼표를 찍는다고 본 것입니다.
2. 예제의 '4. 찍기' 둘째 줄에서 ${} 자리를 비웠습니다. 3을 넣은 글이면 합계 12000원이 찍히도록 빈칸을 채우세요.
const price = 4000;
// 1. 글 받기
const text = '3';
// 2. 수로 바꾸기
const qty = Number(text);
// 3. 계산하기
const total = price * qty;
// 4. 찍기
console.log(`커피 ${qty}잔`);
console.log(`합계 ____원`);
힌트
어느 이름의 값을 넣을지 정하고, 값을 넣는 자리의 꼴($와 중괄호)을 떠올려 보세요.
정답
${total}입니다. 채우면 예제와 같은 코드가 되어 합계 12000원이 찍힙니다.
${price * qty}처럼 같은 값을 내는 식을 넣어도 맞습니다. 12000을 직접 써도 이 글에서는 같은 화면이 찍히지만, 3번 줄의 글을 바꿔도 늘 12000이 찍힙니다.
흔한 오답은 {total}입니다. $를 빠뜨리면 오류 없이 합계 {total}원이 글자 그대로 찍힙니다.
3. 사흘 동안 걸은 걸음 수 n을 쉼표로 꾸미고 하루 평균을 찍습니다. 한국어 설정의 컴퓨터에서 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
const n = 12350;
const text = n.toLocaleString();
const avg = (n / 3).toFixed(1);
console.log(`${text}걸음`);
console.log(`하루 ${avg}걸음`);
힌트
꾸미기는 줄마다 따로 정합니다. 3번 줄에는 쉼표를 찍는 toLocaleString()이 없습니다.
정답
12,350걸음
하루 4116.7걸음2번 줄은 쉼표를 찍어 '12,350'입니다. 3번 줄의 평균은 4116.666…이고, toFixed(1)이 소수 첫째 자리까지 반올림해 '4116.7'입니다. toLocaleString()을 쓰지 않았으니 4116에는 쉼표가 없습니다.
흔한 오답은 둘째 줄의 하루 4116.6걸음입니다. toFixed()가 소수점 아래를 버린다고 본 것입니다.
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
1절의 코드(다섯 줄)를 main.js에 저장해 돌립니다. 그다음 3번 줄의 백틱 둘을 작은따옴표로 바꾸면 4번 줄이 무엇을 찍을지 먼저 적고, 바꿔 돌려서 맞춰 봅니다.
저장하고 돌리는 법은 내 컴퓨터에서 돌려 보기에 있습니다.