sitelink1 | |
---|---|
sitelink2 | |
sitelink3 | http://1 |
sitelink4 | http://ko |
sitelink5 | http://jongsclub.com/webedit/studyView.jsp?num=28 |
sitelink6 | http://sitelink1 |
개요
- utf-8 은 유니코드
를 위한 『?堧?문자 인코딩 방식중 하나로 켄 톰프슨과 롭 파이크가 만들었다.
- 유니코드 한문자를 표시하기 위해 1byte~4byte 까지 가변적으로 표현한다.
- U+0000부터 U+007F 범위에 있는 아스키 문자들은 UTF-8에서 1바이트만으로 표시된다. 4바이트로 표현되는 문자는 모두 기본 다중언어 평면(BMP) 바깥의 유니코드 문자이며, 거의 사용되지 않는다.
구조
- U+007F(0~127) 까지의 문자는 7비트 아스키
문자와 동일하게 표시된다.
- U+007F 이후의 문자는 4byte 까지의 비트 패턴으로 표시되며 7비트 아스키 문자와 혼동되지 않게 하기 위해 모든 바이트의 최상위 비트는 1 이다.
코드 범위 | UTF-16BE 표현 | UTF-8 표현 | 설명 |
---|---|---|---|
000000 ~00007F | 00000000 0xxxxxxx | 0xxxxxxx | 아스키와 동일한 범위 |
000080 ~0007FF | 00000xxx xxxxxxxx | 110xxxxx 10xxxxxx | 첫바이트는 110 으로 시작하고, 나머지 바이트는 10으로 시작함 |
000800 ~00FFFF | xxxxxxxx xxxxxxxx | 1110xxxx 10xxxxxx 10xxxxxx | 첫바이트는 1110으로 시작하고 , 나머지는 10으로 시작함 |
010000 ~10FFFF | 110110yy yyxxxxxx 110111xx xxxxxxxx | 11110zzz 10zzxxxx 10xxxxxx 10xxxxxx | UTF-16![]() |
![]() |
utf-8 인코딩 예제 '위'(한글) --> U+C7404(유니코드) (첫 128 문자는 1바이트로 표시되고, 그 다음 1920 문자 (판독 기호가 붙은 라틴 문자, 그리스 문자, 키릴 문자, 콥트 문자, 아르메니아 문자, |
관련자료
utf-8 체크
-
- 입력된 문자열이 utf-8로 인코딩 되었는지 하기 위해서는 utf-8 의 인코딩 패턴을 조사한다. 즉 바이트 배열의 패턴이 utf-8 인코딩 패턴(1110xxxx 10xxxxxx 10xxxxxx)과 맞는지를 비교한다.
- 000080 ~0007FF 범위의 110xxxxx 10xxxxxx 패턴 일 경우엔 중복되는 코드값으로 인해 utf-8 인코딩인지 아닌지 체크하는것은 사실상 불가능하다.
110xxxxx 10xxxxxx 패턴의 utf-8 판독
110xxxxx 10xxxxxx 패턴의 코드일 경우 utf-8로 인코딩 되었는지 아닌지를 확인하는것은 사실상 불가능하다.
하지만 utf-8로 인코딩 되면 아스키 영역은 1byte 한글은 3byte 내지는 4byte를 사용하므로 단순하게 생각하여 2 바이트 110xxxxx 10xxxxxx 패턴의 경우는 utf-8 인코딩이 아님을 유추할수 있다.
판독 기호가 붙은 라틴 문자, 그리스 문자, 키릴 문자, 콥트 문자, 아르메니아 문자, 히브리 문자, 아랍 문자 등이 입력되면 판독 오류가 발생하겠지만 이는 무시해도 좋을듯 하다. - Null 값의 경우 자바에서는 변형된 utf-8 인코딩 방식에 따라 1byte가 아닌 2byte(11000000 10000000)로 표기하므로 110xxxxx 10xxxxxx 의 경우 null 인지 비교해야 정확한 판독이 가능하지만 입력된 값의 인코딩여부를 판독하므로 상황에 따라서는 무시해도 괜찮을듯 하다.
- CJK 2바이트+한글 2바이트 가 '1110xxxx 10xxxxxx 10xxxxxx 0xxxxxxx' 와 같은 패턴으로 utf-8 3바이트 와 아스키1바이트 조합과 유사할 경우 앞자리 3바이트를 유니코드 형태로 역치환 해서 000800 ~00FFFF 범위가 맞는지 체크한다.
utf-8 인코딩 체크 예제
![]() |
utf-8 인코딩 판독 예제 1. '위'.getBytes("ISO-8859-1") : -20 , -100, -124 |
package util; import java.io.UnsupportedEncodingException; /** * <pre> * 작성자 : 이종희 (qola@naver.com) * JAlbum.com (http://jalbum.net/download.jsp?ref=list) 소스 참고함. * <b>특정 문자열이 utf-8 인코딩인지 아닌지 체크한다.</b> * * utf-8 인코딩 패턴인 110xxxxx 10xxxxxx , 1110xxxx 10xxxxxx 10xxxxxx 인지 비교한다. * 2바이트 (110xxxxx 10xxxxxx) 패턴의 유니 코드 중복으로 인해 100% 검증할수 없지만 * 한글의 경우 3byte 로 표기 되므로 2바이트 패턴일 경우 utf-8 인코딩이 아닌것으로 간주한다. * * 따라서 000080 ~0007FF 영역의 라틴 문자, 그리스 문자, 키릴 문자, 콥트 문자, * 아르메니아 문자, 히브리 문자, 아랍 문자 등은 utf-8 인코딩을 비교할수 없다. * * 수정된 utf-8의 의한 null값 u0000 은 11000000 10000000 로 표기되지만 무시하기로 한다. * * </pre> */ public class UTFUtil { public static boolean isUTF8(String str) throws Exception{ byte[] bytes=str.getBytes("ISO-8859-1"); return isUTF8(bytes,0,bytes.length); } public static boolean isUTF8(byte[] buf, int offset, int length) { boolean yesItIs = false; for (int i=offset; i<offset+length; i++) { if ((buf[i] & 0xC0) == 0xC0) { // 11xxxxxx 패턴 인지 체크 int nBytes; for (nBytes=2; nBytes<8; nBytes++) { int mask = 1 << (7-nBytes); if ((buf[i] & mask) == 0) break; }
//CJK영역이나 아스키 영역의 경우 110xxxxx 10xxxxxx 패턴으로 올수 없다. if(nBytes==2) return false; // Check that the following bytes begin with 0b10xxxxxx for (int j=1; j<nBytes; j++) { if (i+j >= length || (buf[i+j] & 0xC0) != 0x80) return false; } if(nBytes==3){ // 유니코드 형태로 역치환 해서 0x0800 ~ 0xFFFF 사이의 영역인지 체크한다. char c = (char) (((buf[i] & 0x0f) << 12) + ((buf[i+1] & 0x3F) << 6) + (buf[i+2] & 0x3F)); if(!(c >= 0x0800 && c <= 0xFFFF)){ return false; } } yesItIs = true; } } return yesItIs; } }
한글 URL 사용시 문제 발생 케이스
- IE에는 유니코드 지원을 위해 기본적으로 URL을 UTF-8 로 전송해 주지만 옵션 사항이므로 사용자 마다 환경이 다를수 있다.
- utf-8로 다시 보내는 기능을 제공하지 않는 브라우저도 존재한다.
- RSS 리더와 같은 별도의 클라이언트를 사용할경우 서버인코딩, 클라이언트, 브라우저 인코딩 이 모두 일치하여야만 한다.
해결책
- REQUEST 요청시 URL이 UTF-8 인코딩 방식인지 아닌지를 체크하여 UTF-8 방식이면 "ISO-8859-1 --> UTF-8" 형태로 인코딩 변환을 해주고 그렇지 않으면 "ISO-8859-1 --> MS949" 로 인코딩 변환을 시켜준다.
구현 예제
- APACHE MOD_REWRITE
- 아래 예와 같이 MOD_REWRITE를 이용해 특정 패턴의 URL을 REWRITE 시킨다.
RewriteEngine on # // http://tag.naver.com/tag2/한글 --> http://tag.naver.com/tag/index.jsp?tag=한글 RewriteRule ^/tag2/(.+)$ /tag/index.jsp?tag=$1 [PT]
- 아래 예와 같이 MOD_REWRITE를 이용해 특정 패턴의 URL을 REWRITE 시킨다.
- JSP 샘플
- isUTF8() 체크 메소드를 이용해 파라메터의 인코딩을 각각 처리해준다.
<%@page language="java" contentType="text/html;charset=utf-8"%> <%@page import="java.net.URLEncoder, util.*" %> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> </head> <body> index.jsp... <br> <% String uri=request.getRequestURL().toString(); String tag=request.getParameter("tag"); byte[] tagBytes=tag.getBytes("ISO-8859-1"); out.println("byte[]==="); for(int i=0;i<tagBytes.length;i++){ out.println(tagBytes[i]+","); } out.println("<br>"); boolean isUTF8=UTFUtil.isUTF8(tag); if(isUTF8) { out.println(util.Enco.toUtf(tag)); out.println("<br>"); out.println(isUTF8); }else{ out.println(new String(tag.getBytes("ISO-8859-1"),"ms949")); out.println("<br>"); out.println(isUTF8); } %> <a href=""http://tag_test.com/tag2/한글">http://tag_test.com/tag2/한글</a><br> <a href=""http://tag_test.com/tag2/코리아">http://tag_test.com/tag2/코리아</a><br> <a href=""http://tag_test.com/tag2/위">http://tag_test.com/tag2/위</a> </body> </html>
- isUTF8() 체크 메소드를 이용해 파라메터의 인코딩을 각각 처리해준다.