charset encoding

simuruk wiki

Charset encoding

개발을 하면서 문자열 처리에 대해 겪었던 문제와 기본 개념을 정리 해보려 합니다.

최근에는 HTML5의 기본 charset이 utf-8이 되었고 Database 기본 character set과 서버 구동시 encoding을 utf-8로 하는 것이 기본이 되었기 때문에 단순한 인코딩이 문제가 된적은 없습니다.

하지만 예전에 개발을 하다보면 문자열이 ¾È³çÇϼ¼¿ä �븞�뀞�븯�꽭�슂 뻈돧쟏벼뿤 같은 문자열을 종종 만날수 있었고 당황했던 경험이 있습니다.

최근에 개발을 하면서 emoji와 accent 문자열로 인해 이슈를 겪었고 다시 한번 정리 해보는 겸, 혹시 경험해 보지 않으신 분 들을 위해 3가지의 기본적인 내용과 겪었던 3가지 문제와 해결 방법을 아래 적힌 순서대로 적었습니다.

  • ascii unicode utf-16 euckr utf-8
  • utf-8 정규화 비정규화
  • mysql chracter set과 collation
  • emoji 문자 문제
  • accent 문자 문제
  • html escape 문제

ascii unicode ucs-2 utf-16 euckr utf-8차이

ascii

ascii코드는 0부터 128까지의 1byte중 7bit를 사용하는 부호 체계입니다. 1bit는 Parity bit로 통신 에러 검출에 사용하는 방식입니다

ascii extended는 8bit를 사용하는 확장형 코드로 특수문자 기호를 포함합니다 ascii code

DEC OCT HEX BIN Symbol HTML Number HTML Name Description
0 000 00 00000000 NUL � Null char
1 001 01 00000001 SOH  Start of Heading
2 002 02 00000010 STX  Start of Text
3 003 03 00000011 ETX  End of Text
4 004 04 00000100 EOT  End of Transmission
5 005 05 00000101 ENQ  Enquiry
6 006 06 00000110 ACK  Acknowledgment
7 007 07 00000111 BEL  Bell
8 010 08 00001000 BS  Back Space
9 011 09 00001001 HT Horizontal Tab
10 012 0A 00001010 LF Line Feed
11 013 0B 00001011 VT  Vertical Tab
12 014 0C 00001100 FF  Form Feed
13 015 0D 00001101 CR 
 Carriage Return
14 016 0E 00001110 SO  Shift Out / X-On
15 017 0F 00001111 SI  Shift In / X-Off
16 020 10 00010000 DLE  Data Line Escape
17 021 11 00010001 DC1  Device Control 1 (oft. XON)
18 022 12 00010010 DC2  Device Control 2
19 023 13 00010011 DC3  Device Control 3 (oft. XOFF)
20 024 14 00010100 DC4  Device Control 4
21 025 15 00010101 NAK  Negative Acknowledgement
22 026 16 00010110 SYN  Synchronous Idle
23 027 17 00010111 ETB  End of Transmit Block
24 030 18 00011000 CAN  Cancel
25 031 19 00011001 EM  End of Medium
26 032 1A 00011010 SUB  Substitute
27 033 1B 00011011 ESC  Escape
28 034 1C 00011100 FS  File Separator
29 035 1D 00011101 GS  Group Separator
30 036 1E 00011110 RS  Record Separator
31 037 1F 00011111 US  Unit Separator
32 040 20 00100000 Space
33 041 21 00100001 느낌표 느낌표 Exclamation mark
34 042 22 00100010 " " " Double quotes (or speech marks)
35 043 23 00100011 # # Number
36 044 24 00100100 $ $ Dollar
37 045 25 00100101  % % Per cent sign
38 046 26 00100110 & & & Ampersand
39 047 27 00100111 ' ' Single quote
40 050 28 00101000 ( ( Open parenthesis (or open bracket)
41 051 29 00101001 ) ) Close parenthesis (or close bracket)
42 052 2A 00101010 * * Asterisk
43 053 2B 00101011 + + Plus
44 054 2C 00101100 , , Comma
45 055 2D 00101101 - - Hyphen
46 056 2E 00101110 . . Period, dot or full stop
47 057 2F 00101111 / / Slash or divide
48 060 30 00110000 0 0 Zero
49 061 31 00110001 1 1 One
50 062 32 00110010 2 2 Two
51 063 33 00110011 3 3 Three
52 064 34 00110100 4 4 Four
53 065 35 00110101 5 5 Five
54 066 36 00110110 6 6 Six
55 067 37 00110111 7 7 Seven
56 070 38 00111000 8 8 Eight
57 071 39 00111001 9 9 Nine
58 072 3A 00111010  : : Colon
59 073 3B 00111011  ; ; Semicolon
60 074 3C 00111100 < < < Less than (or open angled bracket)
61 075 3D 00111101 = = Equals
62 076 3E 00111110 > > > Greater than (or close angled bracket)
63 077 3F 00111111  ? ? Question mark
64 100 40 01000000 @ @ At symbol
65 101 41 01000001 A A Uppercase A
66 102 42 01000010 B B Uppercase B
67 103 43 01000011 C C Uppercase C
68 104 44 01000100 D D Uppercase D
69 105 45 01000101 E E Uppercase E
70 106 46 01000110 F F Uppercase F
71 107 47 01000111 G G Uppercase G
72 110 48 01001000 H H Uppercase H
73 111 49 01001001 I I Uppercase I
74 112 4A 01001010 J J Uppercase J
75 113 4B 01001011 K K Uppercase K
76 114 4C 01001100 L L Uppercase L
77 115 4D 01001101 M M Uppercase M
78 116 4E 01001110 N N Uppercase N
79 117 4F 01001111 O O Uppercase O
80 120 50 01010000 P P Uppercase P
81 121 51 01010001 Q Q Uppercase Q
82 122 52 01010010 R R Uppercase R
83 123 53 01010011 S S Uppercase S
84 124 54 01010100 T T Uppercase T
85 125 55 01010101 U U Uppercase U
86 126 56 01010110 V V Uppercase V
87 127 57 01010111 W W Uppercase W
88 130 58 01011000 X X Uppercase X
89 131 59 01011001 Y Y Uppercase Y
90 132 5A 01011010 Z Z Uppercase Z
91 133 5B 01011011 [ [ Opening bracket
92 134 5C 01011100 \ \ Backslash
93 135 5D 01011101 ] ] Closing bracket
94 136 5E 01011110 ^ ^ Caret - circumflex
95 137 5F 01011111 _ _ Underscore
96 140 60 01100000 ` ` Grave accent
97 141 61 01100001 a a Lowercase a
98 142 62 01100010 b b Lowercase b
99 143 63 01100011 c c Lowercase c
100 144 64 01100100 d d Lowercase d
101 145 65 01100101 e e Lowercase e
102 146 66 01100110 f f Lowercase f
103 147 67 01100111 g g Lowercase g
104 150 68 01101000 h h Lowercase h
105 151 69 01101001 i i Lowercase i
106 152 6A 01101010 j j Lowercase j
107 153 6B 01101011 k k Lowercase k
108 154 6C 01101100 l l Lowercase l
109 155 6D 01101101 m m Lowercase m
110 156 6E 01101110 n n Lowercase n
111 157 6F 01101111 o o Lowercase o
112 160 70 01110000 p p Lowercase p
113 161 71 01110001 q q Lowercase q
114 162 72 01110010 r r Lowercase r
115 163 73 01110011 s s Lowercase s
116 164 74 01110100 t t Lowercase t
117 165 75 01110101 u u Lowercase u
118 166 76 01110110 v v Lowercase v
119 167 77 01110111 w w Lowercase w
120 170 78 01111000 x x Lowercase x
121 171 79 01111001 y y Lowercase y
122 172 7A 01111010 z z Lowercase z
123 173 7B 01111011 { { Opening brace
124 174 7C 01111100 | Vertical bar
125 175 7D 01111101 } } Closing brace
126 176 7E 01111110 ~ ~ Equivalency sign - tilde
127 177 7F 01111111 &#127; Delete

ascii extend

DEC OCT HEX BIN Symbol HTML Number HTML Name Description
128 200 80 10000000 &#128; Euro sign
129 201 81 10000001
130 202 82 10000010 &#130; Single low-9 quotation mark
131 203 83 10000011 ƒ &#131; ƒ Latin small letter f with hook
132 204 84 10000100 &#132; Double low-9 quotation mark
133 205 85 10000101 &#133; Horizontal ellipsis
134 206 86 10000110 &#134; Dagger
135 207 87 10000111 &#135; Double dagger
136 210 88 10001000 ˆ &#136; ˆ Modifier letter circumflex accent
137 211 89 10001001 &#137; Per mille sign
138 212 8A 10001010 Š &#138; Š Latin capital letter S with caron
139 213 8B 10001011 ‹  &#139; Single left-pointing angle quotation
140 214 8C 10001100 Π&#140; ΠLatin capital ligature OE
141 215 8D 10001101
142 216 8E 10001110 Ž &#142; Latin capital letter Z with caron
143 217 8F 10001111
144 220 90 10010000
145 221 91 10010001 &#145; Left single quotation mark
146 222 92 10010010 &#146; Right single quotation mark
147 223 93 10010011 &#147; Left double quotation mark
148 224 94 10010100 &#148; Right double quotation mark
149 225 95 10010101 &#149; Bullet
150 226 96 10010110 &#150; En dash
151 227 97 10010111 &#151; Em dash
152 230 98 10011000 ˜ &#152; ˜ Small tilde
153 231 99 10011001 &#153; Trade mark sign
154 232 9A 10011010 š &#154; š Latin small letter S with caron
155 233 9B 10011011  › &#155; Single right-pointing angle quotation mark
156 234 9C 10011100 œ &#156; œ Latin small ligature oe
157 235 9D 10011101
158 236 9E 10011110 ž &#158; Latin small letter z with caron
159 237 9F 10011111 Ÿ &#159; Ÿ Latin capital letter Y with diaeresis
160 240 A0 10100000     Non-breaking space
161 241 A1 10100001 ¡ ¡ ¡ Inverted exclamation mark
162 242 A2 10100010 ¢ ¢ ¢ Cent sign
163 243 A3 10100011 £ £ £ Pound sign
164 244 A4 10100100 ¤ ¤ ¤ Currency sign
165 245 A5 10100101 ¥ ¥ ¥ Yen sign
166 246 A6 10100110 ¦ ¦ ¦ Pipe, Broken vertical bar
167 247 A7 10100111 § § § Section sign
168 250 A8 10101000 ¨ ¨ ¨ Spacing diaeresis - umlaut
169 251 A9 10101001 © © © Copyright sign
170 252 AA 10101010 ª ª ª Feminine ordinal indicator
171 253 AB 10101011 «  « « Left double angle quotes
172 254 AC 10101100 ¬ ¬ ¬ Not sign
173 255 AD 10101101 ­ ­ ­ Soft hyphen
174 256 AE 10101110 ® ® ® Registered trade mark sign
175 257 AF 10101111 ¯ ¯ ¯ Spacing macron - overline
176 260 B0 10110000 ° ° ° Degree sign
177 261 B1 10110001 ± ± ± Plus-or-minus sign
178 262 B2 10110010 ² ² ² Superscript two - squared
179 263 B3 10110011 ³ ³ ³ Superscript three - cubed
180 264 B4 10110100 ´ ´ ´ Acute accent - spacing acute
181 265 B5 10110101 µ µ µ Micro sign
182 266 B6 10110110 Pilcrow sign - paragraph sign
183 267 B7 10110111 · · · Middle dot - Georgian comma
184 270 B8 10111000 ¸ ¸ ¸ Spacing cedilla
185 271 B9 10111001 ¹ ¹ ¹ Superscript one
186 272 BA 10111010 º º º Masculine ordinal indicator
187 273 BB 10111011  » » » Right double angle quotes
188 274 BC 10111100 ¼ ¼ ¼ Fraction one quarter
189 275 BD 10111101 ½ ½ ½ Fraction one half
190 276 BE 10111110 ¾ ¾ ¾ Fraction three quarters
191 277 BF 10111111 ¿ ¿ ¿ Inverted question mark
192 300 C0 11000000 À À À Latin capital letter A with grave
193 301 C1 11000001 Á Á Á Latin capital letter A with acute
194 302 C2 11000010 Â Â Â Latin capital letter A with circumflex
195 303 C3 11000011 Ã Ã Ã Latin capital letter A with tilde
196 304 C4 11000100 Ä Ä Ä Latin capital letter A with diaeresis
197 305 C5 11000101 Å Å Å Latin capital letter A with ring above
198 306 C6 11000110 Æ Æ Æ Latin capital letter AE
199 307 C7 11000111 Ç Ç Ç Latin capital letter C with cedilla
200 310 C8 11001000 È È È Latin capital letter E with grave
201 311 C9 11001001 É É É Latin capital letter E with acute
202 312 CA 11001010 Ê Ê Ê Latin capital letter E with circumflex
203 313 CB 11001011 Ë Ë Ë Latin capital letter E with diaeresis
204 314 CC 11001100 Ì Ì Ì Latin capital letter I with grave
205 315 CD 11001101 Í Í Í Latin capital letter I with acute
206 316 CE 11001110 Î Î Î Latin capital letter I with circumflex
207 317 CF 11001111 Ï Ï Ï Latin capital letter I with diaeresis
208 320 D0 11010000 Ð Ð Ð Latin capital letter ETH
209 321 D1 11010001 Ñ Ñ Ñ Latin capital letter N with tilde
210 322 D2 11010010 Ò Ò Ò Latin capital letter O with grave
211 323 D3 11010011 Ó Ó Ó Latin capital letter O with acute
212 324 D4 11010100 Ô Ô Ô Latin capital letter O with circumflex
213 325 D5 11010101 Õ Õ Õ Latin capital letter O with tilde
214 326 D6 11010110 Ö Ö Ö Latin capital letter O with diaeresis
215 327 D7 11010111 × × × Multiplication sign
216 330 D8 11011000 Ø Ø Ø Latin capital letter O with slash
217 331 D9 11011001 Ù Ù Ù Latin capital letter U with grave
218 332 DA 11011010 Ú Ú Ú Latin capital letter U with acute
219 333 DB 11011011 Û Û Û Latin capital letter U with circumflex
220 334 DC 11011100 Ü Ü Ü Latin capital letter U with diaeresis
221 335 DD 11011101 Ý Ý Ý Latin capital letter Y with acute
222 336 DE 11011110 Þ Þ Þ Latin capital letter THORN
223 337 DF 11011111 ß ß ß Latin small letter sharp s - ess-zed
224 340 E0 11100000 à à à Latin small letter a with grave
225 341 E1 11100001 á á á Latin small letter a with acute
226 342 E2 11100010 â â â Latin small letter a with circumflex
227 343 E3 11100011 ã ã ã Latin small letter a with tilde
228 344 E4 11100100 ä ä ä Latin small letter a with diaeresis
229 345 E5 11100101 å å å Latin small letter a with ring above
230 346 E6 11100110 æ æ æ Latin small letter ae
231 347 E7 11100111 ç ç ç Latin small letter c with cedilla
232 350 E8 11101000 è è è Latin small letter e with grave
233 351 E9 11101001 é é é Latin small letter e with acute
234 352 EA 11101010 ê ê ê Latin small letter e with circumflex
235 353 EB 11101011 ë ë ë Latin small letter e with diaeresis
236 354 EC 11101100 ì ì ì Latin small letter i with grave
237 355 ED 11101101 í í í Latin small letter i with acute
238 356 EE 11101110 î î î Latin small letter i with circumflex
239 357 EF 11101111 ï ï ï Latin small letter i with diaeresis
240 360 F0 11110000 ð ð ð Latin small letter eth
241 361 F1 11110001 ñ ñ ñ Latin small letter n with tilde
242 362 F2 11110010 ò ò ò Latin small letter o with grave
243 363 F3 11110011 ó ó ó Latin small letter o with acute
244 364 F4 11110100 ô ô ô Latin small letter o with circumflex
245 365 F5 11110101 õ õ õ Latin small letter o with tilde
246 366 F6 11110110 ö ö ö Latin small letter o with diaeresis
247 367 F7 11110111 ÷ ÷ ÷ Division sign
248 370 F8 11111000 ø ø ø Latin small letter o with slash
249 371 F9 11111001 ù ù ù Latin small letter u with grave
250 372 FA 11111010 ú ú ú Latin small letter u with acute
251 373 FB 11111011 û û û Latin small letter u with circumflex
252 374 FC 11111100 ü ü ü Latin small letter u with diaeresis
253 375 FD 11111101 ý ý ý Latin small letter y with acute
254 376 FE 11111110 þ þ þ Latin small letter thorn
255 377 FF 11111111 ÿ ÿ ÿ Latin small letter y with diaeresis

unicode

유니코드는 Unicode Consortium가 제정하는 문자열 표기 산업 표준으로 문자와 코드가 1:1 매핑 되는 방식입니다

최신 release의 경우 https://www.unicode.org/releases/index.html에서 확인 할수 있습니다

문서를 열어보게 되면 코드 블록 마다 어떤 문자를 담고 있는지 코드 블록에 대한 설명, 코드의 차트, 유니코드를 구현하는 알고리즘 까지 정리 되어있습니다

0000–007F 블록은 ascii 코드와 동일한 코드를 두어 호환이 되도록 하였습니다 (Controls and Basic Latin)


코드 블록 블록 이름 블록 설명

한글에 대한 코드 블록은 한글 자모와 한글 음절로 구분되어있습니다.


유니코드는 전세계 언어들을 다룰수 있도록 나온 표준으로 1byte로 다국어를 포함하기 힘든 상황에서 2byte 3byte 4byte등을 사용하여 값의 구역을 나누고 다국어를 지원하도록 하였고 여러 인코딩 방식이 있습니다

ucs-2

ucs-2은 고정길이(2byte)를 가진 방식으로 늘어나는 유니코드를 포함 할수 없기 때문에 고정길이 4byte를 가진 ucs-4와 가변길이(2byte or 4byte)를 가진 utf-16에 포함 되어 사용이 점차 사라지게 되었습니다.

utf-16 euckr

euckr은 utf-16에 포함되는 한글 완성형 인코딩 방식입니다. 또 다른 완성형 인코딩 방식은 eucjp등 언어별로 존재하는데 utf-8방식과 달리 단일 인코딩 방식이 아니기 때문에 인코딩 방식을 혼동하여 바라지 않는 결과가 나올수 있습니다.

또한 utf-16은 가변길이지만 ucs-2에 기초하여 나왔기 때문에(2byte~4byte) 0~128까지 ascii와 동일한 값을 가지만 데이터의 길이는 2byte로 가져가기 때문에 데이터를 아낄수 있는 부분에서 utf-8보다 낭비를 하게됩니다

utf-8

utf-8은 가변길이(1~4byte)라는 특징을 가졌고 호환성이 좋기 때문에 가장 많이 사용됩니다. `EF BB BF`값을 가진 Byte Order Mark(BOM)를 문서 가장 처음에 표기하여 문서가 utf-8임을 나타내기도 하는데 권장되지 않습니다.

html5의 표준 인코딩 방식은 utf-8이고 일반적으로 유니코드라고 하면 utf-8방식을 말합니다.

utf-8의 장점은 영어의 경우 1byte 한글의 경우 3byte 처럼 가변적으로 문자의 block에 따라 가변적으로 문자를 기록 함으로서 데이터를 아낄수 있다는 장점과 단일 인코딩 방식이기 때문에 인코딩 방식을 혼동해서 생길수 있는 문제가 없어졌습니다.

utf-8 정규화 비정규화 차이

NFC NFD NFKC NFKD 비고
각(AC01) 각 (AC01) 각 (1100 + 1161 + 11A8) 각 (AC01) 각 (1100 + 1161 + 11A8) 한글음절
ㄱ (1100) ᄀ (1100) ᄀ (1100) ᄀ (1100) ᄀ (1100) 한글자모
ㄱ (3131) ㄱ (3131) ㄱ (3131) ᄀ (1100) ᄀ (1100) 호환자모
㈀ (3200) ㈀ (3200) ㈀ (3200) (ㄱ) ( '(' + 1100 + ')' ) (ㄱ) ( '(' + 1100 + ')' ) 자모괄호기호
㈎ (320E) ㈎ (320E) ㈎ (320E) (가) ( '(' + AC00 + ')' ) (가) ( '(' + 1100 + 1161 +,')' ) 음절괄호기호
㈝㈝ (321D) ㈝㈝ (321D) ㈝㈝ (321D) (오전) ( '(' + C624 + C804 + ')' ) (오전) ( '(' + 110B + 1169 + 110C + 1165 + 11ab + ')' ) 오전괄호기호
㉠ (3260) ㉠ (3260) ㉠ (3260) ᄀ (1100) ᄀ (1100) 자모원기호
㉮ (326E) ㉮ (326E) ㉮ (326E) 가 (AC00) 가 (1100 + 1161) 음절원기호
ᄀ (FFA1) ᄀ (FFA1) ᄀ (FFA1) ᄀ(1100) ᄀ (1100) 자모반각기호

유니코드 정규화의 경우 NFD, NFC, NFKD, NFKC 방식이 있습니다.


맥의 경우 NFD(Normalization Form Canonical Decomposition 정준 분해)방식을 사용하고 있습니다

맥에서 파일을 저장하고 윈도우즈에서 열어보려고 할경우 ㄱㅏㄴㅏㄷㅏ.txt처럼 되는데 자음과 모음을 분해하여 저장하는 방식을 사용하고 있기 때문입니다.

그 반대로 일반적으로 사용되는 NFC(Normalization Form Canonical Composition 정준 결합)의 경우 자음 모음이 결합된 방식입니다.

NFD형식 예) `한 (U+D55C) → ᄒ (U+1112) + ᅡ (U+1161) + ᆫ (U+11AB)`

NFC형식 예) `ᄒ (U+1112) + ᅡ (U+1161) + ᆫ (U+11AB) → 한 (U+D55C)`

NFKC, NFKD의 경우 호환 분해 호환 결합으로 한글 특수 문자를 포합하여 분해 결합을 진행합니다.

mysql chracter set과 collation

일반적으로 mysql chracter set의 경우 utf-8을 사용하게 되며 정렬 순서를 나타내는 collation의 경우 utf8-general-ci을 기본으로 사용합니다

utf8-general-ci 방식은 정렬이 빠르다는 장점이 있지만 utf8_unicode_ci 보다 정확도가 떨어진다는 단점이 있습니다 utf8mb4_general_ci 2010년 3월 24일에 utf8mb4 라는 charset을 추가된(MYSQL 5.5.3) 방식으로 4byte 문자를 지원하는 방식입니다.

이외에도 다양한 정렬 방식과 여러 종류의 chracter set이 존재하고 utf-16또한 정렬방식이 몇가지 존재 하지만 많이 사용되진 않고 있습니다. `SHOW COLLATION;`을 통해서 사용하고 있는 mysql버전에서 사용할수 있는 collation을 확인할수 있고 default로 무엇이 설정되어있는지 확인할수 있습니다.

utf8mb4_0900_as_ci 처럼 나타낼때 뒤의 as, ai, cs, ci의 경우 accent문자와 case에 Sensitivity한지 InSensitivity한지를 나타냅니다.

  • as는 accent에 sensitivity하다는 것입니다.
  • ai는 accent에 Insensitivity하다는 것입니다.
  • cs는 case에 sensitivity하다는 것입니다.
  • ci는 case에 Insensitivity하다는 것입니다.

sensitivivity하다는 것은 정렬에 accent(발음기호), case(대소문자)를 사용한다는 것이고 Insensitivity하다는 것은 사용하지 않는 다는 것입니다.

Insensitivity할 경우 정렬에 사용되지 않기 때문에 unique, primary key에서 사용할 경우 같은 값으로 인식되어 duplicated 문제가 발생할수 있습니다.

utf8mb4_general_ci의 경우 accent와 case둘다 Insensitivity하기 unique한 값에 해당하는 collation을 사용할 경우 고려하여 코드를 설계해야합니다.

emoji 문자 문제

emoji라고 불리는 이모티콘 기호는 utf-8에서는 \xF0\x9F\x98\x80부터 utf-16에서 1F600부터의 범위를 있습니다.

언어셋이 다르다면 같은 emoji를 나타내더라도 다른값을 가지게 됩니다.

insert into encoding (utf8,utf16) values ("😀", "😀");
select hex(`utf8`), hex(utf16) from encoding;

위 처럼 다른 언어셋을 가진 테이블에 입력 하게 되면 F09F9880 D83DDE00 처럼 다른 값이 나오게 됩니다.


public class EmojiTest {
    @Test
    public void test01() {
        final String em = "\ud83d\ude00";
        System.out.println("em = " + em);
    }

    @Test
    public void test02() {
        byte[] a = {(byte) 0xF0,(byte)0x9F,(byte)0x98,(byte)0x80};
        System.out.println("em = " + new String(a));
    }
}

java에서 위처럼 코드를 작성하게 된다면 둘다 😀를 출력 하게 됩니다


public final class EmojiConverter {
    private static Pattern EMOJI_PATTERN = Pattern.compile(
                    "[\ud800\udc00-\udbff\udfff]",
                    Pattern.UNICODE_CASE | Pattern.CANON_EQ | Pattern.CASE_INSENSITIVE);

    public static class EmojiSerializer extends JsonSerializer<String> {
        @Override
        public void serialize(String value, JsonGenerator gen, SerializerProvider provider)
                throws IOException {

            if(Strings.isNullOrEmpty(value)){
                gen.writeString("");
                return;
            }

            Matcher matcher = EMOJI_PATTERN.matcher(value);
            String cleanString = matcher.replaceAll("");
            gen.writeString(cleanString);

        }
    }
}

위와 같은 방식으로 컨버터를 만들어서 emoji를 제거 해서 입력 시킬수도 있습니다.

accent 문자 문제

È 문자는 E와 다르게 accent(Diacritic 발음 구별 기호)기호가 붙어있습니다.

이러한 형태도 정규화가 된 형태이며 한글의 nfd와는 다르게 값을 단순히 더한 값은 아니고 유니코드 표를 따라가고 있습니다.

` E + ̀ ` = U+0045 + U+0300 = U+00C8


https://github.com/yu-young-hoon/java-encoding/blob/master/src/test/java/AccentTest.java

    @Test
    public void accent01() {
        String nfc = "\u00c8";
        // 분해
        String nfcToNfd = Normalizer.normalize(nfc, Normalizer.Form.NFD);
        Assert.assertNotEquals(nfc, nfcToNfd);

        // 결합
        String nfdToNfc = Normalizer.normalize(nfcToNfd, Normalizer.Form.NFC);
        Assert.assertEquals(nfc, nfdToNfc);
    }

정규화가 된 상태의 È를 분해해서 결합된 것과 비교하게 된다면 Not equals이며 다시 결합하여 비교하면 equals가 되기 때문에 accent 뿐만 아니라 한글과 같이 분해가 되는 문자열의 정규화 분해결합은 신경써야합니다.


    @Test
    public void accent02() {
        String nfc = "\u00c8";

        String nfcToNfd = Normalizer.normalize(nfc, Normalizer.Form.NFD);
        String removedAccent = nfcToNfd.replaceAll("[\\p{InCombiningDiacriticalMarks}]", "");

        String removedAccent2 = StringUtils.stripAccents(nfcToNfd);
        Assert.assertEquals("E", removedAccent);
        Assert.assertEquals("E", removedAccent2);
    }

accent를 제거하는 방법을 두가지 소개하자면 분해후에 정규식으로 제거하거나 apache common의 StringUtils의 stripAccents를 사용할수 있습니다. 결과값은 nfd가 된 형태이기 때문에 비교하거나 다시 사용해야할경우 nfc를 다시 해야합니다.


다른 언어와 마찬가지로 한글에도 accent기호가 있습니다.

방음(방점)으로 알려진 분음 부호 `>` ` 〮` ` 〯`를 사용하여 한글 에서 중 한국어를 위한 악센트를 표시할수 있습니다.

한글의 accent기호는 결합된 형태가 있는지는 잘 모르겠고 위처럼 제거를 할수 있습니다.

html escape

    @Bean
    public WebMvcConfigurerAdapter webConfigurerAdapter() {
        return new WebMvcConfigurerAdapter() {

            @Override
            public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
                super.configureMessageConverters(converters);

                converters.add(htmlEscapingConveter());
            }

            private HttpMessageConverter<?> htmlEscapingConveter() {
                ObjectMapper objectMapper = new ObjectMapper();
                MappingJackson2HttpMessageConverter htmlEscapingConverter = new MappingJackson2HttpMessageConverter();

                objectMapper.getFactory().setCharacterEscapes(new HTMLCharacterEscapes());
                htmlEscapingConverter.setObjectMapper(objectMapper);

                return htmlEscapingConverter;
            }
        };
    }

java에서 dto를 통해 view로 json 데이터를 꺼내줄때 html에 영향을 주는 문자열을 `{"name":"<하하"}` 처럼 escape하게 됩니다


$('<div/>').html(text).text();

자바스크립트에서 위처럼 dom을 생성하고 html안에 넣은후 결과를 다시 텍스트로 받아오는 방식으로 escape된 문자를 다시 되돌릴 수 있습니다

참고링크