본문으로 바로가기

KoreanChosungSearch 라이브러리

category Open source/KoreanChosungSearch 2022. 2. 1. 16:51

| 이유

유나이트 위키 에서 포켓몬 검색 기능 구현을 시도하다가 초성검색이 제대로 되지 않아 다소 어려움을 겪었다.

'한ㄱ' 과 '한글' 을 비교하면 true를 반환하는 초성 검색 기능을 구현하고 싶었는데, 

시중에 있는 한글 검색 클래스를 사용하자니 오로지 초성으로만 검색해야만 한다거나, 원하는 기능을 구현하기 위해선 쓸데 없이 꽤 장황한 코딩을 해야만 했다. 

라이브러리로 구현해서 이걸 필요할 때 마다 쓰면 편하지 않을까? 하는 생각에 라이브러리를 만들게 되었다.

| Git

KCS.match() 메소드는 '검색어' , '비교대상' 두 가지의 String 변수를 받는다.

'검색어' 에 초성만 포함된 글자가 있는지 검사 후, 만약 초성이 있다면 '비교대상'의 글자에서 '검색어' 글자의 초성 인덱스에 있는 글자를 초성만 있는 글자로 바꾼다.

코드를 말로 설명하니 오히려 더 복잡하고 장황하다. 위 깃 링크의 코드를 보는게 나을 것이다.

첫 오픈소스 이기 때문에 코드 또한 어설픈 면이 많지만, 혹여나 궁금하신 분 께서는 위 깃 링크의 코드를 살펴봐주시길..

 

사용예시는 다음과 같다. ( Adapter의 Filter에 적용 )

| Publish

Jitpack 가이드 를 따라 배포하였다. 이번 라이브러리를 배포하며 Readme 를 작성하는 법에 대해 조금 배우게 되었다.

Jitpack을 이용한다면 개인 레포지토리에 푸쉬 후 Gradle에 두줄만 넣는다면 배포완료로, 상당히 간단한 방식으로 라이브러리를 배포할 수 있다. 

 

코드는 다음과 같다.

class KCS {

    companion object{

    private const val UNICODE_HangulStart = 44032
    private const val UNICODE_HangulLast = 55203


    private val CHO = listOf("ㄱ","ㄲ","ㄴ","ㄷ","ㄸ","ㄹ","ㅁ","ㅂ","ㅃ", "ㅅ","ㅆ","ㅇ","ㅈ","ㅉ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ")
    private val JOONG = listOf("ㅏ","ㅐ","ㅑ","ㅒ","ㅓ","ㅔ","ㅕ","ㅖ","ㅗ","ㅘ", "ㅙ","ㅚ","ㅛ","ㅜ","ㅝ","ㅞ","ㅟ","ㅠ","ㅡ","ㅢ","ㅣ")
    private val JONG = listOf("","ㄱ","ㄲ","ㄳ","ㄴ","ㄵ","ㄶ","ㄷ","ㄹ","ㄺ","ㄻ","ㄼ", "ㄽ","ㄾ","ㄿ","ㅀ","ㅁ","ㅂ","ㅄ","ㅅ","ㅆ","ㅇ","ㅈ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ")

    /*
    Korean unicode formular = (cho * 21 + joong) * 28 + jong + 0xAC00
    */

    fun match(query:String,tocompare:String):Boolean{
        var matched=false

        if( tocompare.length >= query.length && !(isOnlyCho(query).isNullOrEmpty()) ){

            val choindexes = isOnlyCho(query)
            val compareChars = tocompare.toCharArray()

            for(i in choindexes){
                val cho = getCho(tocompare[i].toString())
                compareChars[i]= cho.single()
            }
            val compareReplaced = String(compareChars)

            if(compareReplaced.contains(query)){
                matched= true
            }

        }else if(tocompare.contains(query)){
            matched = true
        }
        return matched
    }

    fun isOnlyCho(word:String):ArrayList<Int>{
        val choindexList = ArrayList<Int>()

        for(cho_ in CHO){
            if(word.contains(cho_)){
                var same_index = word.indexOf(cho_)
                while(same_index>=0){
                    choindexList.add(same_index)
                    same_index = word.indexOf(cho_,same_index+1)
                }
            }
        }
        return choindexList
    }

    fun getCho(word:String):String{
        var word_cho = word

        if(isHangeul(word.single())){
            val charuni = word[0]
            val cho_uniIndex = ((charuni.code-0xAC00) / 28 /21).toChar().code
            word_cho = CHO[cho_uniIndex]
        }

        return word_cho
    }

    fun getJoong(word:String):String{
        var word_joong = word

        if(isHangeul(word.single())){
            val charuni = word[0]
            val joong_uniIndex = ((charuni.code-0xAC00) / 28 %21).toChar().code
            word_joong = JOONG[joong_uniIndex]
        }
        return word_joong
    }

    fun getJong(word:String):String{
        var word_jong = word

        if(isHangeul(word.single())){
            val charuni = word[0]
            val jong_uniIndex = ((charuni.code-0xAC00) %28).toChar().code
            word_jong = JONG[jong_uniIndex]
        }
        return word_jong
    }

    fun isHangeul(word: Char): Boolean {
        return UNICODE_HangulStart <= word.code && word.code <= UNICODE_HangulLast
    }

    }
}

 

| 참조

오픈 소스 컨트리뷰션을 위한 GitHub Fork & Pull Request | Eric Han's IT Blog (futurecreator.github.io)

[Github] github profile 예쁘게 꾸미기 (velog.io)

GitHub 한국 1위 개발자가 말하는 오픈소스 해야 하는 이유 5가지 | by Ted Park | 박상권의 삽질블로그 | Medium

[공지사항] PR, Review 남기는 방법, Approve 방법 · Issue #11 · im-d-team/Dev-Docs (github.com)

Approving a pull request with required reviews - GitHub Docs