따옴표 구성

따옴표 구성 (Quoting constructs)

Raku에서 문자열이나 단어 목록을 쓸 때 따옴표는 거의 피할 수 없는 부분이에요. 그런데 Raku의 따옴표는 Q, q, qq처럼 문자 하나 차이로 보간 여부가 갈리고, 단어 목록도 qw/qww/qqw처럼 미세하게 구분돼요. 실수하기 쉬운 부분이 많아서 이 문서로 정리해요.

출처: Raku 공식 문서 — Quoting constructs

본문

Raku 코드에서 문자열은 보통 어떤 형태의 따옴표 구성으로 표현돼요. 가장 최소주의적인 것은 Q인데, 단축키 「…」로 쓰거나 Q 뒤에 여러 <유니코드 페어>를 포함한 어떤 델리미터 페어든 쓸 수 있어요. 그래도 대부분의 경우 필요한 건 '…'"…"이며, 자세한 내용은 다음 섹션에서 다뤄요.

정규식에 적용되는 따옴표에 대한 정보는 <정규식 문서>를 보세요.

리터럴 문자열: Q

say Q[A literal string];
say 「More plainly.」;
say Q^Almost any non-word character can be a delimiter!^;
say Q「「Delimiters can be repeated/nested if they are adjacent.」」;
say Q⦅Quoting with fancy unicode pairs⦆;

델리미터는 중첩될 수 있지만, 기본 Q 형태에서는 백슬래시 이스케이프가 허용되지 않아요. 즉 기본 Q 문자열은 가능한 한 리터럴이에요.

Q, q, qq 직후에는 일부 델리미터가 허용되지 않아요. <식별자>에 허용되는 문자는 사용할 수 없어요. 그런 경우 따옴표 구성이 그 문자들과 함께 식별자로 해석되기 때문이에요. 또한 ( )는 함수 호출로 해석되므로 허용되지 않아요. 그래도 그 문자들을 델리미터로 쓰고 싶다면 Q·q·qq와 공백으로 분리하세요. 일부 자연어는 문자열의 오른쪽에 왼쪽 델리미터 따옴표를 사용한다는 점에 주의하세요. Q는 왼쪽·오른쪽 델리미터를 구분하기 위해 유니코드 속성에 의존하므로 이런 것을 지원하지 않아요.

Q'this will not work!'
Q(this won't work either!)

위 예들은 오류를 만들어요. 하지만 다음은 동작해요.

Q (this is fine, because of space after Q)
Q 'and so is this'
Q<Make sure you <match> opening and closing delimiters>
Q{This is still a closing curly brace → \}

이 예들은 다음을 만들어요:

this is fine, because of space after Q
and so is this
Make sure you <match> opening and closing delimiters
This is still a closing curly brace → \

따옴표 구성의 동작은 부사(adverb)로 수정할 수 있는데, 자세한 내용은 이후 섹션에서 설명해요.

짧은 의미
:x :exec 명령으로 실행하고 결과 반환
:w :words 결과를 단어로 분할 (따옴표 보호 없음)
:ww :quotewords 결과를 단어로 분할 (따옴표 보호 포함)
:q :single \\, \qq[...]을 보간하고, 델리미터를 \로 이스케이프
:qq :double :s, :a, :h, :f, :c, :b로 보간
:s :scalar $ 변수 보간
:a :array @ 변수 보간 (postcircumfix가 뒤따를 때)
:h :hash % 변수 보간 (postcircumfix가 뒤따를 때)
:f :function & 호출 보간
:c :closure {...} 표현식 보간
:b :backslash 백슬래시 이스케이프(\n, \qq, \$foo 등) 활성화
:to :heredoc 결과를 heredoc 종결자로 파싱
:v :val 가능하면 allomorph로 변환

이 부사들은 Q와 함께 사용할 수 있어서, 따옴표 연산자가 보간하지 않아도 보간하게 할 수 있어요:

my %þ = :is-mighty;
say Q "Þor %þ<>";                         # OUTPUT: «Þor %þ<>␤»
say Q:h"Þor %þ<>";                        # OUTPUT: «Þor is-mighty   True␤»
%þ = :42foo, :33bar;
say Q:h:c "Þor %þ<> →  { [+] %þ.values}"; # OUTPUT: «Þor bar 33␤foo  42 →  75␤»
my @þ= <33 44>; say Q:a "Array contains @þ[]"; # OUTPUT: «Array contains 33 44␤»
say Q:v<33> + 3;                          # OUTPUT: «36␤»

기본적으로, 그리고 위에 보인 대로, Q는 따옴표 문자열을 어떤 종류의 변환 없이 직접 따옴표 처리해요. 부사가 그 동작을 수정해서, 예를 들어 문자열을 allomorph로 바꾸거나(:v 부사), 해시(:h)나 {} 코드 섹션(:c)의 보간을 허용해요. 배열과 해시는 뒤에 postcircumfix가 와야 해요. 즉 시길 붙은 식별자만으로는 보간되지 않고, 뒤에 인덱싱, decont 연산자, 괄호가 있는 메서드 호출이 오면 보간돼요:

my @þ= <33 44>;
say Q:a "Array contains @þ.elems()"; # OUTPUT: «Array contains 2␤»

괄호 없이 같은 코드는 postcircumfix 연산자가 없으므로 그냥 보간되지 않아요.

이스케이프: q

'Very plain';
q[This back\slash stays];
q[This back\\slash stays]; # 출력 동일
q{This is not a closing curly brace → \}, but this is → };
Q :q $There are no backslashes here, only lots of \$\$\$!$;
'(Just kidding. There\'s no money in that string)';
'No $interpolation {here}!';
Q:q!Just a literal "\n" here!;

q 형태는 백슬래시로 문자열을 끝낼 문자를 이스케이프하게 해요. 백슬래시 자체도 이스케이프할 수 있어요(위 세 번째 예). 보통 형태는 '…' 또는 델리미터가 뒤따르는 q지만, 위 다섯 번째·마지막 예처럼 Q의 부사로도 쓸 수 있어요.

이 예들은 다음을 만들어요:

Very plain
This back\slash stays
This back\slash stays
This is not a closing curly brace → } but this is →
There are no backslashes here, only lots of $$$!
(Just kidding. There's no money in that string)
No $interpolation {here}!
Just a literal "\n" here

\qq[...] 이스케이프 시퀀스는 문자열의 일부에 <qq 보간>을 활성화해요. []가 아닌 다른 델리미터도 쓸 수 있어요. HTML 마크업이 관련될 때 각괄호가 해시 키로 해석되는 것을 피하려면 q-따옴표 문자열을 이 이스케이프 시퀀스와 결합해 쓰면 편리해요:

my $var = 'foo';
say '<code>$var</code> is <var>\qq[$var.uc()]</var>';
# OUTPUT: «<code>$var</code> is <var>FOO</var>␤»

보간: qq

my $color = 'blue';
say "My favorite color is $color!"; # OUTPUT: «My favorite color is blue!␤»

qq 형태 — 보통 이중 따옴표로 씀 — 는 백슬래시 이스케이프 시퀀스(q:backslash처럼), 모든 시길 붙은 변수(q:scalar:array:hash:function처럼), 그리고 {...} 안의 모든 코드(q:closure처럼)의 보간을 허용해요.

변수 보간

qq-따옴표 문자열 안에서 시길이 있는 변수를 사용하면 변수 값의 보간이 일어나요. $ 시길이 있는 변수는 (이스케이프되지 않는 한) 나타날 때마다 보간돼요. 그래서 위 예에서 "$color"blue가 됐어요.

다른 시길을 가진 변수는 적절한 후위(postfix)를 뒤에 붙였을 때만 보간을 일으켜요 (배열은 [], 해시는 {}<>«», sub는 ()). 이 덕분에 @raku 변수를 보간하지 않고 "[email protected]" 같은 표현식을 쓸 수 있어요.

배열(또는 다른 변수)을 보간하려면 변수 이름에 []를 붙여요:

my @neighbors = "Felix", "Danielle", "Lucinda";
say "@neighbors[] and I try our best to coexist peacefully."
# OUTPUT: «Felix Danielle Lucinda and I try our best to coexist peacefully.␤»

[] 대신 메서드 이름 뒤에 괄호가 있는 메서드 호출로 배열을 보간할 수도 있어요. 그래서 다음 코드는 동작해요:

say "@neighbors.join(', ') and I try our best to coexist peacefully."
# OUTPUT: «Felix, Danielle, Lucinda and I try our best to coexist peacefully.␤»

하지만 "@example.com"@example.com을 만들어요.

서브루틴을 호출하려면 & 시길을 쓰고 서브루틴 이름 뒤에 괄호를 붙여요.

say "uc  'word'";  # OUTPUT: «uc  'word'»␤
say "&uc 'word'";  # OUTPUT: «&uc 'word'»␤
say "&uc('word')"; # OUTPUT: «WORD»␤
# OUTPUT: «abcDEFghi␤»

해시(또는 다른 변수)를 보간하려면 <> postcircumfix 연산자를 사용해요.

my %h = :1st; say "abc%h<st>ghi";
# OUTPUT: «abc1ghi␤»

qq가 변수를 보간하는 방식은 q:scalar:array:hash:function과 같아요. 다른 qq 보간을 켜지 않고 변수만 보간하려면 이 부사들(또는 짧은 형태 q:s:a:h:f)을 쓸 수 있어요.

클로저 보간

qq의 또 다른 기능은 문자열 안에서 중괄호로 Raku 코드를 보간하는 능력이에요:

my ($x, $y, $z) = 4, 3.5, 3;
say "This room is {$x}m by {$y}m by {$z}m.";               # OUTPUT: «This room is 4m by 3.5m by 3m.␤»
say "Therefore its volume should be { $x * $y * $z }m³!";  # OUTPUT: «Therefore its volume should be 42m³!␤»

이것은 q:closure/q:c 따옴표 형태와 같은 기능을 제공해요.

이스케이프 코드 보간

qq 따옴표 형태는 백슬래시 이스케이프 시퀀스도 보간해요. 이 중 몇 개는 보이지 않는/공백 ASCII 제어 코드나 공백 문자를 출력해요:

시퀀스 Hex 값 문자 참조 URL
\0 \x0000 Nul https://util.unicode.org/UnicodeJsps/character.jsp?a=0000
\a \x0007 Bel https://util.unicode.org/UnicodeJsps/character.jsp?a=0007
\b \x0008 Backspace https://util.unicode.org/UnicodeJsps/character.jsp?a=0008
\e \x001B Esc https://util.unicode.org/UnicodeJsps/character.jsp?a=001B
\f \x000C Form Feed https://util.unicode.org/UnicodeJsps/character.jsp?a=000C
\n \x000A Newline https://util.unicode.org/UnicodeJsps/character.jsp?a=000A
\r \x000D Carriage Return https://util.unicode.org/UnicodeJsps/character.jsp?a=000D
\t \x0009 Tab https://util.unicode.org/UnicodeJsps/character.jsp?a=0009

qq\x\c라는 두 개의 다중 문자 이스케이프 시퀀스도 지원해요. 유니코드 문자의 hex 코드나 문자 목록과 함께 \x 또는 \x[]를 쓸 수 있어요:

my $s = "I \x2665 Raku!";
say $s;
# OUTPUT: «I ♥ Raku!␤»

$s = "I really \x[2661,2665,2764,1f495] Raku!";
say $s;
# OUTPUT: «I really ♡♥❤💕 Raku!␤»

\c와 그 문자의 <유니코드 이름>, <명명된 시퀀스> 또는 <이름 별칭>으로 유니코드 문자를 만들 수도 있어요:

my $s = "Camelia \c[BROKEN HEART] my \c[HEAVY BLACK HEART]!";
say $s;
# OUTPUT: «Camelia 💔 my ❤!␤»

자세한 내용은 문서 페이지의 \c[] 설명을 보세요.

qqq:backslash/q:b가 제공하는 것과 같은 이스케이프 시퀀스 보간을 제공해요.

보간 방지와 누락 값 처리

qq-따옴표 문자열에서 원치 않는 보간은 시길이나 다른 시작 문자를 이스케이프해서 막을 수 있어요:

say "The \$color variable contains the value '$color'"; # OUTPUT: «The $color variable contains the value 'blue'␤»

정의되지 않은 값의 보간은 현재 블록에서 로 잡을 수 있는 제어 예외를 일으켜요.

sub niler {Nil};
my Str $a = niler;
say("$a.html", "sometext");
say "alive"; # 이 줄은 죽은 코드
CONTROL { .die };

단어 따옴표: qw

qw|! @ # $ % ^ & * \| < > | eqv '! @ # $ % ^ & * | < >'.words.list;
q:w { [ ] \{ \} }           eqv ('[', ']', '{', '}');
Q:w | [ ] { } |             eqv ('[', ']', '{', '}');

:w 형태 — 보통 qw로 씀 — 는 문자열을 "단어"로 분할해요. 여기서 단어는 공백으로 구분된 비공백 문자 시퀀스로 정의돼요. q:wqw 형태는 q와 단일 따옴표 문자열 델리미터의 보간·이스케이프 의미를 상속받는 반면, QwQ:wQ 따옴표의 비이스케이프 의미를 상속해요.

이 형태는 문자열 목록에 따옴표와 쉼표를 많이 쓰는 것보다 선호돼요. 예를 들어 다음과 같이 쓸 수 있는 곳에:

my @directions = 'left', 'right,', 'up', 'down';

이렇게 쓰고 읽는 게 더 쉬워요:

my @directions = qw|left right up down|;

단어 따옴표: < >

say <a b c> eqv ('a', 'b', 'c');   # OUTPUT: «True␤»
say <a b 42> eqv ('a', 'b', '42'); # OUTPUT: «False␤», 42가 IntStr allomorph가 됨
say < 42 > ~~ Int; # OUTPUT: «True␤»
say < 42 > ~~ Str; # OUTPUT: «True␤»

각괄호 따옴표는 qw와 같지만, 특정 숫자의 나 리터럴을 구성하게 해주는 추가 기능이 있어요:

say <42 4/2 1e6 1+1i abc>.raku;
# OUTPUT: «(IntStr.new(42, "42"), RatStr.new(2.0, "4/2"), NumStr.new(1000000e0, "1e6"), ComplexStr.new(<1+1i>, "1+1i"), "abc")␤»

이나 리터럴을 구성하려면 추가 공백 없이 숫자 주위에 각괄호를 써요:

say <42/10>.^name;   # OUTPUT: «Rat␤»
say <1+42i>.^name;   # OUTPUT: «Complex␤»
say < 42/10 >.^name; # OUTPUT: «RatStr␤»
say < 1+42i >.^name; # OUTPUT: «ComplexStr␤»

42/101+42i와 달리 나눗셈(또는 덧셈) 연산이 개입하지 않아요. 이는 예를 들어 루틴 시그니처의 리터럴에 유용해요:

sub close-enough-π (<355/113>) {
    say "Your π is close enough!"
}
close-enough-π 710/226; # OUTPUT: «Your π is close enough!␤»
# WRONG: 나눗셈 연산이라 안 됨
sub compilation-failure (355/113) {}

따옴표 보호가 있는 단어 따옴표: qww

qw 형태의 단어 따옴표는 따옴표 문자를 리터럴로 취급해서 결과 단어에 그대로 남겨요:

say qw{"a b" c}.raku; # OUTPUT: «("\"a", "b\"", "c")␤»

qww 변형을 쓰면 따옴표 문자를 사용해 단어 따옴표 구조 안에 문자열을 내장할 수 있어요:

say qww{"a b" c}.raku; # OUTPUT: «("a b", "c")␤»

다른 종류의 따옴표도 일반적인 의미로 지원돼요:

my $one = 'here';
my $other = 'there';
say qww{ ’this and that’ “$one or $other” 「infinity and beyond」 }.raku;
# OUTPUT: «("this and that", "here or there", "infinity and beyond")␤»

내장 문자열의 델리미터는 항상 단어 분할자로 간주돼요:

say qww{'alpha'beta'gamma' 'delta'"epsilon"}.raku; # OUTPUT: «("alpha", "beta", "gamma", "delta", "epsilon")␤»

보간이 있는 단어 따옴표: qqw

qw 형태의 단어 따옴표는 변수를 보간하지 않아요:

my $a = 42; say qw{$a b c};  # OUTPUT: «$a b c␤»

따라서 따옴표 문자열 안에서 변수를 보간하고 싶다면 qqw 변형을 써야 해요:

my $a = 42;
my @list = qqw{$a b c};
say @list;                # OUTPUT: «[42 b c]␤»

변수 보간이 단어 분할보다 먼저 일어남에 주의하세요:

my $a = "a b";
my @list = qqw{$a c};
.say for @list; # OUTPUT: «a␤b␤c␤»

보간과 따옴표 보호가 있는 단어 따옴표: qqww

qqw 형태의 단어 따옴표는 따옴표 문자를 리터럴로 취급해서 결과 단어에 그대로 남겨요:

my $a = 42; say qqw{"$a b" c}.raku;  # OUTPUT: «("\"42", "b\"", "c")␤»

qqww 변형을 쓰면 따옴표 문자를 사용해 단어 따옴표 구조 안에 문자열을 내장할 수 있어요:

my $a = 42; say qqww{"$a b" c}.raku; # OUTPUT: «("42 b", "c")␤»

내장 문자열의 델리미터는 항상 단어 분할자로 간주돼요:

say qqww{'alpha'beta'gamma' 'delta'"epsilon"}.raku; # OUTPUT: «("alpha", "beta", "gamma", "delta", "epsilon")␤»

qqw 형태와 달리 보간도 항상 분할해요 (내장 문자열에서 일어나는 보간은 제외):

my $time = "now";
$_ = 'ni';
my @list = qqww<$time$time {6*7}{7*6} "$_$_">;
.say for @list; # OUTPUT: «now␤now␤42␤42␤nini␤»

따옴표 보호는 보간보다 먼저 일어나고, 보간은 단어 분할보다 먼저 일어나므로, 보간된 변수 안에서 나오는 따옴표는 리터럴 따옴표 문자일 뿐이에요:

my $a = "1 2";
say qqww{"$a" $a}.raku; # OUTPUT: «("1 2", "1", "2")␤»
my $b = "1 \"2 3\"";
say qqww{"$b" $b}.raku; # OUTPUT: «("1 \"2 3\"", "1", "\"2", "3\"")␤»

보간과 따옴표 보호가 있는 단어 따옴표: « »

이 따옴표 스타일은 qqww와 같지만, 를 구성한다는 추가 이점이 있어요 (기능적으로 qq:ww:v와 동등하게 만들어요). « »의 ASCII 동등 형태는 이중 각괄호 << >>예요.

# Allomorph 구성
my $a = 42; say «  $a b c    ».raku;  # OUTPUT: «(IntStr.new(42, "42"), "b", "c")␤»
my $a = 42; say << $a b c   >>.raku;  # OUTPUT: «(IntStr.new(42, "42"), "b", "c")␤»

# 따옴표 보호
my $a = 42; say «  "$a b" c  ».raku;  # OUTPUT: «("42 b", "c")␤»
my $a = 42; say << "$a b" c >>.raku;  # OUTPUT: «("42 b", "c")␤»

셸 따옴표: qx

문자열을 외부 프로그램으로 실행하려면 문자열을 shell이나 run 함수에 전달할 수 있을 뿐 아니라 셸 따옴표를 수행할 수도 있어요. 다만 고려할 미묘한 점이 몇 가지 있어요. qx 따옴표는 변수를 보간하지 않아요. 그래서

my $world = "there";
say qx{echo "hello $world"}

은 그냥 hello를 출력해요. 그런데 raku를 호출하기 전에 환경 변수를 선언했다면 그 환경 변수는 qx 안에서 사용할 수 있어요. 예:

WORLD="there" raku
> say qx{echo "hello $WORLD"}

은 이제 hello there을 출력해요.

qx 호출의 결과는 반환되므로, 이 정보를 나중에 쓰기 위해 변수에 할당할 수 있어요:

my $output = qx{echo "hello!"};
say $output;    # OUTPUT: «hello!␤»

외부 명령을 실행하는 다른 방법은 , , Proc::Async를 참고하세요.

보간이 있는 셸 따옴표: qqx

외부 명령 안에서 Raku 변수의 내용을 사용하고 싶다면 qqx 셸 따옴표 구성을 써야 해요:

my $world = "there";
say qqx{echo "hello $world"};  # OUTPUT: «hello there␤»

다시, 외부 명령의 출력은 변수에 담을 수 있어요:

my $word = "cool";
my $option = "-i";
my $file = "/usr/share/dict/words";
my $output = qqx{grep $option $word $file};
# 다음 명령을 실행: grep -i cool /usr/share/dict/words
say $output;      # OUTPUT: «Cooley␤Cooley's␤Coolidge␤Coolidge's␤cool␤...»

외부 명령 안에서 쓰는 Raku 변수의 내용에 주의하세요. 악의적인 내용은 임의 코드를 실행하는 데 쓰일 수 있어요. <qqx 함정>을 참고하세요.

외부 명령을 실행하는 더 나은 방법은 Proc::Async를 참고하세요.

Heredocs: :to

여러 줄 문자열 리터럴을 쓰는 편리한 방법은 heredoc을 사용하는 거예요. 델리미터를 직접 고를 수 있어요:

say q:to/END/;
Here is
some multi-line
string
END

heredoc의 내용은 항상 다음 줄에서 시작하므로, 줄을 (그리고 마땅히) 마칠 수 있어요.

my $escaped = my-escaping-function(q:to/TERMINATOR/, language => 'html');
Here are the contents of the heredoc.
Potentially multiple lines.
TERMINATOR

종결자가 들여쓰기되어 있으면 그만큼의 들여쓰기가 문자열 리터럴에서 제거돼요. 따라서 이 heredoc

say q:to/END/;
    Here is
    some multi line
        string
    END

다음 출력을 만들어요:

Here is
some multi line
    string

Heredoc은 종결자 앞의 개행을 포함해요. 그걸 제거하는 흔한 관용구는 시작 부분에 을 두는 거예요:

my $s = chomp q:to/END/;
The result will have
no final newline.
END

변수 보간을 허용하려면 형태를 사용해요. 예:

my $f = 'db.7.3.8';
my $s = qq:to/END/;
option \{
    file "$f";
};
END
say $s;

는 다음을 만들어요:

option {
    file "db.7.3.8";
};

주의할 다른 상황은 Raku 표현식처럼 보이는 무해해 보이는 텍스트예요. 예를 들어 다음은 오류를 만들어요:

my $title = 'USAFA Class of 1965';
say qq:to/HERE/;
<a href='https://usafa-1965.org'>$title</a>
HERE
# Output:
Type Str does not support associative indexing.
  in block <unit> at here.raku line 2

'$title' 오른쪽의 각괄호는 실제로는 변수인데 Raku에게는 해시 인덱스처럼 보여서 오류 메시지가 난 거예요. 한 해결책은 스칼라를 중괄호로 감싸는 거예요. 이는 보간 따옴표 구성에서 표현식을 입력하는 한 방법이에요:

say qq:to/HERE/;
<a href='https://usafa-1965.org'>{$title}</a>
HERE

다른 옵션은 < 문자를 이스케이프해서 인덱싱 연산자의 시작으로 파싱되지 않게 하는 거예요:

say qq:to/HERE/;
<a href='https://usafa-1965.org'>$title\</a>
HERE

heredoc은 매우 길 수 있지만 Raku가 여전히 한 줄로 해석하기 때문에, 오류의 원인을 찾기 어려울 때가 있어요. 오류를 디버깅하는 대략적인 방법 하나는 코드의 첫 번째 보이는 줄로 시작해서 그 줄만 heredoc으로 취급하는 거예요. 그런 다음 오류가 나기 전까지 각 줄을 순서대로 추가해요. (그렇게 하는 Raku 프로그램을 만드는 것은 독자의 연습으로 남겨둘게요.)

같은 줄에서 여러 Heredoc을 시작할 수 있어요. 그렇게 하면 두 번째 heredoc은 첫 번째 heredoc이 끝나기 전까지 시작하지 않아요.

my ($first, $second) = qq:to/END1/, qq:to/END2/;
  FIRST
  MULTILINE
  STRING
  END1
   SECOND
   MULTILINE
   STRING
   END2
say $first;  # OUTPUT: «FIRST␤MULTILINE␤STRING␤»
say $second; # OUTPUT: «SECOND␤MULTILINE␤STRING␤»

언쿼팅 (Unquoting)

리터럴 문자열은 이런 이스케이프 시퀀스를 사용해 내장 따옴표 구성의 보간을 허용해요:

my $animal="quaggas";
say 'These animals look like \qq[$animal]'; # OUTPUT: «These animals look like quaggas␤»
say 'These animals are \qqw[$animal or zebras]'; # OUTPUT: «These animals are quaggas or zebras␤»

이 예에서 \qq는 이중 따옴표 보간을, \qqw는 보간이 있는 단어 따옴표를 해요. 위처럼 다른 따옴표 구성을 이스케이프하면 같은 방식으로 동작해서 리터럴 문자열에서 보간을 허용해요.

더 알아보기 (Learn more)