유니코드 이스케이프 변환기
텍스트와 \u0041 형식 유니코드 이스케이프를 상호 변환
유니코드 이스케이프 변환기
처리 중…
0.0
멈춘 것이 아닙니다. 계산이 끝나면 결과가 표시됩니다.
유니코드 이스케이프 변환기 소개
이 도구의 인코딩 방향은 글자를 UTF-16 코드 유닛 단위의 \uXXXX로 바꿉니다. BMP 밖의 글자(이모지, 확장 한자)는 서로게이트 페어 두 개로 나뉘어 \ud83d\ude00처럼 12자가 됩니다. 디코딩 방향은 \uXXXX, \u{1F600}, Python의 \U0001F600, \xXX 네 형식을 알아보고 나머지 글자는 건드리지 않습니다.
JSON, JavaScript, Java, C# 소스에서 보는 이스케이프가 모두 같은 모양이라 서로 바꿔 써도 될 것 같지만, 언어마다 허용하는 형식과 처리 시점이 다릅니다. 아래는 그 차이와 실제로 자주 틀리는 지점입니다.
\uD83D\uDE00은 어떻게 나오는가
\u 뒤에는 16진수 4자리만 올 수 있으므로 U+FFFF까지만 직접 적을 수 있습니다. 그 위의 글자는 UTF-16 방식대로 둘로 쪼갭니다. 😀(U+1F600)이라면 먼저 0x10000을 뺍니다(0xF600). 이 20비트 값의 위 10비트(0x3D)를 0xD800에 더하면 상위 서로게이트 D83D, 아래 10비트(0x200)를 0xDC00에 더하면 하위 서로게이트 DE00이 됩니다.
D800~DFFF 구간은 유니코드에서 글자를 배정하지 않고 이 용도로만 비워 둔 곳입니다. 그래서 \uD83D 하나만 있는 문자열은 「짝 없는 서로게이트」라는 깨진 상태이고, UTF-8로 내보낼 때 �(U+FFFD)로 바뀌거나 오류가 납니다. 이 도구의 디코더는 짝 없는 서로게이트를 만나면 결과 아래에 개수와 함께 경고를 띄웁니다. 경고가 보이면 입력이 페어 중간에서 잘리지 않았는지 확인하세요.
언어별 이스케이프 형식
같은 😀을 적는 방법이 이렇게 다릅니다. 이 도구가 읽는 것은 앞의 세 가지(Python은 \U 형식만)와 \xXX입니다. \N{이름} 형식은 유니코드 이름 표 전체가 필요해서 지원하지 않고 원문 그대로 둡니다.
- JSON, Java, C#, 옛 JavaScript: \uD83D\uDE00 (서로게이트 페어 필수)
- JavaScript(ES2015 이후): \u{1F600} — JSON에서는 쓸 수 없음
- Python 3: \U0001F600(대문자 U와 8자리) 또는 \N{GRINNING FACE}
- CSS: \1F600 (뒤에 공백 하나로 끝을 표시)
- HTML: 😀 또는 😀
- URL: %F0%9F%98%80 (UTF-8 바이트를 퍼센트 인코딩)
\xED\x95\x9C를 넣었는데 「한」이 안 나올 때
Python에서 '한'.encode()를 출력하면 b'\xed\x95\x9c'가 나옵니다. 이것은 UTF-8 바이트 세 개입니다. 그런데 JavaScript의 \xXX는 바이트가 아니라 U+0000~00FF의 글자 하나를 뜻합니다. 이 도구도 기본으로는 JavaScript 규칙을 따르므로 \xed\x95\x9c를 디코딩하면 í와 보이지 않는 제어 문자 두 개가 나옵니다. 디코딩 방향에서 「연속된 \x 를 UTF-8 바이트로 읽기」를 켜면 이어진 \x 묶음을 바이트 열로 모아 UTF-8로 풀어서 「한」이 나옵니다. UTF-8로 맞지 않는 바이트는 �(U+FFFD)가 됩니다. UTF-8 텍스트를 Latin-1로 잘못 읽을 때 한글이 í, ì 같은 라틴 문자와 빈칸으로 깨지는 원리도 같습니다.
Java에서 주석 안의 \u000a가 코드를 깨는 이유
Java는 \uXXXX를 문자열 안에서만 처리하는 게 아니라, 컴파일러가 소스를 토큰으로 나누기 전에 파일 전체에서 먼저 바꿉니다(Java 언어 명세 3.3절). 그래서 // 주석 안에 \u000a를 적으면 실제 줄바꿈이 되어 그 뒤가 코드로 읽힙니다. 문자열 안에 줄바꿈을 넣을 때는 \n을 쓰세요. JavaScript와 JSON은 문자열 리터럴 안에서만 해석하므로 이런 일이 없습니다.
굳이 이스케이프하는 경우
UTF-8이 표준이 된 지금도 이스케이프가 필요한 곳이 있습니다. 인코딩 설정을 믿을 수 없는 오래된 빌드 도구나 Java 9 이전의 .properties 파일(ISO-8859-1로 읽음), 로그에서 보이지 않는 문자(U+200B, U+00A0)를 드러내 보여야 할 때, 그리고 코드 리뷰에서 비슷하게 생긴 글자를 구별해야 할 때입니다. 「영문·숫자·기호는 그대로 유지」 옵션을 켜면 ASCII 출력 가능 문자(0x20~0x7E)만 남기고 나머지를 바꾸므로 줄바꿈과 탭도 \u000a, \u0009로 나옵니다.
예시
한글, 악센트, 이모지를 한꺼번에
- 입력
é한😀- 결과
\u00e9\ud55c\ud83d\ude00
é와 한은 BMP 안이라 하나씩, 😀은 서로게이트 두 개. 결과는 JSON 문자열에 그대로 넣을 수 있습니다.
ES2015 형식 디코딩
- 입력
\u{1F600} \u{D55C}- 결과
😀 한
\u{} 안은 1~6자리 16진수이고 U+10FFFF를 넘으면 원문을 남깁니다.
바이트 이스케이프 오해
- 입력
\xed\x95\x9c- 결과
기본: í + U+0095 + U+009C / UTF-8 바이트 옵션: 한
\x는 기본적으로 Latin-1 범위의 글자 하나를 뜻합니다. Python bytes 출력처럼 UTF-8 바이트라면 옵션을 켜세요.
사용 방법
- 텍스트나 이스케이프 문자열을 입력합니다.
- 인코딩 또는 디코딩 방향을 고릅니다.
- 필요하면 ASCII 유지, 16진수 대문자(인코딩) 또는 \x UTF-8 바이트(디코딩) 옵션을 바꿉니다.
- 결과를 복사합니다.
자주 묻는 질문
이모지가 왜 \u 두 개가 되나요?
U+FFFF를 넘는 글자는 UTF-16에서 서로게이트 페어 두 개로 표현되고, \uXXXX는 코드 유닛 하나씩만 적을 수 있기 때문입니다.
JSON에 \u{1F600}을 써도 되나요?
안 됩니다. JSON(RFC 8259)은 \u 뒤 4자리만 허용하고, BMP 밖 글자는 서로게이트 페어 12자로 적어야 합니다.
Python의 \U0001F600도 되돌려 주나요?
네. 대문자 U 뒤 8자리 형식을 읽습니다. 다만 \N{GRINNING FACE} 같은 이름 형식은 지원하지 않아 원문 그대로 둡니다.
대문자와 소문자 결과가 다른가요?
16진수 표기만 다르고 뜻은 같습니다. 모든 언어가 둘 다 받아들입니다.
관련 가이드
출처
- ECMAScript Language Specification: String Literals
- RFC 8259: The JSON Data Interchange Format, Section 7 (Strings)
- Unicode FAQ: UTF-16 and surrogates
- Java Language Specification §3.3 Unicode Escapes
- Python documentation: String and Bytes literals
기준일: