코드는 대부분 영어로 되어있습니다.
그래서 한국인은 한영키 때문에 오타를 많이 내곤 하는데요...
그런데 왜 키가 한글이라는걸 꼭 쳐봐야만 아는걸까요??
지금 한영 상태가 뭔지, 작성하기 전에 미리 알 순 없을까요?
혹시 키보드가 한글일 때 커서 색깔을 바꿔주면 큰 도움이 될 것 같아요.
그래서 만들게된 IntelliJ-based IDE 플러그인을 소개하고자 합니다.
현재 키보드 언어가 영어가 아닐 때 커서 색깔을 바꿔줍니다. (Vim 호환 가능)
- 지원 환경
- 지원 OS: Windows / macOS
- OS 기본 입력기 사용 (ex. 구름입력기 등 서드파티 입력기 사용 중인 경우 동작하지 않을 수 있음)
이렇게 한영키에 따라 커서 색을 바꿔준다면, 지금 영어키가 맞는지 바로 알 수 있습니다.
Vim 모드 커서와도 호환됩니다!
Settings
- 기본은 빨간색으로, 세팅화면을 통해 커서 색을 바꿀 수 있습니다.
Settings
>Tools
>LangCursor
여러분은 Vim을 자주 쓰시나요?
Vim 모드를 사용하다보면, 한글키가 더욱 치명적인(?) 경우가 많다고 생각하는데요.
아래처럼 v
키로 코드를 셀렉한 상태에서 한글키를 누르면 다 지워집니다 ㅎㅎ
이렇게 한글키 때문에 코드가 다 지워지는 일이 일수였습니다.
물론 macOS의 경우, 아래처럼 한영키 상태를 맥북 상단바로 알아낼 수 있습니다.
그래도 시선 이동 거리가 너무 길어서, 차라리 오타 한번 내는게 낫더라구요.
생각해보면 코딩할 때 저희 시선은 항상 커서에 고정되어 있습니다.
그럼 한글키일 때 커서 색을 바꿔주자!!!라는 생각이 들었고, IntelliJ 플러그인으로 개발하기로 마음 먹었습니다.
그리고 이왕이면, 굳이 한글에만 제한을 두지 않을 생각입니다.
간단하게 정의한 기획은 아래와 같습니다.
모토: 비영어권 개발자를 위한 오타 예방 플러그인
- 현재 키가 ‘영어가 아닐 때’ 커서 색상을 바꿔준다.
- 커서 색상은 설정으로 변경할 수 있도록 한다.
더 많은 기능이 떠올랐지만, 일단 제가 가장 필요했던 기능만 남기고 진행하기로 합니다.
아이디어가 간단하기에 개발도 간단할거라 생각했습니다.
그 때까진 몰랐죠…
기술적으로 한영키를 구분해내는 것이 어려운 포인트였습니다.
사실 이거 때문에 첫 아이디어를 생각한지 6개월 후에나 릴리즈 할 수 있었던건데요.
제가 시도해본 방법들을 하나씩 소개하고, 왜 구현할 수 없었는지 설명하겠습니다.
어려울 수 있으니, 궁금하지 않다면 결론으로 넘기셔도 좋을 내용입니다.
왜 안 되는가?
OS 별로 동작이 다르다. (JVM이 플랫폼을 타네요..???)
InputContext는 사용자의 입력과 관련된 정보를 추상화해 Java에서 공식 지원하는 클래스입니다.
내부적으로 OS 별 Native 구현이 되어있기에 가장 먼저 떠올린 방법입니다.
그런데.. 테스트 해봤을 때, OS 별로 결과값이 달랐습니다. (틀리게 나온다기보다는, 현재 키 레이아웃이 영어라고 표현하는 방식이 다르더군요.)
저는 OS-specific한 플러그인을 만들고 싶지 않았습니다.
사용자가 제한되는 것도 있지만, OS는 계속 새로운 버전이 나오기 때문에 앞으로 유지보수가 굉장히 힘들거 같았습니다.
이와 관련된 스택오버플로우를 참고했을 때, 일단 Linux
환경에서는 InputContext가 올바르게 동작하지 않을 수 있겠다는 생각이 들었습니다.
어디에 OS 별 결과값이 문서화라도 되어있으면 모르겠는데, 그게 없어서 테스트하면서 케이스를 떼우는 방법 밖에는 모르겠더구요;;
그럼 일단 Java InputContext가 내부적으로 키 레이아웃을 구별하는 방법을 따라하면 되지 않을까?
이 생각으로 Native API를 활용한 구현을 조사해보게 됩니다.
왜 안 되는가?
- 공식 문서 부재
- 잦은 I/O로 인해 느려지는 커서 색상 전환 속도
Java InputContext 클래스에서 키보드 언어를 구별하는 핵심 로직을 알아내기 위해,
플러그인에서 사용하는 JDK인 JetbrainsRuntime을 파내려가봤습니다.
아래는 macOS에서 InputMethod를 구별하는 클래스의 코드입니다.
언어는 C# 인듯합니다.
static void initializeInputMethodController() {
static BOOL checkedJRSInputMethodController = NO;
if (!checkedJRSInputMethodController && (inputMethodController == nil)) {
id jrsInputMethodController = objc_lookUpClass("JRSInputMethodController");
if (jrsInputMethodController != nil) {
inputMethodController = [jrsInputMethodController performSelector:@selector(controller)];
}
checkedJRSInputMethodController = YES;
}
}
JRSInputMethodController
라는 MacOS 내부 클래스의 메소드를 호출해서 분별하는 걸로 보입니다.
JRSInputMethodController
라는걸 파보면 한영키 구분 코드를 알아낼 수 있을거 같은데요, 리포지토리 어디에도 저 클래스가 보이지 않습니다...(??)
네??
결론적으로, 저 클래스는 macOS 내부 클래스라서 리포지토리에서 찾을 수 없는게 맞고,
Jetbrains
처럼 JDK를 직접 구현하는 사람들은 노하우(?)가 있기 때문에 활용이 가능하다고 합니다.
어쨌든 Apple이 공식적으로 지원하는 클래스가 아니니 쓰지 않는걸 강력하게 권장한다고 합니다.
이해가 갈듯 말듯 하지만, 쓰더라도 나중에 유지보수는 거의 못한다는 소리네요.
그만 알아보기로 합니다...
macOS는 아래와 같이 쉘 커맨드로 현재 키 레이아웃을 알아보는 방법도 있습니다.
# command
defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources
# output
(
{
"Bundle ID" = "com.apple.PressAndHold";
InputSourceKind = "Non Keyboard Input Method";
},
{
InputSourceKind = "Keyboard Layout";
"KeyboardLayout ID" = 252;
"KeyboardLayout Name" = ABC; # 현재 영문 상태
}
)
이 방법을 사용하려면 I/O 호출이 매번 일어납니다.
빠르게 동작할 수 없을거란 생각을 했습니다.
실제로 위 방법대로 구현 후 비교했을 때, 커서 색상 전환 딜레이가 좀 더 체감되었습니다.
타이핑하다 커서 색상 전환 딜레이를 느끼게 하는건 플러그인의 쓸모를 떨어뜨리기에 치명적이라고 생각했습니다.
그래서 일단 이 방법으로도 구현하지 못했습니다.
그렇다면 OS로 지금 언어 상태를 알아내려 하지 말고,
사용자에게 한영키 키맵을 입력 받아서, 해당 키맵이 인식된 경우 커서 색상을 바꿔주면 어떨까요 ??
왜 안 되는가?
- 한영키처럼 시스템에서 활용 중인 키맵인 경우, 플러그인이 이벤트를 잡아내지 못함
실제 테스트 해봤을 때, 한영키를 포함한 시스템 키맵만 잡아내지 못하더군요...ㅜㅜ
결국 한영 여부는 OS에 의존해서 구별할 수 밖에 없었습니다.
- 한영키 체크 주기: 키 이벤트에 따라 트리거하는건 어려움, 일정한 시간(x00ms ~ 1초 사이)마다 주기적으로 체크해야함
- 한영키 구분 방법: 모든 OS 통일할 방법 없음, OS 각각 개발하자니 유지보수가 어려움, 사용자에게 한영키 키맵을 받아 처리할 수도 없음
- 일정 주기(
200ms
)마다 한영키 체크 로직 실행Java InputContext
로 한영키 구분- 정책적으로 OS 제한 (
Windows
,macOS
만 지원)
-Linux
환경인 경우 IDE Notification으로 동작하지 않을 수도 있음을 알린다.
한영키 체크 주기는 '빠른 속도로 타이핑하고 있어도 한영키에 즉각 반응하는 것처럼 보이는 정도' 를 찾으려 여러번 테스트를 거쳤고 200ms
로 정했습니다.
이건 아직도 이 방법이 최선일지 고민 중인 부분입니다.
로컬 환경이 워낙 다양하다보니, 예외 케이스가 분명 있을 것 같습니다. (구름입력기 케이스 제보해주신 분 감사합니다 💖)
PR은 언제나 받고 있으니 전달해주시면 큰 도움이 될 것 같습니다!!
전작에 고생했던 경험으로 이번엔 한번에 심사를 통과했습니다.
(생각보다 플러그인 description까지도 꼼꼼하게 봅니다. 혹시 플러그인 개발해볼 생각이 있으신 분들은 참고하세요!)
아직 따로 해외에 홍보해보진 않았는데요,
예상했던대로 비영어권 사용자에게 먼저 반응이 보이는거 같습니다.
(전작은 처음부터 미국 사용자가 가장 많았습니다.)
제 개인 SNS, 글또(💖) 슬랙에는 먼저 홍보를 했는데요.
감사하게도 관심을 많이 가져주시고, 플러그인에 대한 질문도 몇가지 받았습니다.
자주 받았던 질문을 몇개만 정리하고 글을 마무리하려 합니다.
이 질문 거의 열몇개 받은거 같아요!
정말 하고싶은데, 하더라도 오래 걸릴거 같아요. (제 현생도 있지만, LangCursor를 재활용할 수 있는 부분이 거의 없다시피 합니다.)
일단 구현 가능한지, LangCursor 만큼 빠른 색상 전환이 가능한지 등 짬짬이 조사를 해보려고 합니다.
성능 개선을 (꽤 많이) 했습니다!
IntelliJ Profiler로 돌려본 메모리 전후 차이를 보여드리면 아래와 같습니다.
(CPU 점유율은 큰 차이가 안 나는데, 메모리가 90% 가까이 절감되었습니다.)
이전
이후
다음 버전 기능으로 개발 중입니다! >.0
사실 JetBrains 플러그인의 경우 한국어 자료가 매우 부족합니다. (영어도 그렇게 많은거 같지는...)
저도 거의 공식 문서만 더듬더듬 찾아가면서 한거라 따로 비법(?)같은게 없습니다.
우선 주 언어는 Kotlin이나, Java를 사용하셔야 합니다.
저는 JetBrains에서 제공하는 플러그인 개발 템플릿의 도움을 많이 받았습니다.
샘플코드, CI/CD 까지 전부 제공해주니 사용하시면 좀 더 편하게 개발하실 수 있을겁니다.
템플릿 리드미가 상세하게 잘 되어있는 편이라, 보시면서 Jetbrains 플러그인 구조 파악에 도움이 되실겁니다.
그리고 플러그인 개발 공식 문서를 참고해가며 그때그때 필요한 클래스를 찾으시면 될 것 같습니다.
전 기존에 공개된 다른 플러그인들의 코드를 어느정도 참고해가면서 도움을 얻었습니다.
숑숑님 덕분에 바로 플러그인 설치하고 며칠 사용해봤습니다!
caps lock을 누를 때 정확성이 높아져서 생각보다 좋은 것 같아요!
저도 플러그인을 만들어보고픈 마음이 스멀스멀 올라왔네요. 감사합니다.