문자열 이스케이프란?
문자열 이스케이프는 문자열 리터럴 내에서 특별한 의미를 갖는 문자 앞에 백슬래시(또는 다른 마커)를 삽입하는 과정입니다. 프로그래밍 언어 파서가 큰따옴표로 묶인 문자열 안에서 큰따옴표를 만나면 문자열의 끝으로 처리합니다. 따옴표 앞에 백슬래시를 붙여 이스케이프하면 — " 대신 \" 로 표기하면 — 파서에게 이것이 구분자가 아닌 리터럴 문자임을 알립니다. 문자열 리터럴을 사용하는 모든 언어에는 이스케이프 규칙이 있지만, 정확한 시퀀스는 언어마다 다릅니다.
가장 일반적인 이스케이프 시퀀스는 소스 코드에 직접 표현할 수 없는 공백 문자 및 제어 문자에 대응합니다. 개행 문자는 \n, 탭은 \t, 리터럴 백슬래시는 \\로 표현합니다. 이 규칙은 C 프로그래밍 언어(ISO/IEC 9899)에서 유래하여 JavaScript(ECMA-262), Python, Java, Go, Rust에 채택되었습니다. JSON(RFC 8259)도 동일한 문법을 사용하지만 지원하는 시퀀스 집합이 더 작습니다.
언이스케이프("de-escaping"이라고도 함)는 반대 연산으로, 이스케이프 시퀀스를 원래 문자로 되돌립니다. 로그 파일을 읽거나 API 응답을 파싱하거나 이중 이스케이프된 데이터를 디버깅할 때 자주 사용됩니다. 두 작업 모두 손으로 직접 처리하면 실수하기 쉬우므로, 개발자들은 여러 줄 문자열, 중첩 따옴표, 유니코드 문자를 다룰 때 이스케이프/언이스케이프 도구를 사용합니다.
온라인 문자열 이스케이프 도구를 사용하는 이유
백슬래시를 수동으로 추가하거나 제거하는 작업은 번거롭고 실수하기 쉽습니다. 특히 중첩 따옴표나 여러 줄 입력이 있을 때 더욱 그렇습니다. 브라우저 기반 문자열 이스케이프 도구는 REPL을 설정하거나 임시 스크립트를 작성할 필요 없이 즉각적인 결과를 제공합니다.
문자열 이스케이프 활용 사례
이스케이프 시퀀스 참조표
아래 표는 일반적인 이스케이프 시퀀스와 JavaScript, Python, JSON에서의 지원 여부를 나열합니다. 세 언어 모두 핵심 집합(개행, 탭, 백슬래시, 큰따옴표)을 공유하지만, 작은따옴표, 16진수 이스케이프, 확장 유니코드 표기법에서는 차이가 있습니다.
| 시퀀스 | 의미 | JavaScript | Python | JSON |
|---|---|---|---|---|
| \n | Newline (LF) | Yes | Yes | Yes |
| \r | Carriage return | Yes | Yes | Yes |
| \t | Tab | Yes | Yes | Yes |
| \\ | Backslash | Yes | Yes | Yes |
| \" | Double quote | Yes | Yes | Yes |
| \' | Single quote | Yes | Yes | No |
| \b | Backspace | Yes | Yes | Yes |
| \f | Form feed | Yes | Yes | Yes |
| \v | Vertical tab | Yes | Yes | No |
| \0 | Null character | Yes | Yes | No |
| \xNN | Hex byte | Yes | Yes | No |
| \uNNNN | Unicode (BMP) | Yes | Yes | Yes |
| \u{N..} | Unicode (full) | Yes | No | No |
JavaScript vs Python vs JSON 이스케이프 비교
이 세 형식은 같은 백슬래시 기반 문법을 공유하지만, 유효한 시퀀스와 엣지 케이스 처리 방식이 다릅니다. 잘못된 모드를 선택하면 겉으로는 올바르게 보이지만 파싱 시 오류가 발생하는 결과물이 나옵니다.
코드 예시
JavaScript, Python, Go 및 커맨드 라인에서 문자열을 이스케이프하고 언이스케이프하는 예시입니다.
// Escape a string with special characters
const raw = 'Line 1\nLine 2\tTabbed "quoted"';
const escaped = JSON.stringify(raw);
// → '"Line 1\\nLine 2\\tTabbed \\"quoted\\""'
// Unescape a JSON string value
const input = '"Hello\\nWorld"';
const unescaped = JSON.parse(input);
// → "Hello\nWorld" (actual newline character)
// Template literals don't need quote escaping
const tpl = `She said "hello"`;
// → 'She said "hello"' — no backslashes needed
// Escape for use inside a RegExp
const query = 'price: $5.00 (USD)';
const safe = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// → "price: \\$5\\.00 \\(USD\\)"# Escape with repr() — shows escape sequences
raw = "Line 1\nLine 2\t'quoted'"
print(repr(raw))
# → "Line 1\nLine 2\t'quoted'"
# Raw strings skip escape processing
path = r"C:\Users\name\Documents"
print(path)
# → C:\Users\name\Documents (backslashes kept literal)
# JSON escaping with json module
import json
data = 'He said "hello\nworld"'
escaped = json.dumps(data)
# → '"He said \\"hello\\nworld\\""'
# Unicode escaping
text = "Caf\u00e9" # → "Café"
print(text.encode('unicode_escape').decode())
# → "Caf\\xe9"package main
import (
"fmt"
"strconv"
"encoding/json"
)
func main() {
// strconv.Quote adds escape sequences and wraps in quotes
raw := "Line 1\nLine 2\t\"quoted\""
fmt.Println(strconv.Quote(raw))
// → "\"Line 1\\nLine 2\\t\\\"quoted\\\"\""
// strconv.Unquote reverses it
unescaped, _ := strconv.Unquote(`"hello\nworld"`)
fmt.Println(unescaped)
// → hello
// world
// JSON marshal handles escaping automatically
b, _ := json.Marshal("tabs\there & \"quotes\"")
fmt.Println(string(b))
// → "tabs\there \u0026 \"quotes\""
}# Use $'...' syntax for escape sequences in bash echo $'Line 1\nLine 2\tTabbed' # → Line 1 # Line 2 Tabbed # printf interprets escape sequences printf 'Path: C:\\Users\\name\n' # → Path: C:\Users\name # Use jq to escape a string for JSON echo 'He said "hello"' | jq -Rs . # → "He said \"hello\"\n" # Unescape JSON string with jq echo '"Line 1\\nLine 2"' | jq -r . # → Line 1 # Line 2