JNI(Java Native Interface)는 네이티브 쪽과 자바 쪽을 연동시키는 것이 필요한 경우를 위해 썬에서 공개한 SDK의 일종입니다.
여기서 네이티브라 하는 것은 물론 C/C++이나 델파이 등 가상 환경이 아닌 로레벨 개발 환경을 말하는 겁니다.
JNI는 자바 쪽에서 네이티브 호출, 혹은 네이티브 쪽에서 자바 호출 양쪽 모두 가능합니다. 하지만 후자는 별로 사례가 많지 않고 주로 자바쪽에서 네이티브를 호출하는 경우가 흔한데요. 그건 자바 개발자들도 동의하듯이 자바는 성능과 기능성, 저수준 접근성 등에서 네이티브에 미치지 못하기 때문입니다. 다시 말해, 자바 프로젝트에서도 고속 연산 등 빠른 처리가 필요한 경우나, 자바의 기능으로는 처리하기 어려운 복잡한 기능들이 필요한 경우, 또 OS 저수준 접근 등의 작업에서는 해당 기능은 따로 떼어 네이티브로 개발하고 자바쪽에서 호출합니다. 이것이 JNI의 일반적인 케이스죠.
반대로, 네이티브쪽에서 자바를 호출하는 경우는 그리 많지 않은데요. 한 마디로 말하자면 “네이티브가 뭐가 답답해서 자바에 의존하겠느냐” 라고 할 수 있습니다. 성능이나 기능, 저수준 접근 모두 자바보다 월등하기 때문에 네이티브에서는 자바를 호출할 일이 흔치 않습니다.
그럼에도 불구하고 드물게 네이티브에서 자바를 호출하는 경우도 있는데요. 그건 언어를 떠나 아주 잘 만들어진 자바 소프트웨어가 있어서 굳이 네이티브로 다시 개발하거나 하지 않고 갖다 쓰는 것이 더 효과적일 경우입니다.
대표적인 예를 들자면, Lucene(루씬)이 있습니다. 루씬은 자바로 만들어진 검색엔진인데, 웬만큼 경험이 있는 웹 개발자들은 다 아는 유명한 검색엔진입니다. 루씬에 대한 책도 여러권 나와 있구요. 오픈소스여서 무료로 가져다 쓸 수 있는 장점도 있지만 기능적으로도 웬만한 상용 제품은 비교도 되지 않을 정도로 잘 만들어져 있어서, 검색 엔진 기능을 필요로 하는 수많은 웹 개발자들이 가져다 씁니다. 닷넷 진영에서는 이 루씬이 워낙에 탐이 나서 닷넷으로 포팅해서 가져다 쓰더군요. (루씬을 가져다 몇군데 수정하고는 자신이 개발했다고 사기치는 간 큰 웹 개발자들도 몇 봤습니다)
루씬 같은 소프트웨어는 물론 뛰어난 개발자들 여럿 데려다놓는다고 며칠, 몇달 정도에 개발할 수 있는 것이 아닙니다. 그래서 비록 느리고 기능도 떨어지는 자바이긴 하지만 루씬과 같은 뛰어난 소프트웨어라면 연동해서 기능을 가져다 쓸 가치가 충분하고도 남습니다.
하지만 이렇게 네이티브에서도 반드시 가져다 쓸만큼 뛰어난 자바 소프트웨어가 흔한 것은 아니어서, 대부분의 JNI 사례는 자바쪽에서 네이티브를 호출하는 데에 집중되어 있습니다. 그런데 자바->네이티브 호출의 경우 자바쪽에서 개발을 하는 거라서, 네이티브 개발자들은 별로 작업할 게 없습니다. 그래서 결과적으로 대부분의 네이티브 개발자들은 JNI라는 것을 사용해볼 기회 자체가 없습니다.
그런데 최근에 제가 JNI를 쓸 일이 생겼습니다. 제가 자바로 개발하지는 않으므로(뭐 하려면 할 수야 있지만) 네이티브쪽에서 자바를 연동해야 하는 아주 드문 케이스에 걸린 거죠. 그것도 자바쪽 소프트웨어가 기능적으로 뛰어나서도 아니고… 해당 소프트웨어의 기능은 아주 단순한 수준이고 제가 델파이나 C++로도 여러번 해본 기능이라서, 해당 소프트웨어 자체의 성능도 느리고 JNI 연동도 성가신 작업이라서 델파이로 전면 재개발을 해주겠다고 했는데…
작업을 의뢰한 쪽에서 엄청난 삽질을 감수하면서도 자바쪽으로 연동하기를 원하더군요. 사실 제가 델파이로 개발했으면 2~3일 정도면 충분한 기능이었는데 자바로 개발하면서 개발에 총 2개월이 걸려서 제게 전달을 해주는 웃지 못할 상황이 벌어졌습니다. 저는 생전 해보지도 않은 JNI로 델파이에서 자바 클래스를 연동해야 하는 상황이 벌어져서 다시 여러날을 JNI 때문에 삽질을 하게 되었구요. 아무래도 정책적, 혹은 정치적인 상황에 꼬인 것 같았습니다.
그래서 전 다음과 같은 세 가지 삽질 사태들에 부딛히게 되었습니다.
1. 말씀드렸다시피 네이티브쪽에서 JNI를 호출한 사례 자체가 많지 않아서 관련 정보가 많지 않고 어쩌다 정보가 찾아도 그다지 확실하거나 신뢰할 수 있을만한 정보가 아니라 자신도 삽질해보고 나온 정보를 알려주는 정도였습니다.
2. C++빌더였다면 이 삽질 단계는 필요하지 않았을텐데, 발주처에서 델파이를 원했습니다. 그런데 JNI 인터페이스 중 네이티브->자바 호출 인터페이스는 기본적으로 C/C++을 위해 만들어놓은 거라 델파이용은 서드파티 개발자가 자작하여 제공한 것 뿐이었습니다. 그나마도 2003년 정도 이후로 제대로 업데이트가 되지 않아서 최근의 델파이 버전들과는 호환도 잘 안되었습니다.
3. 제가 연동해야 하는 자바 소프트웨어는 원래 일정을 상당히 많이 넘겨 다급하게 개발한 직후의 상황에서 별도의 실무적인 상황의 테스트도 없이 제게 넘긴 거였습니다. 당연히 상당히 많은 버그들이 있을 거라고 예상되었습니다. 이런 경우 십중팔구는 제가 베타테스터가 됩니다. -.-;;;;
기본적인 프로그램의 로직이나 기능을 다투는 일도 아니고, 당연히 네이티브로 해야 할 일을 엉뚱하게도 자바로 만들어놓고 일을 몇배로 키워놓은 거라서 정말 하기 싫은 프로젝트였습니다만… 저도 정치적인 문제에 휘말려서 어쩔 수 없이 진행하게 되었습니다. 그래서 아래와 같이 각개 격파(?)를 했죠.
1번의 문제는 뾰족한 수가 없죠. 엄청난 검색과 삽질을 했습니다. 오직 구글신님만이 저를 도와주셨을 뿐입니다. -.-;;;;
2번의 문제는, 여기저기에서 짜깁기를 해서 사실상 JNI C++ 인터페이스를 제가 새로 포팅하다시피 했습니다. 해외에 최근에 JNI를 델파이로 포팅하여 공개한 개발자가 있어 좀 도움이 되었는데, 실험적인 수준으로 아주 일부만 포팅해놔서 후반 작업을 다 해야 했습니다. 제가 포팅한 소스도 다시 많은 시행착오를 거쳐 겨우 안정화시켰습니다.
3번의 문제는 예상은 했지만, 생각보다 문제가 더 심각했습니다. 가장 큰 문제였고, 엄청 속을 썩였습니다. 문서로 전달해준 내용과 정확하게 정반대로 동작하는 부분도 있었고, 두자리 코드값이 리턴되어야 하는 함수에 텍스트 에러 메시지가 전달되는 황당한 경우도 있었구요. 그나마도 예외처리가 안되어서 에러메시지를 자바의 기본 시스템 익셉션 메시지를 받아보기도 했습니다. 이건 “급하게 만들다 보니… (긁적긁적)” 이런 변명이 불가능한 수준이었습니다. 한마디로 악전 고투였습니다.
매번 해당 자바 개발자와 연락을 주고받으며 수정을 요청하기에 지쳐, 조금은 극단적인 방법을 쓰기로 했습니다. 자바 디컴파일러를 구해 해당 소프트웨어를 디컴파일해서 소스로 만들어버린 거죠. -.-;;; 네이티브에서야 디컴파일이라고 해봐야 알아보기 힘든, 해킹 전문가쯤 되어야 겨우 쫓아갈 수 있지만, 자바나 닷넷은 디컴파일을 하면 거의 완벽하게 원본과 동일한 소스가 쏟아져나옵니다. 게다가 이런 디컴파일러가 무료로 많이 돌아다니구요. 물론 디컴파일이 어렵게 해주는 툴도 나와 있지만, 보안 측면에서 믿기에는 그 기능도 한계가 너무 얕습니다.
사실 디컴파일 방법이 극단적인 이유는, 개발자로서 다른 개발자의 소스를 허락없이 들여다보는 것은 법적으로야 어떻든 도덕적으로는 상당히 실례이기 때문입니다. 어떤 분들은 디컴파일 혹은 리버스 엔지니어링 자체가 불법이라고 잘못 알고 계시는데, 2001년 개정 프로그램보호법에서 리버스 엔지니어링에 대한 조항이 삭제되면서 해당 소프트웨어의 정당한 사용자는 악의적인 목적이 아닌 이상 법적으로 허용되게 되었습니다.
그래도, 이번의 경우에는 그런 예의를 따질 계제가 아니었습니다. 개발 경력 20년이 다 되어가고 온갖 업계에서 별의 별 상황에서 다 일해봤으니까 삽질 프로젝트야 익숙한 경험이지만, 단연 이번이 최악이었습니다. 원래 델파이로 개발할 생각으로 간단히 맡은 프로젝트였고, 제가 많이 해봤던 거라 그래서 기간도 넉넉잡고 1주일 짜리였는데요. 이게 제가 최소한 1개월 이상은 전념해야 하는 상황이 되었고, 그런데도 제가 바로 그 다음주에는 다른 중요 프로젝트에 들어가야 해서 1주일 이내에 무조건 끝내야 했습니다. 그래서 예의고 뭐고 디컴파일을 감행했죠.
어쨌든, 디컴파일러로 돌렸더니 불과 몇초만에 너무나 깔끔한 자바 원본 소스 코드가 쏟아져 나왔습니다. 자바 디컴파일러로는 jad.exe라는 것을 가장 많이 쓰는데, 무료고 가볍고 빠릅니다. 물론 원본 소스 코드도 아주 깔끔하게 잘 나오구요. 지금 원래의 홈페이지는 폐쇄되었는데, 구글 신에서 검색해보면 여기저기서 엄청 많이 나옵니다.
해당 원본 소스를 뒤져서 작업을 진행하니 자바 소프트웨어 쪽의 로직 버그들을 빠르게 파악하게 되었고, 그래서 작업 속도가 좀 나오게 되었습니다. (암만 그래도, 상대편의 버그까지 찾아주면서 협업(?)을 하는 이런 식의 작업 진행은 좀 어이가 없지 않습니까?) 최종적으로 제쪽의 작업을 다 마무리하는 단계에서, 해당 소프트웨어에서 발견된 버그들을 원 개발자에게 알려주고 수정을 요청했습니다.
나름 흔치 않은 경험을 쌓게 된 것은 쬐금 정도는 보람이 있습니다만… 다시 하고 싶은 경험은 전혀 아니더군요. 효율과 결과를 최우선을 해야 할 개발 프로젝트가 정책과 정치에 묶이면 얼마나 꼬일 수 있는지 다시 한번 뼈아프게 체감했답니다.
여전히 바쁜 나날을 보내고 계시군요.. 고생하셨겠습니다. ^^
그런데 컨설팅 만 아니라 직접 개발도 지원해 주시나보네요?
개발 컨설팅에서 컨설팅과 완전히 개발 실무가 완전히 분리되는 경우는 별로 없고 보통은 엔진, 프레임워크 쪽의 개발이 포함되는 경우가 많은데요. 저도 그런 쪽 개발 작업은 많이 합니다.
그런데 이번 사례의 경우는, 초기에 워낙 간단한 일로 파악했었기 때문에 간단히 개발해주겠다고 흔쾌히 수락했던 건이었습니다. 제가 예전에 많이 해봤던 메일 관련의 일이라, 델파이로 자바쪽 소프트웨어의 롤까지 포함해서 구현해도 실제 작업 시간은 2일 정도면 충분했습니다. 추가적으로 보안 메일에 대한 니즈가 있기는 했지만 아주 간단하고 효과적인 아이디어가 떠올랐기 때문에 보안 메일 구현도 반나절이면 충분했거든요. 많이 해본 일이 아니면 간단히 며칠 정도라고 단언하지 않죠.
그런데 이번에는 첫 업무 협의 당시에는 없었던 자바 소프트웨어가 갑자기 튀어나오고 연동을 해야 되어서, 사례가 흔치 않은 네이티브->자바 JNI를 구현해야 하게 되어 일이 커졌구요. 게다가 그 자바 소프트웨어 자체가 제가 써보기 이전에 전혀 검증이 되지 않은 것이라, 결국 연동해서 개발해야 하는 제가 베타테스터 역할을(더 정확하게는 마루타 역할) 떠맡게 된 거죠.
사실 해당 자바 소프트웨어의 원본 코드를 살펴보니 급하게 작업하느라 여기저기 실수 투성이이긴 했지만 꽤 잘만들어지긴 했습니다. 분량도 상당히 많았구요. 하지만 그래봤자, 델파이로 작업했으면 그 작업들은 하루 정도면 끝날 작업이었던 게 문제였죠.
그래서 이틀 짜리 작업이었던 게 문제가 엄청 복잡해졌습니다. 이 작업을 하는 과정에서 기대한 것과 다르게 동작할 때마다, 다음과 같은 각각의 가능성들을 모두 고려해서 하나 하나 다 확인해봐야 했습니다.
1. 제가 JNI 인터페이스를 잘못 썼을 가능성
2. 해당 자바 소프트웨어의 버그일 가능성
3. JNI의 네이티브->자바 호출 인터페이스에 버그가 남아있을 가능성
4. JNI를 델파이로 포팅한 개발자의 실수의 가능성
5. 저와 자바 개발자와의 커뮤니케이션 문제로 오해했을 가능성
실제로는, 이 다섯가지 케이스가 거의 모두 발생했습니다. 당연히 실제 코딩 시간보다 테스팅과 재코딩, 재테스트 시간이 훨씬 많이 걸리죠. 그래서 JNI로 자바 소프트웨어와 연동해서 개발하는 케이스를 어떻게든 피해보려고 설득도 했고 또 프로젝트를 드랍시킬까 심각하게 고민도 했었는데, 제 얼굴을 걸고 약속을 한 거라 그렇게 하지도 못했구요.
자바쪽을 호출하는 JNI 부분을 빼고 나면 이 프로젝트의 나머지 코드는 완전히 단순 예제 코드 수준에다 분량도 얼마 되지않았는데 순전히 자바쪽과 연동하느라 일의 분량이 거의 열배 수준으로 커졌고 로직을 구상하고 코딩한 시간보다 삽질한 시간이 몇배로 많았으니, 다시 생각해봐도 정말 끔찍하답니다.
그건 그렇고.. 이번 토요일에 광화문에서 뵙게 되겠네요..? ^^
그렇겠네요.
한가지 원인이 아니라 여러가지 경우의 수를 생각하다 보면 끝이 없죠..
어쨌든..토요일에 보시죠 ^^
델파이 관련 내용을 찾다가 우연히 포스팅을 보게되어 글을 남깁니다.
현재 공개되어 있는 dede.exe는 어셈블리어 수준인데 이를 원본 소스
혹은 이를 c언어 나 다른 고급언어로 바꿀수가 있는지요?
참고로 델파이 3 혹은 4 버전입니다.