메뉴 건너뛰기

Dev tips

PHP 한글영타를 한글로...

taknim 2005.09.01 20:16 조회 수 : 9088 추천:2216

한글영타를 한글로...


기술적인 거...에 특별한게 저한테 있을리는 없구요... ^^;;
늘 그렇듯이 막코딩의 산물입니다.

"안녕하세요?" 를 "dkssudgktpdy?" 로 쳤을때 그걸 출력해주는거죠;;
현재 윈도우즈에서 쓰는 CP949 혹은 UHC라 불리는 확장완성형으로는 자모분리를 할 수 없어서 유니코드를 이용했습니다. UTF-8은 아니고, UCS-2 라 불리는 Unicode 2.0 체계입니다.

원리부터 간단히 설명을 드리면...

유니코드에 쓰이는 한글 초성은 순서대로...
ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ

중성은...
ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ

종성은...
없음 ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ

의 순서입니다.
이제 글자를 조합해서 코드를 만들면...
코드 = 0xAC00 + 초성순서번호(0번부터)*중성갯수*종성갯수 + 중성순서번호*종성갯수 + 종성순서번호
가 됩니다. 뭐... 이 정도의 정보만 있으면 누구나 만드실 수 있겠지만... 의외로 유니코드에 대한 정보가 명확하게 정의된 걸 찾기가 힘들어서(방대해서 그럴수도) 저 나름대로는 꽤 고생하며 만들었습니다. 기능 구현이 우선이라 함수가 깔끔하지 못하네요. 조금 더 깔끔하게 해주시면 감사하겠습니다. :)

아... 다들 아시겠지만... 마지막의 iconv 함수부분에서 UTF-8 대신에 CP949를 적으시면 확장완성형 형태의 결과물또한 얻으실 수 있습니다. (EUC-KR은 글자수가 조합형 및 유니코드의 절반도 안됩니다. -_-)

function eng2han ($str)
{
        static $convTable = null;
        if (is_null($convTable))
        {
                // 초성
                $convTable[] = array('r'=>0, 'R'=>1, 's'=>2, 'e'=>3, 'E'=>4, 'f'=>5, 'a'=>6, 'q'=>7, 'Q'=>8, 't'=>9, 'T'=>10, 'd'=>11, 'w'=>12, 'W'=>13, 'c'=>14, 'z'=>15, 'x'=>16, 'v'=>17, 'g'=>18);

                // 중성
                $convTable[] = array('k'=>0, 'o'=>1, 'i'=>2, 'O'=>3, 'j'=>4, 'p'=>5, 'u'=>6, 'P'=>7, 'h'=>8, 'hk'=>9, 'ho'=>10, 'hl'=>11, 'y'=>12, 'n'=>13, 'nj'=>14, 'np'=>15, 'nl'=>16, 'b'=>17, 'm'=> 18, 'ml'=>19, 'l'=>20);

                // 종성
                $convTable[] = array('r'=>1, 'R'=>2, 'rt'=>3, 's'=>4, 'sw'=>5, 'sg'=>6, 'e'=>7, 'f'=>8, 'fr'=>9, 'fa'=>10, 'fq'=>11, 'ft'=>12, 'fx'=>13, 'fv'=>14, 'fg'=>15, 'a'=>16, 'q'=>17, 'qt'=>18, 't'=>19, 'T'=>20, 'd'=>21, 'w'=>22, 'c'=>23, 'z'=>24, 'x'=>25, 'v'=>26, 'g'=>27);
        }

        $retText = array(); $hanChar = '';
        $len = strlen($str);
        for ($idx = 0; $idx < $len; $idx++)
        {
                if ( is_numeric($convTable[0][$str[$idx]]) )
                {
                        // 초성
                        $hanChar = 0xAC00 + $convTable[0][$str[$idx]]*21*28;
                        $idx++;
                        
                        // 중성
                        if ( $convTable[1][$str[$idx].$str[$idx+1]] ) {
                                $hanChar += $convTable[1][$str[$idx].$str[$idx+1]]*28;
                                $idx+=2;
                        } elseif ( is_numeric($convTable[1][$str[$idx]]) ) {
                                $hanChar += $convTable[1][$str[$idx]]*28;
                                $idx++;
                        }

                        // 종성
                        if ( $convTable[2][$str[$idx].$str[$idx+1]] && (!is_numeric($convTable[1][$str[$idx+2]]) || $idx+2 >= $len) ) {
                                $hanChar += $convTable[2][$str[$idx].$str[$idx+1]];
                                $idx++;
                        } elseif ( $convTable[2][$str[$idx]] && (!is_numeric($convTable[1][$str[$idx+1]]) || $idx+1 >= $len) ) {
                                $hanChar += $convTable[2][$str[$idx]];
                        } else {
                                $idx--;
                        }

                        $hanChar = dechex($hanChar);
                        $hanChar = iconv("UCS-2", "UTF-8", chr(hexdec(substr($hanChar, 0, 2))).chr(hexdec(substr($hanChar, -2))));

                        $retText[] = $hanChar;
                }
                else
                {
                        $retText[] = $str[$idx];
                        continue;
                }
        }

        return implode('', $retText);
}

테스트
echo eng2han('dkssudgktpdy?');

결과
안녕하세요?