SlideShare a Scribd company logo
1 of 20
Download to read offline
ES6: RegExp.prototype.unicode 이해하기
JSConf EU 2015 컨퍼런스에서 Mathias Bynens가 발표한
ES6의 RegExp.prototype.unicode 동영상을 정리하고 설명을 덧붙임
원본: https://www.youtube.com/watch?v=raJcug_vW0c
자바스크립트에서도 캐릭터의 symbol을 직접 사용할 필요 없이,
U+ 와 16진수 숫자(hexadecimal)로 코드 포인트를 직접 참조할 수 있다.
유니코드의 범위는 아래와 같이 크게 세 가지로 나눌 수 있다.
Unicode range
- U+000000 ~ U+10FFFF
BMP range (Basic Multilingual Plane)
- U+000000 ~ U+00FFFF
- 기본적인 다국어를 포함하는 범위
Astral planes range
- U+010000 ~ U+10FFFF (전체 범위의 95% 이상)
- 기본적인 다국어 외 이모지 등을 포함
자바스크립트는 Astral planes 를 두 개의 코드 포인트로 나눠 처리한다.
각각의 코드 포인트를 'surrogate half'라고 부르고, 두 코드 포인트의 조합을 'surrogate pair'라고 한다.
아래 코드를 보면 동작 방식을 이해할 수 있다.
예를 들어, !와 같이 Astral plane 레인지에 포함되어 있는 캐릭터가 있다고 가정해보자.
let poo = '!';
한 글자이지만 실제로 length를 조회해보면 2 가 리턴된다.
poo.length; //-> 2
캐릭터의 각 인덱스에 있는 코드를 확인해보자.
poo.charCodeAt(0); //-> 55357
poo.charCodeAt(0).toString(16); //-> 'd83d'
poo.charCodeAt(1); //-> 56489
poo.charCodeAt(1).toString(16); //-> 'dca9'
실제로 ! 캐릭터는 아래처럼 두 개의 유니코드로 구성되어 있다. (서로게이트 페어)
let poo2 = 'uD83DuDCA9';
물론, 두 값을 비교해도 같다.
poo === poo2; //-> true
코드 포인트를 브레이스({})로 감싸 표현하면, 자바스크립트의 기본 표현 범위(uXXXX)보다 더 큰 값의 코드 포인트를
참조할 수 있다.
let poo3 = 'u{1F4A9}';
poo2 === poo3; //-> true
위처럼 Astral plane range에 있는 캐릭터가 서로게이트 페어로 나뉘어지는 구조 때문에,
ES5에서는 Astral 캐릭터들은 정규식에서 매칭하기 어려웠다.
ES6부터는 유니코드 처리를 위한 RegExp.prototype.unicode 를 추가했고,
지금부터 설명할 u 플래그로 손쉽게 처리할 수 있게 되었다.
u flag
ES6에서는 정규식에서 유니코드를 처리할 수 있는 u 플래그가 추가됐다.
/u{61}/u.test('a'); //-> true
/u{1F4A9}/u.test('!'); //-> true
u 플래그를 생략하면 브레이스({})를 정규식의 한정 수량자로 인식한다.
/u{61}/.test('a'); //-> false, 이 정규식 구문은 'u'가 61개 있는 패턴을 의미한다.
u 플래그가 추가되면, 정규식이 스트릭트 모드(strict mode)로 동작한다고 생각하면 된다.
/abc/.test('abc'); //-> true, ES5에선 백슬래시() 뒤에 예약된 캐릭터가 오지 않는 경우 백슬래시를 무시했다.
/abc/u.test('abc'); //-> throws error
dot(.) operator
u 플래그가 붙은 경우, 닷(.) 오퍼레이터는 astral plane 에 포함된 문자열까지 포함한다.
let poo = 'a!b';
/a.b/.test(poo); //-> false
/a.b/u.test(poo); //-> true
quantifiers (수량자)
u 플래그는 astral 심볼도 한 글자로 가정해 매칭한다.
/a{2}/.test('aa'); //-> true
/!{2}/.test('!!'); //-> false
ES5에서 위 코드는 실제로 아래와 같이 서로게이트 페어로 나뉘어져 동작한다.
/uD83DuDCA9{2}/.test('uD83DuDCA9uD83DuDCA9'); //-> false
u 플래그를 사용한다면 아래처럼 의도한 결과를 볼 수 있다.
/!{2}/u.test('!!'); //-> true
Character classes
u 플래그는 캐릭터 클래스([])에 심볼이 포함된 경우도 한 글자로 처리한다.
let regex = /^[ab!]$/;
regex.test('a'); //-> true
regex.test('b'); //-> true
regex.test('!'); //-> false
마찬가지로 위 코드는 실제로 아래와 같이 서로게이트 페어로 나뉘어지기 때문이다.
let regex = /^[abuD83DuDCA9]/;
u 플래그를 적용한 경우, 의도한 대로 유니코드도 매칭된다.
let regex = /^[ab!]$/u;
regex.test('!'); //-> true
u 플래그를 사용하면 astral 캐릭터로 레인지를 표현할 수도 있다.
let regex = /[!-"]/u; // U+1F4A9 부터 U+1F4AB 까지의 심볼을 매칭한다.
regex.test('#'); //-> true (U+1F4AA)
regex.test('$'); //-> true (U+1F4AC)
u 플래그를 생략하면 range 에러가 발생하는데,
실제로 아래처럼 첫 번째 글자의 마지막 서로게이트와 두 번째 글자의 첫 서로게이트의 범위를 설정하려고 하기 때문이다.
let regex = /[!-"]/; //-> throws error
let regex = /[uD83DuDCA9-uD83DuDCAB]/;
같은 맥락에서, ES5에서는 negate 캐릭터(^)도 astral 캐릭터를 매칭하지 못했다.
/^[^a]$/.test('!'); //-> false
마찬가지로, 서로게이트 페어로 분리되어 매칭하기 때문이며,
/^[^a]$/u.test('!'); //-> true
Character class escapes
몇 가지 예약된 클래스 이스케이프가 있는데, u 플래그에서도 위에서 언급한 예제와 비슷한 맥락으로 동작한다.
d = [0-9]
D = [^0-9]
s = 공백 캐릭터
S = 공백 캐릭터가 아닌 캐릭터
w = [0-9a-zA-Z_]
W = [^0-9a-zA-Z_]
/^[^S]$/.test('!'); //-> false
u 플래그가 없다면 마찬가지로 서로게이트 페어로 분리되어 매칭하지 못한다.
/^[^S]$/u.test('!'); //-> true
With i flag
i 플래그를 u 플래그와 함께 쓰는 경우, 기본 아스키 범위 외의 유니코드 문자열과 알파벳 대소문자를 매칭할 수 있다.
let es5regex = /[a-z]/i;
let es6regex = /[a-z]/iu;
let K = 'u212A'; // 기본 알파벳이 아닌 대문자 K
es5regex.test(K); //-> false
es6regex.test(K); //-> true
하지만 W 와 함께 쓰는 경우엔 좀 헷갈리는 결과가 나온다.
let es5regex = /W/i;
let es6regex = /W/iu;
es5regex.test('S'); //-> false
es6regex.test('S'); //-> true
i 와 u 플래그가 동시에 쓰이면, W 는 더이상 w 의 반대값으로 동작하지 않는다.
HTML 문서 내에서의 패턴
HTML에서는 u 플래그가 항상 적용된 상태로 동작한다.
<style>
:invalid { background: red; }
:valid {background: green; }
</style>
<input pattern="a.b" value="aXXb"> //-> red background
<input pattern="a.b" value="a!b"> //-> green background
u 플래그 사용 가능 환경
지원 브라우저
- Microsoft Edge/Chakra (HTML 패턴 제외)
- V8 (옵션으로 --harmony-unicode-regexps 전달)
예를 들어, 커맨드라인에서 테스트해보고 싶다면 아래와 같이 실행하면 된다.
$ node --harmony_unicode_regexps
빌드 도구
- Babel 같은 빌드 도구에서 u 플래그 적용 여부에 대한 플래그가 있음
다른 라이브러리 사용
- regexpu (https://github.com/mathiasbynens/regexpu)
- XRegExp (http://xregexp.com/)

More Related Content

What's hot

코딩인카페 C&JAVA 기초과정 C프로그래밍(2)
코딩인카페 C&JAVA 기초과정 C프로그래밍(2)코딩인카페 C&JAVA 기초과정 C프로그래밍(2)
코딩인카페 C&JAVA 기초과정 C프로그래밍(2)유익아카데미
 
Ruby - 6th (루비 6장 변수와 식)
Ruby - 6th (루비 6장 변수와 식)Ruby - 6th (루비 6장 변수와 식)
Ruby - 6th (루비 6장 변수와 식)재영 이
 
자바스크립트.
자바스크립트.자바스크립트.
자바스크립트.Deoc Jin
 
코딩인카페 C&JAVA 기초과정 C프로그래밍(1)
코딩인카페 C&JAVA 기초과정 C프로그래밍(1)코딩인카페 C&JAVA 기초과정 C프로그래밍(1)
코딩인카페 C&JAVA 기초과정 C프로그래밍(1)유익아카데미
 

What's hot (7)

코딩인카페 C&JAVA 기초과정 C프로그래밍(2)
코딩인카페 C&JAVA 기초과정 C프로그래밍(2)코딩인카페 C&JAVA 기초과정 C프로그래밍(2)
코딩인카페 C&JAVA 기초과정 C프로그래밍(2)
 
Lua 문법
Lua 문법Lua 문법
Lua 문법
 
Ruby - 6th (루비 6장 변수와 식)
Ruby - 6th (루비 6장 변수와 식)Ruby - 6th (루비 6장 변수와 식)
Ruby - 6th (루비 6장 변수와 식)
 
자바스크립트.
자바스크립트.자바스크립트.
자바스크립트.
 
코딩인카페 C&JAVA 기초과정 C프로그래밍(1)
코딩인카페 C&JAVA 기초과정 C프로그래밍(1)코딩인카페 C&JAVA 기초과정 C프로그래밍(1)
코딩인카페 C&JAVA 기초과정 C프로그래밍(1)
 
You dont know_js
You dont know_jsYou dont know_js
You dont know_js
 
Equation Solving
Equation SolvingEquation Solving
Equation Solving
 

More from Ohgyun Ahn

호갱노노 이렇게 만듭니다
호갱노노 이렇게 만듭니다호갱노노 이렇게 만듭니다
호갱노노 이렇게 만듭니다Ohgyun Ahn
 
카카오스토리 웹팀의 코드리뷰 경험
카카오스토리 웹팀의 코드리뷰 경험카카오스토리 웹팀의 코드리뷰 경험
카카오스토리 웹팀의 코드리뷰 경험Ohgyun Ahn
 
Node.js 시작하기
Node.js 시작하기Node.js 시작하기
Node.js 시작하기Ohgyun Ahn
 
JavaScript Memory Profiling
JavaScript Memory ProfilingJavaScript Memory Profiling
JavaScript Memory ProfilingOhgyun Ahn
 
JavaScript Minification
JavaScript MinificationJavaScript Minification
JavaScript MinificationOhgyun Ahn
 
JavaSript Template Engine
JavaSript Template EngineJavaSript Template Engine
JavaSript Template EngineOhgyun Ahn
 
Github Usage Scenarios
Github Usage ScenariosGithub Usage Scenarios
Github Usage ScenariosOhgyun Ahn
 
diff output formats
diff output formatsdiff output formats
diff output formatsOhgyun Ahn
 
패키지 매니저의 요건
패키지 매니저의 요건패키지 매니저의 요건
패키지 매니저의 요건Ohgyun Ahn
 
BASH Guide Summary
BASH Guide SummaryBASH Guide Summary
BASH Guide SummaryOhgyun Ahn
 
Python Usage (5-minute-summary)
Python Usage (5-minute-summary)Python Usage (5-minute-summary)
Python Usage (5-minute-summary)Ohgyun Ahn
 
UX 심포지엄 20120 키노트 정리
UX 심포지엄 20120 키노트 정리UX 심포지엄 20120 키노트 정리
UX 심포지엄 20120 키노트 정리Ohgyun Ahn
 
크롬익스텐션 맛보기
크롬익스텐션 맛보기크롬익스텐션 맛보기
크롬익스텐션 맛보기Ohgyun Ahn
 
재미있는 생산성 향상 도구
재미있는 생산성 향상 도구재미있는 생산성 향상 도구
재미있는 생산성 향상 도구Ohgyun Ahn
 
Raphael.js로 SVG 차트 만들기
Raphael.js로 SVG 차트 만들기Raphael.js로 SVG 차트 만들기
Raphael.js로 SVG 차트 만들기Ohgyun Ahn
 
깃헙으로 코드리뷰 하기
깃헙으로 코드리뷰 하기깃헙으로 코드리뷰 하기
깃헙으로 코드리뷰 하기Ohgyun Ahn
 
Recurrence relation
Recurrence relationRecurrence relation
Recurrence relationOhgyun Ahn
 

More from Ohgyun Ahn (17)

호갱노노 이렇게 만듭니다
호갱노노 이렇게 만듭니다호갱노노 이렇게 만듭니다
호갱노노 이렇게 만듭니다
 
카카오스토리 웹팀의 코드리뷰 경험
카카오스토리 웹팀의 코드리뷰 경험카카오스토리 웹팀의 코드리뷰 경험
카카오스토리 웹팀의 코드리뷰 경험
 
Node.js 시작하기
Node.js 시작하기Node.js 시작하기
Node.js 시작하기
 
JavaScript Memory Profiling
JavaScript Memory ProfilingJavaScript Memory Profiling
JavaScript Memory Profiling
 
JavaScript Minification
JavaScript MinificationJavaScript Minification
JavaScript Minification
 
JavaSript Template Engine
JavaSript Template EngineJavaSript Template Engine
JavaSript Template Engine
 
Github Usage Scenarios
Github Usage ScenariosGithub Usage Scenarios
Github Usage Scenarios
 
diff output formats
diff output formatsdiff output formats
diff output formats
 
패키지 매니저의 요건
패키지 매니저의 요건패키지 매니저의 요건
패키지 매니저의 요건
 
BASH Guide Summary
BASH Guide SummaryBASH Guide Summary
BASH Guide Summary
 
Python Usage (5-minute-summary)
Python Usage (5-minute-summary)Python Usage (5-minute-summary)
Python Usage (5-minute-summary)
 
UX 심포지엄 20120 키노트 정리
UX 심포지엄 20120 키노트 정리UX 심포지엄 20120 키노트 정리
UX 심포지엄 20120 키노트 정리
 
크롬익스텐션 맛보기
크롬익스텐션 맛보기크롬익스텐션 맛보기
크롬익스텐션 맛보기
 
재미있는 생산성 향상 도구
재미있는 생산성 향상 도구재미있는 생산성 향상 도구
재미있는 생산성 향상 도구
 
Raphael.js로 SVG 차트 만들기
Raphael.js로 SVG 차트 만들기Raphael.js로 SVG 차트 만들기
Raphael.js로 SVG 차트 만들기
 
깃헙으로 코드리뷰 하기
깃헙으로 코드리뷰 하기깃헙으로 코드리뷰 하기
깃헙으로 코드리뷰 하기
 
Recurrence relation
Recurrence relationRecurrence relation
Recurrence relation
 

ES6: RegExp.prototype.unicode 이해하기

  • 2. JSConf EU 2015 컨퍼런스에서 Mathias Bynens가 발표한 ES6의 RegExp.prototype.unicode 동영상을 정리하고 설명을 덧붙임 원본: https://www.youtube.com/watch?v=raJcug_vW0c
  • 3. 자바스크립트에서도 캐릭터의 symbol을 직접 사용할 필요 없이, U+ 와 16진수 숫자(hexadecimal)로 코드 포인트를 직접 참조할 수 있다. 유니코드의 범위는 아래와 같이 크게 세 가지로 나눌 수 있다. Unicode range - U+000000 ~ U+10FFFF BMP range (Basic Multilingual Plane) - U+000000 ~ U+00FFFF - 기본적인 다국어를 포함하는 범위 Astral planes range - U+010000 ~ U+10FFFF (전체 범위의 95% 이상) - 기본적인 다국어 외 이모지 등을 포함
  • 4. 자바스크립트는 Astral planes 를 두 개의 코드 포인트로 나눠 처리한다. 각각의 코드 포인트를 'surrogate half'라고 부르고, 두 코드 포인트의 조합을 'surrogate pair'라고 한다. 아래 코드를 보면 동작 방식을 이해할 수 있다. 예를 들어, !와 같이 Astral plane 레인지에 포함되어 있는 캐릭터가 있다고 가정해보자. let poo = '!'; 한 글자이지만 실제로 length를 조회해보면 2 가 리턴된다. poo.length; //-> 2
  • 5. 캐릭터의 각 인덱스에 있는 코드를 확인해보자. poo.charCodeAt(0); //-> 55357 poo.charCodeAt(0).toString(16); //-> 'd83d' poo.charCodeAt(1); //-> 56489 poo.charCodeAt(1).toString(16); //-> 'dca9'
  • 6. 실제로 ! 캐릭터는 아래처럼 두 개의 유니코드로 구성되어 있다. (서로게이트 페어) let poo2 = 'uD83DuDCA9'; 물론, 두 값을 비교해도 같다. poo === poo2; //-> true
  • 7. 코드 포인트를 브레이스({})로 감싸 표현하면, 자바스크립트의 기본 표현 범위(uXXXX)보다 더 큰 값의 코드 포인트를 참조할 수 있다. let poo3 = 'u{1F4A9}'; poo2 === poo3; //-> true
  • 8. 위처럼 Astral plane range에 있는 캐릭터가 서로게이트 페어로 나뉘어지는 구조 때문에, ES5에서는 Astral 캐릭터들은 정규식에서 매칭하기 어려웠다. ES6부터는 유니코드 처리를 위한 RegExp.prototype.unicode 를 추가했고, 지금부터 설명할 u 플래그로 손쉽게 처리할 수 있게 되었다.
  • 9. u flag ES6에서는 정규식에서 유니코드를 처리할 수 있는 u 플래그가 추가됐다. /u{61}/u.test('a'); //-> true /u{1F4A9}/u.test('!'); //-> true
  • 10. u 플래그를 생략하면 브레이스({})를 정규식의 한정 수량자로 인식한다. /u{61}/.test('a'); //-> false, 이 정규식 구문은 'u'가 61개 있는 패턴을 의미한다. u 플래그가 추가되면, 정규식이 스트릭트 모드(strict mode)로 동작한다고 생각하면 된다. /abc/.test('abc'); //-> true, ES5에선 백슬래시() 뒤에 예약된 캐릭터가 오지 않는 경우 백슬래시를 무시했다. /abc/u.test('abc'); //-> throws error
  • 11. dot(.) operator u 플래그가 붙은 경우, 닷(.) 오퍼레이터는 astral plane 에 포함된 문자열까지 포함한다. let poo = 'a!b'; /a.b/.test(poo); //-> false /a.b/u.test(poo); //-> true
  • 12. quantifiers (수량자) u 플래그는 astral 심볼도 한 글자로 가정해 매칭한다. /a{2}/.test('aa'); //-> true /!{2}/.test('!!'); //-> false ES5에서 위 코드는 실제로 아래와 같이 서로게이트 페어로 나뉘어져 동작한다. /uD83DuDCA9{2}/.test('uD83DuDCA9uD83DuDCA9'); //-> false u 플래그를 사용한다면 아래처럼 의도한 결과를 볼 수 있다. /!{2}/u.test('!!'); //-> true
  • 13. Character classes u 플래그는 캐릭터 클래스([])에 심볼이 포함된 경우도 한 글자로 처리한다. let regex = /^[ab!]$/; regex.test('a'); //-> true regex.test('b'); //-> true regex.test('!'); //-> false 마찬가지로 위 코드는 실제로 아래와 같이 서로게이트 페어로 나뉘어지기 때문이다. let regex = /^[abuD83DuDCA9]/; u 플래그를 적용한 경우, 의도한 대로 유니코드도 매칭된다. let regex = /^[ab!]$/u; regex.test('!'); //-> true
  • 14. u 플래그를 사용하면 astral 캐릭터로 레인지를 표현할 수도 있다. let regex = /[!-"]/u; // U+1F4A9 부터 U+1F4AB 까지의 심볼을 매칭한다. regex.test('#'); //-> true (U+1F4AA) regex.test('$'); //-> true (U+1F4AC) u 플래그를 생략하면 range 에러가 발생하는데, 실제로 아래처럼 첫 번째 글자의 마지막 서로게이트와 두 번째 글자의 첫 서로게이트의 범위를 설정하려고 하기 때문이다. let regex = /[!-"]/; //-> throws error let regex = /[uD83DuDCA9-uD83DuDCAB]/;
  • 15. 같은 맥락에서, ES5에서는 negate 캐릭터(^)도 astral 캐릭터를 매칭하지 못했다. /^[^a]$/.test('!'); //-> false 마찬가지로, 서로게이트 페어로 분리되어 매칭하기 때문이며, /^[^a]$/u.test('!'); //-> true
  • 16. Character class escapes 몇 가지 예약된 클래스 이스케이프가 있는데, u 플래그에서도 위에서 언급한 예제와 비슷한 맥락으로 동작한다. d = [0-9] D = [^0-9] s = 공백 캐릭터 S = 공백 캐릭터가 아닌 캐릭터 w = [0-9a-zA-Z_] W = [^0-9a-zA-Z_] /^[^S]$/.test('!'); //-> false u 플래그가 없다면 마찬가지로 서로게이트 페어로 분리되어 매칭하지 못한다. /^[^S]$/u.test('!'); //-> true
  • 17. With i flag i 플래그를 u 플래그와 함께 쓰는 경우, 기본 아스키 범위 외의 유니코드 문자열과 알파벳 대소문자를 매칭할 수 있다. let es5regex = /[a-z]/i; let es6regex = /[a-z]/iu; let K = 'u212A'; // 기본 알파벳이 아닌 대문자 K es5regex.test(K); //-> false es6regex.test(K); //-> true
  • 18. 하지만 W 와 함께 쓰는 경우엔 좀 헷갈리는 결과가 나온다. let es5regex = /W/i; let es6regex = /W/iu; es5regex.test('S'); //-> false es6regex.test('S'); //-> true i 와 u 플래그가 동시에 쓰이면, W 는 더이상 w 의 반대값으로 동작하지 않는다.
  • 19. HTML 문서 내에서의 패턴 HTML에서는 u 플래그가 항상 적용된 상태로 동작한다. <style> :invalid { background: red; } :valid {background: green; } </style> <input pattern="a.b" value="aXXb"> //-> red background <input pattern="a.b" value="a!b"> //-> green background
  • 20. u 플래그 사용 가능 환경 지원 브라우저 - Microsoft Edge/Chakra (HTML 패턴 제외) - V8 (옵션으로 --harmony-unicode-regexps 전달) 예를 들어, 커맨드라인에서 테스트해보고 싶다면 아래와 같이 실행하면 된다. $ node --harmony_unicode_regexps 빌드 도구 - Babel 같은 빌드 도구에서 u 플래그 적용 여부에 대한 플래그가 있음 다른 라이브러리 사용 - regexpu (https://github.com/mathiasbynens/regexpu) - XRegExp (http://xregexp.com/)