title: “이번 주의 팁 #64: Raw 문자열 리터럴” layout: tips sidenav: side-nav-tips.html published: true permalink: tips/64 type: markdown order: “064” —
원래 totw/64로 2013-12-09에 게시됨
작성자: Titus Winters (titus@google.com)
2017-10-23 업데이트
빠른 링크: abseil.io/tips/64
"(?:\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*')";
— 고양이가 키보드를 밟고 지나간 흔적일까요, 아니면 여우가 뭐라고 하는 걸까요… 사실, 실제 C++ 코드에서 발견된 지나치게 이스케이프된 정규 표현식입니다.
아마도 C++에서 이스케이프 문제 때문에 정규 표현식을 제대로 이해시키는 데 어려움을 겪은 경험이 있을 것입니다. 마찬가지로, Protobuf나 JSON 데이터를 텍스트 형태로 유닛 테스트에 삽입할 때 따옴표와 줄바꿈을 유지하는 데 짜증이 났을 수도 있습니다. 이스케이프 처리가 많이 필요할수록(심지어 여러 번 중첩된 이스케이프라면 더더욱), 코드의 가독성은 급격히 떨어집니다.
다행히도, C++11에서는 이러한 이스케이프 처리를 제거해 주는 새로운 기능이 추가되었습니다: 바로 raw 문자열 리터럴입니다.
Raw 문자열 리터럴 형식
Raw 문자열 리터럴은 다음과 같은 특별한 문법을 사용합니다:
R"tag(여기에 원하는 내용을 입력하세요)tag"
tag
는 최대 16자의 문자열(빈 태그도 가능합니다)이며, "tag(
이후와 )tag"
사이에 있는 모든 문자는 문자열 리터럴의 내용으로 그대로 사용됩니다. tag
에는 괄호, 백슬래시, 공백을 제외한 어떤 문자든 포함될 수 있습니다.
다음의 예를 비교해 보세요:
const char concert_17_raw[] =
"id: 17\n"
"artist: \"Beyonce\"\n"
"date: \"Wed Oct 10 12:39:54 EDT 2012\"\n"
"price_usd: 200\n";
대신에 raw 문자열 리터럴을 사용하면 다음과 같이 작성할 수 있습니다:
const char concert_17_raw[] = R"(
id: 17
artist: "Beyonce"
date: "Wed Oct 10 12:39:54 EDT 2012"
price_usd: 200)";
특별한 경우
들여쓰기 규칙과 raw 문자열 리터럴이 줄바꿈을 포함할 수 있다는 사실을 고려하면, raw 문자열 블록의 첫 번째 줄을 어떻게 들여쓸 것인지에 대해 고민하게 될 수 있습니다. Protobuf 텍스트는 공백을 무시하므로, 선행 줄바꿈을 추가하여(파서에서 무시됨) 문제를 피할 수 있지만, 모든 raw 문자열이 그렇게 관대하지는 않습니다.
문자열 안에 )"
가 포함되어 닫는 구분자로 인식되지 않게 하려면, 비어 있지 않은 태그를 사용하는 것이 유용합니다:
std::string my_string = R"foo(This contains quoted parens "()")foo";
결론
Raw 문자열 리터럴은 대부분의 프로그래머에게 일상적으로 사용하는 도구는 아닙니다. 하지만 이 새로운 언어 기능을 잘 활용하면 가독성을 높일 수 있는 상황이 분명 존재합니다. 다음에 이스케이프를 두 번(\\
) 해야 할지 네 번(\\\\
) 해야 할지 고민하게 된다면, raw 문자열 리터럴을 대신 사용해 보세요. 독자들이 감사할 것입니다. 물론, 정규 표현식은 여전히 어려울 수 있지만요:
R"regexp((?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'))regexp";
reference
https://github.com/abseil/abseil.github.io/blob/master/_posts/2017-10-26-totw-64.md