IntelliJ IDEA에서 한글 입력이 안 되는 현상(Ubuntu 18.04, UIM 입력기)

최근에 IntelliJ IDEA 2019.3 으로 업데이트 후 한글입력이 안되는 현상이 발생했다.
그래서 Jetbrains에 문의하였다.

한글입력을 위해서 UIM(벼루)을 사용하고 있었고, IDEA 2019.2에서는 작동했지만, 업데이트 후 작동하지 않음을 보고 했다.

idea.log를 첨부해달라는 메시지를 보고, idea.log를 살펴봤는데, 문제가 되는 로그를 확인했다.

2019-12-26 21:13:15,112 [ 10848] INFO – ntellij.idea.ApplicationLoader – canDisableInputMethod spent 33 ms, found keyboard layouts: [(us, xkb), ], result==true
2019-12-26 21:13:15,209 [ 10945] INFO – #com.intellij.idea.Main – InputMethods was disabled

UIM은 영문입력기만 있으면 되고, 한글 입력기가 별도로 필요없다.

그런데, 영문 입력기 하나만 있으면 IDEA에서 canDisableInputMethod를 true로 반환하는 것이다. 그러니 Shift + Space를 눌러도 아무 반응이 없이, Space 처리만 되면서 한글을 입력할 수 없었던 것이다.

그래서 ibus용 한글 입력기를 하나 추가한 이후에 다음과 같은 로그를 확인했다.

2019-12-26 21:24:45,771 [ 11841] INFO – ntellij.idea.ApplicationLoader – canDisableInputMethod spent 77 ms, found keyboard layouts: [(hangul, ibus), (us, xkb), ], result==false

이제서야 IDEA에서 한글 입력이 잘 된다. 물론 입력기는 그냥 영문으로만 선택해 놓고, UIM을 사용하여 한글을 입력한다.

ibus를 사용하면 웹 브라우저에서 한글 입력이 자음만 되는 이상한 현상이 있어서 UIM을 사용하고 있다.

어쨌든 이렇게 해결을 했다.

Jetbrains에서 관련 이슈를 파 줬다.
https://youtrack.jetbrains.com/issue/JBR-2049

동일한 문제로 어려움을 겪는 분에게 도움이 됐으면 좋겠다.

개구리와 가부장제

개구리의 가사는 아래와 같다.

개굴개굴 개구리 노래를 한다
아들손자 며느리 다 모여서
밤새도록 하여도 듣는 이 없네
듣는사람 없어도 날이 밝도록

개굴개굴 개구리 노래를 한다
개굴개굴 개구리 목청도 좋다

아마도 개구리들이 밤새 울어대서 잠들지 못하는 것을 묘사하고 싶어서 이런 곡을 쓴 게 아닐까 싶다. 이런 맥락으로만 보면 별 문제가 없어 보인다.

하지만, “아들 손자 며느리” 이 가사는 좀 불편한 지점이다. 지난 번에 페북에서 이 지점에 대해 얘기를 했었는데, 이 부분이 문제가 되지 않는다는 남성들의 반응이 참 재미있는 지점이었다. 왜 여성분들은 문제가 없다는 말을 하지 않았을까?

남성들이 기득권을 갖고 있기 때문이다. 남성들에게는 별로 문제가 안 될 것이다.

명절 때 큰집에 가면 밥먹는 순서는 공교롭게도 아들 손자 며느리다. 어렸을 때 이 지점이 이해가 되지 않았었다. 장유유서가 그렇게 중요하면 며느리들부터 드셔야 하는데, 며느리들은 죄다 뒷전이다.

그래서 나에게 특히 “아들손자며느리”는 불편한 지점이다. “온 동네의 개구리” 정도로 바꿔 불러도 의미 전달은 충분할 것 같다. 더 좋은 개사가 있으면 좋겠다.

개굴개굴 개구리 노래를 한다
온 동네의 개구리 다 모여서
밤새도록 하여도 듣는 이 없네
듣는사람 없어도 날이 밝도록

개굴개굴 개구리 노래를 한다
개굴개굴 개구리 목청도 좋다

단순히 이 노래 하나 때문에 가부장제가 더 견고해진다고 하기엔 비약이라 할 수 있겠지만, 이런 식의 노래가 한 두 곡이 아니라 여러 곡이라면 나는 문제가 될 수 있다고 생각한다. 어릴 때부터 들으며 학습하는 자연스러운 가부장제 문화. 이제는 바뀌어야 하지 않을까?

그래서 문제가 있다고 생각되는 동요들은 비판도 하고 개사해서 대안도 제시할 것이다.

대안 없는 비판은 그냥 비난이 될 수 있으니 말이다. 생산적이고 더 나아지는 방향의 비판을 할 수 있도록 노력해 보겠다.

동요와 페미니즘

우선 좋은 동요들이 훨씬 많다는 점을 이야기하고 싶다. 좋은 가사의 동요들이 정말 많다. 하지만 그렇지 않은 가사들도 있다.

종종 생각날 때마다 한 곡씩 소개해 보려고 한다. 그리고 할 수 있으면 개사를 해보려고 한다.

얼마전에 곰세마리에 대한 이야기를 나눴다. 다음엔 아들손자며느리로 유명한 “개구리”로 이야기해 보려 한다.

이렇게라도 써놔야 책임감에 글을 쓰겠지 싶어서이다.

기술부채 그리고 살림부채

개발을 하다보면 기술부채가 생기게 마련이다. 물론 부채를 하나도 쌓지 않고 개발을 하는 천재들도 있겠지만, 나는 그 정도는 아닌 것 같다. 어쨌든 부채를 만들지 않으려고 노력은 하는데, 리팩터링 단계까지 진행을 못할 때가 많다. 핑계를 대자면 뻔히 아는 스케줄의 문제인 경우가 많다. 하지만 시간이 흐를 수록 이는 진정 부채가 되고, 나중엔 작은 기능 하나 변경하는데 필요이상의 시간을 쓰게 되는 경우들도 있다.

요즘 반전담 육아와 집안일을 하면서 살림부채를 경험하고 있다. 아이와 함께하는 시간 동안에는 아이의 심리적 부채가 쌓일 새가 없다. 하지만 식기, 빨랫감, 쓰레기 등등 여기저기 쌓여간다. 살림부채다. 청산해야 한다.

기술부채든 살림부채든 모두 동일한 점은 부채이기 때문에 청산해야 하고, 청산할 부채가 많을 수록 스트레스를 많이 받는다는 것이다. 뭐 재무부채도 마찬가지 아니겠나 싶다.

부채가 생기는 건 불가피, 하지만 최대한 빠르게 청산하기. 오늘도 달려보자. 어쩌다 보니 매일 빚청산하느라 바쁘다. 헥헥

동요: 곰 세 마리

곰 세 마리의 “뚱뚱해”, “날씬해”, “귀여워”는 모두 외모를 평가하는 표현들이라, 이제 아이에게는 내가 개사한 곰 세 마리를 불러준다. 🙂

곰 세 마리가 한 집에 있어
아빠 곰, 엄마 곰, 애기 곰
아빠 곰은 연주해,
엄마 곰은 노래해,
애기 곰은 춤을 추어요.
으쓱으쓱 잘 한다.

앞으로도 다양한 개사곡들이 나타나면 좋겠다는 생각이 든다.

조직구성원과 주주

주주는 기업에 돈을 투자하는 사람들이다.

조직 구성원들은 해당 기업에 인생을 투자하는 사람들이다.

따라서 경영인들이 더 잘 챙겨야 할 사람은 조직 구성원이다.

주주들도 시간을 투자하지 않느냐고 반문할 수 있다.

물론 맞다. 주주들은 투자하고 투자의 결과를 볼 때까지 기다려야 한다. 그럼에도 불구하고 조직구성원들에게 더 마음을 써야 하는 까닭은, 조직 구성원들이 조직을 위해 근로를 제공하는 동안 다른 일을 할 수 없다는 점에서 주주의 시간투자와는 개념이 다르기 때문이다.

조직구성원들을 챙기지 않으면 조직은 어떤 형태로든 그 결과에 대한 책임을 지게 된다.

LINE Works에서 Mailgun 활용하여 Gmail로 옮기면서 발생한 이슈

LINE Works가 이제 유료화를 보름 앞두고 있다.
그래서 G-Suite으로 이사할까 했지만, 어차피 유료고 업무용 메일도 아닌데 굳이 돈을 쓸 필요 있을까 싶어서 대안을 찾다가, Mailgun과 Gmail을 사용해서 개인 메일 세팅이 가능한 내용들을 검색하였다. LINE Works 때문에 벌써 고민하고 포스팅하신 분들이 있었다. 두 분께 이 자리를 빌어 감사드린다.

http://wequlo.blogspot.com/2017/04/mail-gun.html
http://recordingbetter.com/aws/2017/09/22/custom-domain-email-gmail-mailgun

위의 두 포스팅을 읽고 mailgun 세팅을 완료했다.

이제 테스트할 단계다. 그래서 Gmail에서 mailgun에 세팅한 개인 이메일 계정으로 메일을 보냈다.

“550 5.7.1 Relaying denied” 라는 메시지와 함께 메일이 들어오는 문제가 있었다.

이건 뭐지 싶었다. 일단 테스트를 3통 했는데, 모두 오류 메일이 함께 들어오는 것이다. 이건 뭔가 문제가 있는 거 같았다. 일시적이었을 거라 생각하며 마지막으로 한 통의 메일을 더 발송했는데, 메일이 아예 들어오지를 않는 것이다. 550 5.7.1의 오류 메일도 오지 않는 것이다. 직감적으로 Gmail에서 차단한 것이구나 싶었다.

그래서 해당 오류가 무슨 의미인지 찾아보기 시작했다. 아래 참고자료의 Ask leo의 내용을 읽어보면 쉽게 이해할 수 있다.

일단 이 문제가 발생한 기본적인 이유는 Gmail 발송 서버 -> 메일건(osg.kr) -> Gmail 수신 서버의 흐름으로 메일이 전달되는 구조에서 출발한다.

문제는 마지막으로 osg.kr(mailgun)에서 gmail로 relay하는 부분인데, gmail에서는 osg.kr에서 relaying하는 게 누구인지 신원 확인이 되지 않은 상황인 것이다. 신원이 확인되지 않은 메일에 대해서 Gmail 수신 서버는 차단하는 것이다. 그래서 “550 5.7.1 Relaying  denied” 메일을 세 번 받은 이후에는 더 이상 메일이 들어오지 않는 것이었다.

해결책은 Gmail 수신 서버에 osg.kr을 인증된 도메인으로 설정해 주면 된다.

1. https://postmaster.google.com/managedomains
2. 우측 하단의 + 표시를 누른다.
3. 인증할 도메인을 입력해 준다. 필자는 osg.kr을 사용하므로 osg.kr을 입력하였다.
4. NEXT 버튼을 누르면, DNS TXT에 설정할 값을 알려준다.
5. 해당 값을 인증할 도메인의 네임서버에 TXT 값으로 설정해 준다. 필자는 Vultr에서 네임서버를 사용하고 있으므로, vultr에서 ns 세팅을 하였다.
6. Verify 버튼을 누른다.

이제 Gmail에 들어가서 인증한 도메인의 메일로 메일을 발송해 본다. 아주 잘 들어오면 세팅이 끝난 것이다. 일단 필자는 이렇게 문제를 해결했다.

참고자료:
http://ask-leo.com/what_does_relaying_denied_mean.html
https://productforums.google.com/forum/#!topic/gmail/v8wVQIa0PTA

Python에서 용량이 큰 테이블의 insert, update 속도 문제

테이블 하나에 약 800만개의 레코드를 가진 테이블(약 1.2GB)을 만들고 분석할 기회가 생겼는데, 매일의 데이터 변경사항에 대해 추가하거나 업데이트를 해야 한다.

약 1,000개의 레코드를 업데이트하는데 25초 정도 걸렸다. 분명 뭔가 잘못됐다는 신호다. 초당 40개 정도의 업데이트밖에 되지 않았다.

해결책은 그리 복잡하지 않았다. 필자가 했던 적용법들은 다음과 같다.

1. select query를 사용하여 레코드 하나씩 1,000번씩 쿼리를 던져서 필요한 값들을 확인하던 것을 한 번의 쿼리로 작업 단위에 필요한 만큼 불러온 후, python에서 관련 값들을 확인하고 처리하도록 변경했다.

2. insert시 1,000개의 insert query를 실행하던 것을 다음과 같이 한 개의 insert query로 변경했다. 이 방법을 사용하는 경우 query문이 너무 길어지는 경우 실행되지 않을 수 있다. my.cnf에 관련 값을 얼마로 설정했느냐에 따라 달라지는 것으로 보이는데, key값이 지금은 기억나지 않는다. 추후에 확인해 보고 추가해 놓으려 한다.

insert into 테이블명 (필드1, 필드2, ...) values (값1a, 값2a, ...), (값1b, 값2b, ...), ..., (값na, 값 nb, ...)

3. update시 1,000개의 query를 실행하는 것은 동일하지만, where절에 키 두 개를 사용해서 update 하던 것을 primary key 하나만 사용하도록 변경하였다.

위의 3가지 방법을 모두 적용한 후 1,000개 레코드 처리에 25초 정도 걸리던 것은 평균 0.6초 이내로 처리시간이 단축되었다.

적용하기 전에는 Mysqld 프로세스의 CPU 점유율이 단일코어기준으로 100%이었는데, 변경 후에는 약6% 언저리에서 작동했다. 작업 환경은 다음과 같다. CPU는 인텔 G4400, 메모리 8G, SSD 128G, OS는 Windows 10, MariaDB 버전은 10.2를 사용하였다. 그리고 프로그래밍 언어는 Python3에서 MySQLdb를 사용하였다.

테이블 용량이 조금 크다고 해서 테이블을 여러개로 쪼개는 것이 우선이 아니라는 것을 이번에 배웠다. 특히 테이블 크기가 큰 경우에는 DB의 부하를 줄이는 방향으로 최적화할 필요가 있음을 느꼈다. 재미있는 경험이었으며, 기본적인 원칙이 얼마나 중요한지 다시금 생각해 보는 계기가 됐다.

mocha, jasmine 원하는 테스트만 실행/제외

Mocha에서 원하는 테스트만 실행하려 할 때는 .only를 사용하면 된다.

다음 예제의 경우 test 1만 실행된다.

describe('description', () => {
  it.only('test 1', () => {})
  it('test 2', () => {})
})

그리고, 다음의 경우에는 description 1의 test 1, 2만 실행된다.

describe.only('description 1', () => {
  it('test 1', () => {})
  it('test 2', () => {})
})

describe('description 2', () => {
 it('test 11', () => {})
 it('test 12', () => {})
})

그리고 제외하는 것은 .skip을 사용하면 된다. 작동되는 원리는 .only와 같다.

describe.skip(~)

it.skip(~)

Jasmine에서도 작동원리는 Mocha와 동일하다.

Jasmine에서는 focused의 의미로 f를 붙여서 원하는 테스트만 실행한다.

fdescribe(~)

fit(~)

그리고 제외하는 것은 exclude의 의미로 x를 붙여서 테스트를 제외시킨다.

xdescribe(~)

xit(~)

jasmine이 사용하기는 더 편해보이지만, mocha는 처음 보는 누구라도 쉽게 이해할 수 있도록 되어 있다.

<요약>
1. 원하는 테스트만 실행:
– mocha(describe.only, it.skip)
– jasmine(fdescribe, fit)
2. 원하는 테스트만 제외:
– mocha(describe.skip, it.skip)
– jasmine(xdescribe, xit)

Bitbucket 저장소와 Jenkins webhook 연동 – proxy

Jenkins와 Bitbucket Repository를 Webhook으로 연동했을 때의 문제는 webhook 조건을 pull request merged로 설정하면 브랜치 여부에 관계없이 webhook을 날린다는 것이다. 필자가 앞서 포스팅 한 글(https://blog.osg.kr/archives/80)에서 사용하는 방법도 마찬가지다.

안드로이드 프로젝트의 dev 브랜치가 pull request 됐을 때 개발용 앱을 빌드하고, master 브랜치에는 tag가 push 됐을 때 상용 앱을 빌드하도록 하고 싶다면? 어떻게 해야 할까? 이는 실제 필자가 서비스 개발에서 활용하고 있는 방법이다.

필자는 Proxy 서버를 Node.js로 간단히 구축하여 개발서버에서 구동하고 있다. Bitbucket에서는 webhook을 날리는 request body를 로그로 남겨준다. 로그에 기록된 body를 참조해서 해당 json을 파싱해서 활용하면 된다.

프록시 작동 원리는 다음과 같다. 개발용 앱 빌드의 경우 Bitbucket에서는 브랜치에 상관없이 pull request가 merge되면 webhook을 Node.js로 구축한 Proxy 서버에 보낸다. 프록시 서버는 body의 내용을 확인해서 dev 브랜치로 머지된 것인 경우에만 Jenkins 서버로 다시 Webhook을 걸어준다.

상용 앱 릴리즈 시에는 Bitbucket에 tag가 push되면 Proxy로 일단 webhook이 걸린다. 프록시 서버에서 body의 내용을 확인해서 master branch에 태깅됐을 경우에만 Jenkins로 webhook을 걸어준다.

단순히 도식화하면 아래와 같다.

Bitbucket Webhook > Node.js proxy > Jenkins task item

물론 Proxy 서버는 꼭 Node.js를 쓸 필요는 없다. 자신이 쓰기 편한 프레임워크를 사용하면 된다.