메인 작업을 하다보면 거의 10중 8 이상 게시판 추출글 작업을 하게 된다.
공지사항이라던지 새소식 등의 최신글을 추출해서 메인에 뿌려주는 부분인데 대부분 xml 데이터 연동, 또는 LCDS, ajax / javascript 연동 등 외부 데이터를 호출하여 동적으로 뿌려주게 된다.
이 때 데이터에서 입맛에 맞게 뿌려줄 문자열 만큼만 내려준다면야 좋겠지만 그런 경우는 거의 없고, 또 그렇게 되면 추후 유지보수에서 문제가 된다.
그래서 종종 메인에서 들쭉 날쭉한 글목록이나 쌩뚱맞게 글이 반쪽만 잘려 나오는 것을 볼 때가 있다.
아마도 반쪽만 나오는 경우는 TextField 의 길이를 강제해서 글을 자른 경우일 것이고, 들쭉날쭉한 경우는 뿌려줄 문자열을 length 로 자른 경우일 것이다.
TextField 의 길이를 강제하는 경우는 생각해볼 필요도 없고-
length로 자르는 경우를 보자면
1234567890
가나다라마바사아자차
위에서 보면 둘다 length value는 10이다. (10글자니까)
하지만 길이를 보자면 구지 자세히 볼 것도 없이 틀리다.
// 숫자
12345678901234567890
가나다라마바사아자차// 영문
abcdefghijklmnopqrst
가나다라마바사아자차
위는 숫자 20 글자, 영문 20 글자와 한글 10글자의 길이를 비교한 것이다.
length value 로 보자면 딱 두배 차이인 것이다.
이로써 한글은 숫자 두글자 또는 영문 두글자의 길이를 차지한다 라고도 볼 수 있을 것이다.
실지로 한글 한글자는 영문, 숫자, 대부분의 특수기호 한글자가 1byte를 차지할때 2byte를 사용한다.
확인해 보자.
var byteArray:ByteArray = new ByteArray();
byteArray.writeMultiByte("한", "euc-kr");
trace(byteArray.length.toString());
byteArray 를 생성하고 “한” 이라는 한글을 바이트 스트림에 썼다.
그리고 length를 찍어보면 2가 찍힌다.
마찬가지로 “한” 대신에 영문, 숫자, 특수기호 들을 넣어보면 글자가 차지하는 byte 를 알 수 있다.
이를 이용하면 문자열의 문자 하나하나가 한글인지 아닌지(2byte 인지 아닌지)를 체크해 볼 수 있다.
private function isKor(ch:String):Boolean {
var byteArray:ByteArray = new ByteArray();
byteArray.writeMultiByte(ch, "euc-kr");
return byteArray.length == 2;
}
심플하게 넘어온 문자의 바이트가 2이면 true, 아니면 false를 리턴하는 메소드다.
이 메소드는 ch 매개변수가 한 글자가 아닌 여러글자의 문자열이면 원하는 결과를 리턴하지 못한다.
좀 더 확실하게 구현하고 싶다면 넘어온 ch 매개변수의 length 를 체크해서 처리해 주는 것도 좋을 듯.
이 메소드를 사용하는 예는 아래-
var testString:String = "한글 or English?";
var i:int, len:int = testString.length;
for (i = 0; i < len; i++)
trace(isKor(testString.charAt(i)));
결과는 당연히 true, true, false, false, false, false, false, false, false, false, false, false, false, false.
(공백도 1byte 라는 것도 알 수 있다.)
여기까지가 준비운동이었고 실제로 바이트로 문자열을 자르는 메소드는 아래와 같다.
private function cutStringBytes(str:String, bytes:Number, ellips:Boolean = true):String {
var count:int;
var resultString:String = "";
var maxSize:int = bytes + 1;
var i:int, len:int = str.length;
for (i = 0; i < len; i++) {
if(isKor(str.charAt(i))) {
if(count + 2 >= maxSize) break;
count += 2;
resultString += str.charAt(i);
} else {
if(count + 1 >= maxSize) break;
count += 1;
resultString += str.charAt(i);
}
}
if(str.length > resultString.length && ellips)
resultString += "..";
return resultString;
}
지금 까지의 설명 만으로도 충분하지만 보태자면 앞서 만들었던 isKor 메소드를 이용해서 문자열의 각 글자마다 byte를 체크한 후에 1바이트면 count 를 1 올려주고 2바이트면 count 를 2 올려주는 식으로 체크하고 있다. 매개변수 중 ellips 는 글이 잘려나갔을 경우 끝에 ..을 붙여줄지 여부이다. (보통은 붙여주어서 뒤에 글이 더 있음을 알려주는 것이 좋다.)
마지막으로 아래와 같이 테스트 해보면 길게 떠들었던 부분이 확- 오지 않을까 싶다.
trace(cutStringBytes("12345678901234567890", 10));
trace(cutStringBytes("가나다라마바사아자차", 10));
또 참고로 덧붙이자면 디자인상 한 문자열에 두개의 폰트가 쓰였을 경우에 (주로 영문 따로 한글 따로 폰트를 사용한 디자인) 위의 isKor 메소드를 이용해서 한글, 영문을 구분할 수는 있지만 절대 비추다.
영문, 한글 폰트는 대부분 폰트의 baseline 이 같지 않다. 이 말은 문자열의 글자들이 위아래로 춤을 추는 모양이 나올 수가 있다는 것이다.
구지 setTextFormat 이 아닌 문자열의 한글, 영문을 구분해서 따로 TextField 를 생성하고 위치를 잡아줄 수도 있지만 구지 그렇게 까지 해야 하는 경우는 선뜻 이해가 안간다.
이 경우에는 디자이너와 협희해서 한종류 폰트로 처리하는 것을 추천.
