안드로이드 키보드 어플 제작하기 1.

이상빈·2022년 1월 10일
0

이번 포스트에서는 안드로이드 키보드 어플리케이션을 제작하는 과정을 글로 옮겨보고자 합니다.

키보드 어플리케이션은 특이한 경우 아니면 서버와의 통신기능은 필요가 없기 때문에 코루틴, DB연동과 같은 기능은 쓰지 않았습니다(다만, 네이버 스마트보드 같은 경우 네이버뉴스 등을 받아오는 기능이 있어서 서버 통신이 구현되어있는 거 같습니다)

제가 키보드 어플리케이션을 제작하면서 사용한 안드로이드 기능은 라이브데이터와 데이터바인딩, 뷰모델 정도입니다.

들어가기에 앞서

저는 거의 프로그래밍을 이 어플리케이션을 만들기 위해 배웠다고 해도 무방합니다. 제 CS개념은 아직 초보적인 수준이고, 엄청난 삽질을 통해 그럴듯한 기능을 구현한 정도라고 보시면 되겠습니다. 또한, RPG키보드 - 나만의 키보드를 제작해보자(godsangin)님의 포스트를 많이 참조하였습니다.

0. 어떤 키보드를 만드려고 했나요?

제가 만들기 원했던 키보드는 컴퓨터 자판에 가장 근접한 키보드입니다. 컴퓨터 자판은 물리적인 촉감을 통해 눈을 감고 있어도 오타율이 적죠. 이 촉감을 모바일 기기에서는 어떻게 구현할 수 있을지 많은 고민을 했습니다.

<초안>

  1. 스마트폰은 보통 엄지로 자판을 입력합니다.

    스마트폰을 잡고 있을 때 각 엄지의 행동반경에 최적화된 자판이 구성하면 어떨까?

  2. 컴퓨터 자판은 F, J키에 조그만 돌기가 있어서, 이 버튼을 기준으로 양손이 빠르게 자리잡습니다.

    스마트폰 자판도 이런 "기준점"을 설정한다면 사용자가 더 편리하지 않을까?

위의 두 가지 큰 틀을 잡고 키보드 제작에 나섰습니다.

1. 키보드 어플리케이션의 구성요소

키보드 어플리케이션은 기본적으로 안드로이드 4대 구성요소의 Service가 메인인 어플리케이션입니다.

1-1. 우선 매니페스트 파일에 다음 서비스를 추가합니다.

        <service
            android:name="com.example.inputmethodservice"
            android:enabled="true"
            android:exported="true"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_INPUT_METHOD">
            <meta-data
                android:name="android.view.im"
                android:resource="@xml/xml"/>

            <intent-filter>
                <action android:name="android.view.InputMethod" />
            </intent-filter>
        </service>

안드로이드 퍼미션에서 BIND_INPUT_METHOD를 명시해줘야 합니다.

1-2. 다음으로는 키보드의 InputMethodService를 상속한 클래스가 필요합니다.

사용자가 안드로이드 시스템에서 사용권한을 받고 키보드를 실행하면 InputMethodService를 상속받은 클래스가 비로소 돌아갑니다.

문서에 따르면 InputMethodService를 상속받았을 때 오버라이드하여 작성할 수 있는 메소드들이 많지만, 그 중에서 키보드의 생명주기와 관련해 반드시 작성해야 하는 메소드들이 몇 개 있습니다.

  • onCreate()

    사용자가 입력방법으로 해당 키보드를 선택할 때 작동. 라이프사이클이나 키보드 변수 초기화 등 작업
  • onCreateInputView()

    해당 키보드의 자판뷰(View)가 처음 생성되었을 때 작동. 키보드의 UI 초기화 작업 진행
  • onStartInput()

    사용자가 EditText(View)를 눌러 키보드를 사용하고자 할 때마다 작동. 입력하려고 하는 창(EditText)의 뷰 속성 등을 받아옴
  • onStartInputView()

    사용자가 EditText(View)를 눌러 키보드 자판뷰(View)를 불러올 때마다 작동.
  • onUpdateSelection()

    수명주기와 관련된 메소드는 아니지만, 사용자가 임의로 커서를 옮길 때 작동.
  • onFinishInput()

    사용자가 입력을 종료할 때마다 작동
  • onFinishInputView()

    사용자가 입력을 종료하고 자판뷰(View)가 내려갈 때마다 작동.
  • onDestroy()

    입력방법에서 해당키보드를 선택해제할 때 작동. 키보드 종료 작업 등 실행

다만 onStartInput()과 onStartInputView()의 엄밀한 차이는 아직 잘 모르겠네요. 로그를 찍어봐도 저 둘은 항상 연달아 실행되기 때문에, onStartInput()에 작성한 코드는 onStartInputView()에 작성해도 무리없이 돌아갑니다. 그냥 메소드 이름만 보고 어떻게 쓰는 게 좋은지 예상하는 정도밖에 안 되네요.

1-3. 키보드의 UI 설정값 등을 제어할 액티비티

필수요소는 아니지만, 키보드의 설정을 조절할 수 있는 기능이 있다면 키보드의 완성도가 더욱 높아지겠죠. 어떤 설정값을 사용자가 조절할 수 있게 할지는 구현하기 나름입니다.

저는 키보드의 높이, 테마, 키 진동값 등 UI요소를 중점으로 사용자가 커스터마이징할 수 있게끔 구현하였습니다. 그에 따른 모든 설정값은 SharedPreference을 이용해서 저장하고 불러오게 했습니다.

1-4. 추가 요소 - 한글 오토마타

내가 영어키보드를 구현하겠다면 위의 요소들만 충실히 구현해도 아무 문제가 없습니다.

그렇지만 한글 키보드를 구현하겠다면 얘기가 많이 달라집니다. 왜냐하면 컴퓨터는 한글이 어떻게 구성되는지 모르기 때문입니다.

가령, 우리가 "ㄱ"과 "ㅏ"를 순차적으로 입력한다 해서 "가"를 입력되는 게 아닙니다. 일련의 연산과정을 통해 "ㄱㅏ"를 "가"로 완성시켜줘야 합니다. 개발자가 직접!

이 알고리즘을 편의상 다들 한글 오토마타라고 부르는 것 같은데, 저도 하도 이거 만드는 데 익숙해져서 이 단어를 쓰겠습니다.

한글 오토마타를 만드는 가장 정석적인(?) 방법은 한글을 초성, 중성, 종성으로 나누고, 입력키에 따라 초성, 중성, 종성으로 나눠서 경우의 수를 쌓는 겁니다.

예를 들면 "ㄱ ㅏ ㄴ"을 순차적으로 입력한다면 'ㄱ'이 초성, 'ㅏ'가 중성, 'ㄴ'이 종성이 되는 식입니다.

만약 "ㅏ ㄱ"을 순차적으로 입력한다면 초성은 없고, 'ㅏ'가 중성, 'ㄱ'이 다시 초성이 됩니다.

결과적으로 우리에게 필요한 건,

var 입력상태: Int
var 초성: Int
var 중성: Int
var 종성: Int
var 최종결과: Int

fun composeKRCharacters(입력상태: Int, 입력글자: Int) {
 when (입력글자) {
   자음 -> { when (입력상태) { .. } }
   모음 -> { when (입력상태) { .. } }
 최종결과 = ..
}

위와 같은 함수를 만들어서 최종결과 Character를 연산하고, InputMethodService에 이를 보내주는 사이클을 구성하는 것입니다.

Q. 입력상태가 무엇인가요?
A. 한글은 초성, 중성, 종성으로 구분되는데, 초성만 입력했을 때, 중성만 입력했을 때, 초성과 중성을 입력한 상태일 때, 초중종성을 모두 입력한 상태일 때 등을 입력상태라고 했습니다. 예컨대, 'ㄱ'만 입력한 상태에서 다시 자음을 입력하는 것과 모음을 입력하는 건 다르겠죠.

Q. 그래서 저 함수는 어떻게 만드나요?
A. 저 함수는 이 글에서 모두 설명드리기가 난해합니다...이중모음, 이중자음, 쌍자음 등 어마어마한 예외처리를 통해야 하기 때문입니다. 특히 나랏글이나 천지인, 단모음 자판과 같은 경우 쿼티 키보드의 3~4배에 달하는 복잡도를 자랑합니다. 그래도 기본 골자는 각 입력상태에 따라 초,중,종성에 입력값을 저장하여 단순한 사칙연산을 통해 최종결과값을 만들어내는 것입니다.

profile
발전을 좋아하는 사람

2개의 댓글

comment-user-thumbnail
2022년 12월 18일

키보드 어플 제작을 희망합니다만
혹시 제작의뢰도 가능하신가요?

답글 달기
comment-user-thumbnail
2022년 12월 18일

키보드 어플제작을 도와 주실수 있을까요?
오재헌 010 3414 1026입니다

답글 달기