[PHP] 한국어 조사 처리 함수

트위터에서 녹풍님의 [PHP] 명사 뒤에 나오는 ‘은는이가을를’ 판단할 수 있게 해 주는 함수를 봤는데, 조사가 없는 글자를 판단하기 위해 죄다 문자열에 넣어두는 식으로 구현했더군요. 그런데 유니코드는 완성형과 달리 규칙적인 문자 체계라서 코드만으로도 조사의 여부를 판단할 수 있기 때문에 굳이 이런 식으로 번거롭게 작성하지 않아도 됩니다.

그래서 대략 10년 전쯤에 작성했던  한국어 조사를 판단해주는 함수의 자바스크립트로 코드를 가져와서 PHP로 만들어보았습니다. 또한 아마도 메시지 템플릿을 처리할 때 편하게 사용할 수 있도록 "{은}"과 같이 중괄호를 조사 양쪽에 씌워두면 해당 부분을 자동으로 판단해서 치환해주도록 바꿨습니다. 편의를 위해 “은” 또는 “는”, “이” 또는 “가”, “을” 또는 “를” 중 무엇을 사용해도 상관없도록 했습니다.

클로저를 사용했기 때문에 PHP 5.3 이상이 필요하지만, preg_replace_callback에 사용된 콜백 함수를 따로 빼면 조금 더 하위 버전에서도 사용할 수 있습니다. 파일의 인코딩 및 mb_* 계열 함수 내부 인코딩은 UTF-8으로 설정되어 있다고 가정했습니다.

function josa($str) {
    $josa = '이가은는을를과와';

    return preg_replace_callback(
        "/(.)\\{([{$josa}])\\}/u",
        function($matches) use($josa) {
            list($_, $last, $pp) = $matches;

            $pp1 = $pp2 = $pp;
            $idx = mb_strpos($josa, $pp);
            ($idx % 2) ? ($pp1 = mb_substr($josa,--$idx,1)) : ($pp2 = mb_substr($josa,++$idx,1));

            if (strlen($last) > 1) {
                $code = (hexdec(bin2hex($last)) - 12) % 28;
            } else {
                $code = (strpos('2459', $last) > -1) ? 0 : 1;
            }

            return $last.($code ? $pp1 : $pp2);
        },
        $str
    );
}

// 사용예
josa('한글{와} 컴퓨터의 한글2015{은} 언제 출시될까.');

Leave a Reply