월요일, 4월 26, 2010

Software Package Solution 의 유혹

살아남은 국내 솔루션 업체들
오러클이 선을 인수했다. 선의 최고 히트작인 Java 언어를 인수한 것이다. Java Enterprise Edition(Java EE)의 Reference Implementation 역할을 했던 Glassfish 의 본격적인 commercial edition을 만들겠다고 한다. 분산 데이터 그리드 솔루션인 Coherence 를 결합하는 방안도 검토 중이다.

Java EE 솔루션의 글로벌 경쟁은 Glassfish와 WebLogic을 인수한 오러클 외에는 IBM WebSphere와 open source 기반으로 Redhat이 인수한 JBoss 정도이다.
보통 JBoss가 경쟁하는 시장은 조금 다르다고 볼 수 있으므로 commercial Java application server 시장에서는 손쉽게 담합도 가능할 정도로 정리가 되어버렸다.

국내는 Tmax JEUS 가 시장 점유율 1위를 몇년째 유지하고 있지만, 하루하루가 쉽지 않다. 엄청난 투자를 쏟아붓고 있는 global vendor와의 경쟁에서 핵심 기능 중심으로 기술 정체성을 확립해간다는 것은 숨막히는 혈투와 같다. 홈의 잇점을 최대한 활용해서 버텨가야 한다. 한동안 위기에 빠져 투자를 본격화할 수 없었던 Sun이 자바 스튜어드 역할을 할 때와는 비교할 수 없다.

물론 핵심 영역에서의 기술 경쟁력이나 국내 영업력, R&D까지 바로 이어지는 기술지원 등 JEUS의 시장 경쟁력은 여전하고, 실제로는 많이 사용되지 않는 복잡한 기술 트렌드의 유혹에 의해 고객이 구매 대체 결정을 하지는 않을 것이다. 하지만, Java EE가 다루는 영역이 급속하게 넓어지고 있음은 누구나 동의할 수 있을 것이다.
어떤 형태로든 JEUS의 공격적인 시장 대응이 시장 점유율 유지에 필요할 것이다.

Tmax는 국내에서 Tibero라는 RDBMS 솔루션을 가지고 오러클에 또다른 도전을 하고 있다.
오러클의 모든 기능을 다 갖추진 못했으나 성능과 안정성 그리고 호환성 측면에서 조금씩 시장 검증을 받고 있는 상황이라고 생각한다. 아직 본격적인 시장 폭발은 일어나지 않고 있지만...

국내 패키지 솔루션의 성공의 첫 사례는 워드 프로세서인 아래아 한글이었을 것 같다.
여전히 한컴이라는 회사가 존재하고 아래아 한글 역시 버전 업을 계속하고 있다. 마이크로소프트의 거센 공격 속에도 이렇게 오래 버틴 SW 기업이 있을까 싶을 정도로 우여곡절을 거듭하면서도 수익을 내는 SW 솔루션으로 자리잡고 있다.
최근 스마트폰 열풍과 함께 안드로이드 기반에서 실행 가능한 ThinkFree Office Mobile 에디션도 존재감을 만들어가고 있다. 다만, 한컴 대표이사가 배임 혐의 등으로 검찰의 조사를 받고 있는 상황이 안타깝지만...

V3라는 MS DOS용 anti-virus 솔루션으로 출발한 보안 솔루션 업체인 안철수연구소 또한 소프트웨어 솔루션으로 외산의 공격을 막아내며 오랜 세월 자기 역할을 해내고 있다.

없지는 않지만, 다섯 손가락으로 헤아릴 수 있을 정도로 몇몇 개의 SW 솔루션들이 살아남았다.

Software 솔루션 개발의 유혹
20년 가까운 국내 Software Solution 회사들의 역사에 지금 살아남았고, 어느 정도 인정을 받고 있는 회사는 다섯 손가락 안에 든다는 것은 국내에서 Software Solution으로 생존하는 것이 얼마나 어려운지를 보여준다.
그나마 성공이란 것을 제대로 보여준 경우는 아직 없지 않은가.

국내 시장이 Software의 가치를 제대로 평가하지 않는다는 점, 또 시장 규모 자체가 너무 작다는 점, SI와 Solution을 같은 Software 개념으로 이해하는 부류들이 대부분이라는 점 등등 환경적인 부분들은 매우 척박하다.

이러한 환경 속에서 global 범주에서 차별화된 software solution을 만들어낸 경우도 많지가 않다.
앞에서 언급한 솔루션들 모두 creativity 관점에서는 좋은 점수를 주기 어렵다. 또, global 시장에서의 경쟁력도 아직은 본격적으로 검증되지 않았다.

어쩌면 얕은 Software 연구 토양이 깊이있는 창의적 결과를 가로막고 있는지도 모르겠다.

그럼에도 Software에 종사하는 수많은 사람들은 솔루션 성공이란 신화를 꿈꾸며 지금도 도전하고 있다. 왜 그럴까? 미국처럼 역사적으로 고수익의 성공 신화가 있는 것도 아니고 또, 국내 대학에서도 전산 전공은 주목받지 못하고 있다. 대부분의 Software 종사자들은 40대가 되기 전에 스스로 다른 업종으로 전환하거나 전환을 강요받는다.

이러한 국내 상황에서 Software Solution 자체에 미련을 가진 사람들은 도대체 어떤 생각을 가진 사람들이란 말인가?

하나는 미국과 같은 벤처 신화를 국내에서도 이룰 수 있다고 믿는 사람들이다. 빌 게이츠의 성공 신화나 애플, 구글의 성공 이야기, 또 그외에도 수없이 많은 기술 기반의 startup을 성공적으로 launch 시켜 대기업에 제값 받고 합병시킨 이야기들.. 모두 미국 이야기이지만, 같은 업계에 일하는 사람들로서 달콤한 유혹일 것이다.

시장의 룰이 보이지 않는 국내 환경에서 여전히 벤처 신화가 가능하다고 믿으며 기술 집약의 가치와 창의적 차별성을 키워가는 사람들.

그 가능성은 국내에서는 바늘 구멍 같고 점점 더 확률이 줄어들고 있지만, 세계 경제의 global화를 생각할 때, 국경에 종속되지 않는 소프트웨어 기술 부문이라면 꿈꾸는 자에게 희망이 없다고 할순 없다.


또다른 부류는 가진 기술이 소프트웨어밖에 없어 소프트웨어를 계속하는 사람들이다. SI나 단순 개발을 하기에는 자신의 인생 이력이 너무 처량해 기술 집약이며 완성도가 필요한 소프트웨어 솔루션 개발에 몰두하는 사람들이다.

출구가 보이지 않지만, 장인 정신으로 버티는 것이다. 모든 사람들이 미래를 예측하여 이를 준비하며 사는 것은 아니다. 하지만, 목표가 분명할수록 내용이 꽉찬 인생이 될 가능성이 높다. 성취감도 인생에 중요한 요소이다. 그리고 누구나 다 목표를 정조준할 수는 없다. 하지만, 그 성취감이 실질적인 성공으로 이어지려면 분명한 출구를 찾아야 한다.

Software Solution과 Services
최근 구글의 대성공으로 수익 모델 관점에서 소프트웨어와 서비스의 경계가 모호해지고 있다.
구글은 소프트웨어 기술로 성공한 기업이지만, 소프트웨어 판매로 수익을 올리는 기업이 아니다. 매우 복잡도가 높은 소프트웨어 기술을 집약적으로 연구 개발하고 있지만, 수익은 이로부터 독립된 서비스를 통해 창출한다는 측면에서 여태까지의 소프트웨어 기업들과는 많은 차별성이 있다.
국내에서도 NHN이나 다음과 같은 서비스 기업이 있지만, 소프트웨어에 대한 연구 수준은 상대적으로 미미한 편이다. 복잡도가 높은 소프트웨어 부분은 연구 성과가 수년에 걸쳐 나타나게 되는데 그러한 장기투자를 과감하게 하기에는 국내 서비스 기업으로서는 단기 수익률에 대한 고민이 더 클 것이다. 그래서 소프트웨어 기술에 대한 연구개발 투자가 구글 흉내내기 위한 최소 비용 차원에서 이루어지고 전략적인 소프트웨어 기술 확보에 대한 고민은 기업의 사활을 걸고 이루어지는 개념은 아닌 것으로 보인다.
이에 비하면 구글에 있어 소프트웨어 기술 연구의 중요성은 차기 전략의 핵심 요소와 항상 맞물려 있는 것처럼 보인다.

구글의 소프트웨어 전략 중 특이한 것은 오픈 소스의 활용이다.
특정 핵심 영역에서는 내부적인 기술 확보를 통해 영역을 넓혀가지만, 어느 정도 기술이 공개되고, 공유된 영역에서는 공개 소스를 활용하는 전략을 사용하여 소프트웨어의 개발 사이클을 줄이고 전략적 기술의 검증 기회를 앞당긴다.
공개 소스의 품질적 측면이나 지원 측면은 항상 의구심을 주지만, 어느 정도 활성화된 커뮤니티가 뒷받침되는 공개 소스를 빌딩 블럭으로 활용하고 전략적 차별성이 필요한 기술 부분에 집중하는 것은 매우 현명한 전략이 아닐까 싶다.
물론 공개 소스를 활용한다고 공개 소스의 커스터마이즈나 유지보수에 비용을 지불하지 않아도 된다고 생각해서는 안되겠지만...

소프트웨어 솔루션과 서비스를 나눠볼 때 국내 게임 기업도 언급할 만하다. NCSoft와 같은 기업은 게임 서비스를 통해 수익을 내는 기업이라고 얘기할 수 있다.
게임 서비스는 일면 솔루션 패키지와 유사한 부분도 있지만, 온라인 게임 서비스가 중시되는 부분에서는 서비스로 분류하는 것이 맞을 것이다.

게임 서비스는 수익 모델이 개인별 subscription에 두고 있으므로 광고 수익 모델에 많은 부분 의존하는 서비스 수익 모델보다는 솔루션 판매와 유사한 부분이 크다.


기술적인 측면에서는 온라인 게임 서비스나 웹 기반 서비스나 엄청난 규모의 대용량 처리나 확장성, 그리드 클러스터링 등에 관심이 많을 것이다.

국내 솔루션 기업에도 미래가 있을까
푸념처럼 이 생각 저 생각, 이 기업 저 기업 대충 꼽아보아도 국내 소프트웨어 솔루션 기업의 장미빛 미래는 그려지지 않는다.

복잡도 있는 기술 기반으로 경쟁력을 가진 기업이라고 하더라도 수익 모델과 성공의 목표가 분명하지 않다면 미래는 쉽지 않다. 차별성 있는 장점을 축적해서 국내 시장이든 글로벌 시장이든 한쪽 시장에서 먼저 승부를 내어야 한다.
범용 소프트웨어일수록 시장이 넓은 매력이 있지만, 국내 시장에 집중한다고 하더라도 범용성 때문에 글로벌 기업들과 힘겨운 승부가 불가피하다.

기술 발전 및 변화가 심한 현재의 소프트웨어 환경에서는 투자에 대한 관리가 무엇보다 중요하다. 복잡한 소프트웨어는 한번의 투자 싸이클이 제조 과정에서만 4,5년이 걸릴 수 있다. 이 투자가 수익으로 연결되는 데는 또 그만큼의 시간이 걸릴 수 있다.

기술 기반의 소프트웨어를 아웃소싱하는 것은 불가능하다. 소프트웨어 특성별로 전략적인 투자 판단은 시장 가능성과 성공 가능성 모두를 두고 이루어져야 한다.

SI적 영역이나 단순 개발의 솔루션이 아니라면 투자 기간이 긴 솔루션을 성공시키려면 많은 비용을 감당할 수 있어야 한다. 구글처럼 오픈 소스를 활용하여 투자 비용을 줄이고 제품 사이클을 단축하는 방법도 있겠지만, 솔루션의 기술적 차별성을 확보하지 못한다면 고객으로부터 비아냥거리가 될 것이다.

점점 더 많은 기술 영역이 공개되고 공유되어 가는 것은 피할 수 없는 흐름이다. 독점적 솔루션이 지배하는 시장에서 적은 비용으로 같은 역할을 하는 솔루션을 만들어 독점 지배가 만들어놓은 높은 가격을 일부 공유하며 일부 시장 점유 및 확대를 꾀하는 것은 후발 주자로서 시장을 확보하기 위한 하나의 접근 방법일 것이다. 하지만 그보다는 전문 영역에서 niche 기술 요구들을 잘 catch해서 보다 빠르게 (1년 정도의 투자 규모) 사업화하는 것이 벤처적인 솔루션 기업의 주요 방향이 아닐까 한다.


최근 정부에서는 convergence에 대한 목소리가 높다.
예를 들어 아이폰이 convergence의 결과물이라고 느끼는 것 같다. 내 생각엔 아이폰은 convergence가 아니다. 소프트웨어가 전용 기계인 컴퓨터의 테두리를 벗어나 좀더 사람의 생활과 문화로 영역을 확대한 것일 뿐이다. 아이폰에서 휴대폰을 바라보는 시각은 너무 하드웨어에 집착하는 것이 아닌가 한다.
이것을 convergence라고 부른다면 소프트웨어를 핵으로 하는 외연 확대를 융합이라고 부르는 셈이 아닐까 싶다.
TV와 같은 가전기기에도 안드로이드와 같은 SW 운영체제가 필요한 시점이 되었다.
이것은 어떤 문화적 폭발의 전주곡이 아닐까 싶다.

복잡도 높은 SW 기술을 확보하고 있는 집단이 있다면 이 폭발을 catch하여 빠르게 준비할 수 있지 않을까?

국내 소프트웨어의 미래는 솔직히 아직 칠흙 어둠 속이다. 스티브 잡스를 바라보는 나의 마음 속엔 어둠 속에서 희망을 놓기 싫어하는, 인생 이력을 허무하게 만들기 싫은 사람의 허튼 바램 뿐이다.

화요일, 4월 13, 2010

고비를 넘기기란

스포츠 경기를 보다 보면 지고 있던 선수가 엄청난 집중력과 투혼으로 듀스 혹은 동점을 만들어낸다.
그 여세를 몰아서 이기는 경우도 있지만, 사실은 험난한 노력 끝에 대등한 상황을 만든 다음에 어이없는 실수로 와르르 무너지는 경우가 더 많은 듯하다.

작년 초였던가 테니스 황제 로저 페더러가 왼손 천재 라파엘 나달을 맞아, 예술같은 경기 능력, 흠잡을 데 없는 완벽한 플레이를 보였지만, 이기는 경기는 쉽게 이기면서도 상대방의 서비스 게임을 듀스 혹은 어드밴티지까지는 계속 가면서도 결국 게임을 빼앗지는 못하고 긴 시간 끝에 세트 2:3으로 역전패하는 것을 본 기억이 있다. 아마 이 경기가 세계 랭킹 1위에서 2위로 물러나는 시점이었을 것이다. 지금은 나달이 부상을 당한 후 슬럼프에 빠져 페더러가 다시 1위로 복귀한 것으로 기억한다.

야구든 배구든 단체 경기에서도 이러한 상황을 많이 만나게 된다. 야구 경기에서 초반에 대량 실점하여 많은 점수차로 뒤지다가 중반에 힘겹게 동점까지 쫓아간다. 하지만, 어이없는 실수로 바로 그 다음 회에 결승점을 내어주고는 더 이상 추격하지 못한다.

이러한 상황, 마치 데자뷰 같은 느낌...

고비를 넘긴다는 것은 이러한 상황의 심리적인 도전을 담담하게 이겨내는 것이다.
어떤 일이든 매우 힘든 과정을 거쳐 고비에 다다랐다면, 고비를 채 넘기 전에 이른 안도감에 기인한 심리적인 무장 해제와 또, "왜 이렇게까지?"라는 자문에 이른다.

지리산 천왕봉을 등정하다가 굳이 정상까지 가는 이유를 스스로 물어본다면 무엇이라 답할 것인가. 이미 먼 길 떠나왔다면 등정한 후에 내려가는 길을 찾아보는 게 맞지 않겠는가.

시간이 얼마 남지 않을수록 마음속 회의와 갈등이 뒤엉킨다. 마치 인생이란 산을 오르다가 왜 오르고 있냐고 묻는 것처럼...

길에 대한 판단은 한치 앞을 보지 못하는 눈보라 속에서 할 수 있는 것이 아니다. 길이 보이지 않는다고 눈보라 속에서 가만히 서 있을 수는 없다. 가던 길, 목표했던 방향으로 계속 가서 이정표를 만나거나 눈보라가 그치면 그때 다시 판단해야 한다.

아직 듀스까지 이르지도 못했다.

토요일, 4월 03, 2010

Heap Dump 분석을 통한 Perm Area Memory Leak 원인 진단

Software 특히 Java 언어를 사용하는 Software 개발 조직에 몸담고 있지만, 마흔을 훌쩍 넘긴 나이에 이런 글을 쓰는 것이 적합한지 의심되는데 특히 국내 SW 환경을 고려한다면 몹시 우스꽝스럽다.

이젠 개발팀장도 아니고 개발실장도 아니고 그위의 관리자이지만, 아직 완전히 제품 코드로부터 역할을 분리하지 못했고, 이러한 시간이 많이 걸리고 책임 소재가 불분명한 문제를 해결할 전문 인력을 두고 있지 않기 때문에 결국 직접 하는 경우가 생긴다. 이것은 미흡한 관리 능력의 결과라고 봐도 좋겠다.

개인적으로는 이러한 일이 전혀 나쁘지 않다. 즐거운 Software Life의 하나일 뿐이다.
관리자가 이러한 삽질을 직접 하는 것이 관리 체계를 무너뜨리는 것 아니냐고 묻겠지만...

oh, give me a break.. 나중에 교육교재 만드는 데 도움이 될까해서 하는 관리 행위의 하나라고 봐주기 바람~~ ㅠ_ㅠ;;

perm gen 과 class leak
Permanent Generation 은 young과 old를 구분하는 Generational Collector 방식인 Sun (now, Oracle)의 HotSpot JVM에서 Old generation 중 한 영역이다.
lifetime이 길다고 판단된 object들을 old generation으로 옮겨서 빈번한 gc의 대상이 되지 않도록 하는 것이 generational collector의 기본 아이디어인데 permanent generation은 old 중에서도 거의 gc 대상이 될 일이 없다고 생각되는 object들을 딴 영역에서 관리하겠다는 아이디어의 산물이다.

HotSpot JVM의 Perm Area 에는 주로 자바의 클래스 객체들이나 문자열 상수 풀에 속한 String 객체들이 위치한다.
메모리 leak의 대상이 되는 것은 string constants 보다는 주로 class 객체들이다.

(class 객체는 주로 객체의 타입을 나타내는 클래스나 인터페이스를 표현하는 객체로 타입명 뒤에 .class 라는 literal을 붙임으로써 지칭할 수 있다. 예를 들어 자바 코드에서 String.class 라는 객체는 java.lang.String 이라는 클래스의 타입을 지칭하는 객체이다.)

memory leak이란 보통 reclaim되어야 할 memory space가 reclaim되지 못하고 있는 상황을 뜻하는데 Java와 같이 garbage collector 기능을 내장한 VM에서는 주로 코드 오류로 인해 gc 대상이 되는 객체를 불필요하게 reference(자바에서는 weak reference나 soft reference와 구분하여 strong reference)하는 gc 대상이 아닌 객체들이 존재하기 때문에 발생한다.

perm area 에 위치하는 class 객체들은 classloader에 의해 load 되기 때문에 이 class 객체들이 unload되는 유일한 방법은 classloader가 unload 즉, gc 되는 것이다.

보통 Java VM이 로드될 때 사용되는 classloader들(runtime에 필요한 클래스를 주로 로드하는 system classloader와 classpath에 설정된 클래스들을 로드하는 application classloader 등)은 JVM이 종료할 때까지 gc되지 않기 때문에 여기에서는 관심의 대상이 아니고, 주로 application이 dynamic하게 코드 상에서 만드는 classloader들이 관심의 대상이 된다.

즉, 다시 말해서 "gc되어야 하는 classloader 객체가 어떤 다른 strong object 에 의해 참조되는 것을 찾는 것이 오늘의 주제"이다.

OutOfMemoryError와 heap dump
heap dump 분석은 Java에서 OutOfMemoryError(이하 OOM)가 발생할 경우 원인을 찾기 위해 많이 사용된다.
OOM 시 heap dump를 자동으로 생성하는 HotSpot JVM 옵션이 있는데 이에 관해서는 앞의 다른 blog를 참고하기 바란다.

OOM은 주로 세 가지 경우에 발생한다. 하나는 전체 heap memory 부족, 또하나는 permanent area 부족, 나머지 하나는 native thread를 더 이상 생성할 수 없을 경우이다.

전체 heap memory 부족은 너무 많은 객체를 만들거나 strong reference에 의해 객체 일부가 reclaim 되지 않아서 발생하게 된다. perm area 부족은 앞과 동일한 이유이겠지만 해당 객체가 class 객체인 경우이고 전체 heap 영역 중 perm 영역이 분리되어 있기 때문에 다르게 발생하는 것이다. thread를 생성 못하는 이유는 OS 환경과 상관이 있을 테고, 또 코드 수준에서 thread를 지나치게 많이 만들거나 또 thread 종료가 제대로 안되어 leak이 발생한 때문일 것이다.

세 가지 중 어느 원인으로 OOM이 발생했는지에 대해선 OOM 에러의 메시지를 보면 쉽게 알수 있다.

heap dump 분석에 필요한 소프트웨어
heap dump 분석을 위해 사용하는 소프트웨어는 다음과 같다.
먼저 heap dump 분석 프로그램. HP에서 제공하는 jmeter 가 있고, IBM에서 제공하는 HeapAnalyzer, SAP에서 만들었다가 지금은 eclipse에 donate된 MemoryAnalyzer 등이 있다.

다들 한번씩 try는 해봤지만 지금은 swing 기반으로 된 순수 자바 프로그램인 IBM HeapAnalyzer를 쓴다.
jmeter는 예쁘게 생겼지만 지원하는 heap dump 포맷이 제약이 있었고, SAP MemoryAnalyzer는 적은 메모리로 큰 dump 파일을 읽어들일 수 있긴 하지만, 제공해주는 정보들을 이해하기 좀 어려웠다.
그러다보니 IBM HeapAnalyzer에 익숙해져버렸다.

또, 하나 많이 사용하는 것은 X 서버이다. PC 환경에서 heap analyzer를 돌리기엔 heap dump 파일이 너무 커서 메모리를 많이 사용하기 때문에 대용량 heap을 사용할 수 있는 64비트 JVM 환경(32비트 JVM에서는 max heap size를 1.4기가 정도밖에 줄 수 없다. 정확한 최대값은 모르겠음)에서 heap analyzer를 실행해야 했는데 그러다보니 PC용 X 서버가 필요했다.

요즘 사용하는 PC용 X 서버는 free open source인 cygwin-x 이다. 큰 문제 없이 쓸 수 있다.

HeapAnalyzer 실행
요즘 개발자들은 X 환경을 이해 못하는 경우가 많아서 간단하게 PC용 X 서버에서 원격지의 heap analyzer를 어떻게 실행하는지 절차를 적어본다. (예전에 motif application 개발을 잠깐 했었던 추억이 있음)

유닉스에서 주로 사용되는 윈도우 시스템인 X-Window 시스템은 서버/클라이언트 구조로 되어 있으며 X 서버는 display를 제공하는 쪽을 뜻하고, 실제 애플리케이션 프로세스가 실행되는 쪽이 X 클라이언트가 된다.

1. X 서버인 cygwin-x를 PC에서 실행하고 xterm 프로그램을 하나 실행시킨다.

2. xterm의 shell prompt 에서 "xhost +" 명령을 실행한다. xhost는 X 서버에 접속할 수 있는 X 클라이언트 호스트들에 대한 접근 제어를 하는 명령이다. cygwin-x가 PC에서 실행되고 원격지 유닉스 서버에서 heap analyzer를 띄울 것이므로 PC가 X 서버이고 유닉스 서버가 X 클라이언트 호스트이다. xhost + 다음에 호스트 명을 주지 않으면 모든 호스트에 대해서 allow한다는 뜻이다.
다음과 같이 불평할 것이다.

[mypc]/home/yoonforh 504> xhost +
access control disabled, clients can connect from any host

3. 해당 유닉스 서버로 telnet 등을 통해 접근한다.
해당 유닉스 서버의 셸에서 DISPLAY 환경 변수를 cygwin-x가 실행된 PC로 지정해야 한다.
예를 들면 ksh이나 bash에서 다음과 같이 지정한다.

export DISPLAY=<PC IP 주소>:0

보통의 X용 appliation은 실행시 -display 옵션을 통해서 지정할 수도 있다. DISPLAY 환경변수 값은 ip 주소와 display screen 번호로 구성된다.

보통 기본값인 0 혹은 0.0을 screen number로 사용한다. 윈도우 시스템 위에 실행되는 window manager 프로그램에 따라 CDE나 gnome-desktop, mwm, twm 등은 여러 개의 screen을 가지므로 screen number를 0이 아닌 다른 값으로 지정할 수도 있다. 사실 대부분의 X용 윈도우 매니저들은 multi screen을 지원한다.
사족이 길어졌다. 그냥 0번 스크린을 지정한다. ㅠ_ㅠ

4. DISPLAY가 지정된 환경에서 heap analyzer를 실행한다.
해당 셸에서 다음과 같이 heap analyzer를 실행한다. 현재 사용하고 있는 버전은 3.7이다.

java -Xmx5G -jar ha37.jar

큰 heap dump 파일을 분석할 때에는 메모리가 많이 사용되므로 heap 최대값을 5G로 줬다. dump 파일 크기에 따라 더 줘야 할 경우도 있을 것이다. 앞에서 얘기했듯이 이 JVM이 64비트인 경우에 주로 지원된다. OS나 JVM 버전, 비트 수마다 지원하는 최대 heap 크기가 다르므로 이 부분은 알아서들 체크하기 바란다.

사족이 길었지만 이 application을 remote에서 띄워보려고 했다. 매번 연구원들에게 일일이 이런 것 가이드하기 싫어서 교육용으로 부연해보았다. cygwin-x 위에 뜬 heap analyzer 아마도 상당히 촌스럽다고 느낄 것이다. 뭐, 잘생겼다고 일 잘하는 건 아니다.

5. heap dump 파일을 읽어들인다.
보통 HotSpot JVM에서 binary format으로 heap dump를 남기게 하면 heap analyzer는 "HPROF binary"라는 포맷으로 읽어들인다.
perm area 부족으로 인한 OOM인 경우는 전체 heap 부족으로 인한 OOM인 경우보다는 heap size가 작으므로 dump 파일도 상대적으로 작다. (이것도 다행이라고 생각하면 되려나 ㅎㅎ)

dump 파일이 클수록 읽는 데 시간이 많이 걸리므로 open 시켜 놓고 다른 일을 하면 되겠다. 어차피 프로세싱은 원격지 서버에서 일어나는 것이니 PC에 몹쓸 짓은 안한다.

Object Reference 관계와 ClassLoader 간 계층 관계
이제 분석할 준비가 완료되었다. 몇 가지 필요한 사전 지식에 대해 언급해본다.

ClassLoader는 계층 구조를 가진다. 이 계층 구조는 ClassLoader를 생성할 때 반드시 부모 ClassLoader를 지정하도록 되어 있는데, 기본적인 자바의 class 정의 검색 방식은 부모 ClassLoader에 정의된 class 정의를 우선으로 찾고, 그 다음에 자식 ClassLoader에 정의된 class 정의를 찾는 구조이다.

자바의 각 ClassLoader들은 내부적으로 parent 라는 멤버 필드를 가지고 있고, 이 값이 부모 클래스로더 객체가 된다.
(classloader들의 parent/chlid 관계는 class inheritance의 parent class, child class와는 아무 상관이 없다.)

Object Reference 관계는 객체 간의 참조 구조를 나타내며 directed graph 형태이다. 즉, 참조자(Referencer)를 시작점으로 피참조자(Referencee)를 끝점으로 하나의 화살표가 그려지는 단방향 그래프 형태라고 생각할 수 있다.

표준적인 용어인지는 모르겠지만, HeapAnalyzer에서는 참조자를 parent, 피참조자를 child로 표현하고 있다. 그리고, parent가 없이 strong object인 경우를 root 라고 표현하고 있다.

즉, 단방향 그래프로 이루어진 forest 형태이지만 이것을 root node가 여러 개인 tree인 것으로 표현하고 있다. 생각해보면 root node들 위에 공통된 가상의 parent node 하나가 있다고 가정하면 하나의 tree로 볼 수 있다. 이렇게 보면 parent/child 용어는 적합하다고도 볼 수 있다. (엄밀하게 보면 상호 참조나 순환 참조가 가능하기 때문에 forest나 tree라고 볼 수 없다. 하지만, 여기에서 얘기하는 parent/child 관계를 적용하는 데는 큰 무리가 없으므로 child가 parent로도 되는 경우나 descendant가 ancestor의 parent가 되는 경우가 존재한다는 것을 예외로 간주하고 rough하게 metaphor를 적용해보자.)

이제 ClassLoader 간 parent/child 관계가 Object Reference 관계에서 어떤 관계를 가지는지 생각해보자. 이게 아마 이 논의의 핵심일 것이다.

Child ClassLoader 객체는 멤버 필드로 parent를 가지고 있으며 이 parent 필드의 값이 Parent ClassLoader 객체이다.
즉, Object Reference 관계로 보면 child classloader 객체가 parent란 필드를 통하여 parent classloader를 reference하고 있다.

다시 말하면 object reference 관계에서는 child classloader 가 referencer(parent), parent classloader가 referencee(child)로 되어 parent/child 관계가 뒤바뀐다.

용어적인 유사성 때문에 혼란이 오는 것이며 서로 관련없는 관계이지만, 결과적으로는 "일반적으로 classloader 객체 간 parent/child 관계는 객체 참조간 parent/child 관계와 반대가 된다"고 생각해도 되겠다.

분석 예
이제 실 예를 들어 perm leak을 찾아보자. 사실 perm leak 이 발생하려면 ClassLoader를 동적으로 만들어 사용하는 프로그램에서 가능하기 때문에 일반적인 application에서는 이런 경우가 많지 않다. 보통은 그냥 클래스를 많이 사용하는 경우이므로 JVM 옵션으로 perm area 영역을 늘려주면 된다.

하지만, plugin 과 같은 동적 프로그램 기능을 가지고 있는 application에서는 plugin을 위한 ClassLoader를 만들어 사용하기 때문에 이러한 경우가 종종 발생한다.

먼저 heap dump 파일을 HeapAnalyzer로 연 다음 "Analysis/Search Name" 기능을 사용하여 의심이 가는 클래스로더 객체를 찾는다. 클래스 명으로 찾을 수 있는데 dump 상에는 separator가 '.'이 아니라 '/'인 점을 주의하여 찾는다.


검색 결과를 보면 해당하는 타입의 객체와 클래스 객체가 나타난다. 아래 그림에서 클래스로더 객체는 12개가 존재한다. (13개 중 한 개는 클래스로더 타입을 나타내는 class 객체)


위 그림에서 보이듯이 각 클래스로더 객체를 선택하여 오른쪽 마우스 버튼(두번째 마우스 버튼)을 클릭하면 팝업 메뉴가 보이며 이를 통해 해당 객체의 parent 객체들이나 child 객체들을 추적할 수 있다.

클래스로더 객체를 참조하고 있는 객체 즉, object reference 관계에서 parent에 있는 객체들이 클래스로더 객체의 가비지 컬렉션을 막고 있는 상황을 찾아야 하므로, 계속해서 "List parents" 기능을 사용하여 object reference tree를 거슬러 올라가보면 문제가 되는 참조자 객체를 찾을 수 있을 것이다.

경우에 따라서는 parent 객체들이 sun/reflect/DelegatingClassLoader, java/security/ProtectionDomain, java/lang/Package 등만 나타나는 경우가 있는데 이런 객체들은 일시적인 참조이며, 이 경우는 garbage collection되기를 기다리고 있는 경우이기 때문에 leak이 아니다.

각 객체별로 parent를 추적해보면 알 수 있지만, ProtectionDomain 객체와 Package 객체는 ClassLoader 와 상호참조되는 객체들이며 다른 strong reference에 의해 연결되지 않으며 DelegatingClassLoader는 HotSpot JVM 에서 reflection을 사용하여 dynamic proxy 객체를 만들 때마다 일시적으로 사용되는 클래스로더이다.

object reference 상의 parent 추적은 여러 depth에 걸쳐 일어날 것이며 해당 클래스의 소스 코드를 알고 있다면 쉽게 연결하여 이해할 수 있을 것이다.


object reference graph 추적은 perm leak이든 일반적인 memory leak이든 동일하게 사용할 수 있다. 다만 여기에서는 classloader 객체가 leak이 되는 경우에 perm area problem이 발생한다는 것을 중심으로 설명하였다.

누구에게든 이 잡다한 내용이 작은 도움이 되길 바라면서...

목요일, 4월 01, 2010

연구와 개발의 밸런스

R&D에 계속 몸을 담고 있지만, R과 D가 크게 다르다는 점은 별로 주목받지 못하는 것 같다.

연구 조직과 개발 조직을 완전히 분리하는 경우도 있겠지만, 내가 몸담은 조직은 개발 조직에서 연구를 함께 진행하는 경우이다.

연구와 개발은 다르다
Software 제품의 개발과 기술 심화를 위한 연구는 결과적으로는 제품이라는 형태로 가치가 외화된다는 점에서는 같은 것이라고 볼 수 있겠지만, 개발과 연구를 하나의 영역으로 간주한다면 효율과 성과 측면에서 어려움에 부닥칠 것이다.

연구를 개발의 일부로만 바라보고 제품 개발 프로세스에 직접적으로 포함시켜버린다면 연구의 깊이나 창의성은 매우 약해질 것이다. 연구가 제품의 직접적인 이슈를 해결해주기 위한 보완적 성격으로만 사용될 것이고, 장기적인 제품 비전과 질적 깊이를 이루지 못할 것이다.
반대로 연구 중심의 프로세스를 셋업하고 개발을 부차적인 프로세스로 간주한다면 Software 제품의 직접적인 품질을 결정하는 코드 품질이나 모듈화 등 기본 방법론적 측면이 약화될 것이고, 연구 성과를 제품의 일부로 흡수하기까지 너무 많은 시간을 허비하면서 제품은 그 시간 한계 속에서 시장으로부터 벗어나게 될 것이다.

연구는 흔히 투자 개념으로 바라본다. 보통 투자는 상대적으로 장기적인 관점의 수익을 기대하는 부분이지만, 시장 요구 혹은 트렌드와 무관하지는 않다.

개별 제품 개발 프로세스는 보통 진척률과 이슈, Feature Set 등을 중심으로 관리하게 되는데 연구는 핵심 기술 영역 확보 혹은 차별적인 Key Feature Set을 가지기 위한 특별한 투자로 바라볼 수 있다.

문제는 연구는 제품 개발에 비해 시간 제약이나 성과에 대한 예측이 더 어렵다는 데 있다.
제품 개발의 경우 Risk를 최소화하기 위해 여러 가지 기법들이 연구되어 있고, 마일스톤별 Feature를 축소하는 등 시장에 대한 시간 압박에 적응하기 위한 노력들이 정형화될 수 있지만, 연구의 경우는 그러한 제약들을 매우 느슨하게 적용하는 것이 일반적이다.

연구 개발의 관리
연구 관리와 개발 관리를 어떻게 조화롭게 관리하여 손실을 최소화할 수 있느냐는 관점에서 바라봤을 때, 연구와 개발은 먼저 관리되는 업무로서는 완전히 분리를 해서 다르게 관리를 해야 한다는 것은 분명하다.
연구 Task와 개발 Task를 다르게 바라보고, 그 다른 성격을 존중하되 시장과의 긴장은 각 영역별로 다르게 제약을 하는 것이 필요하다. 단일 Project 안에서 연구 Task와 개발 Task가 혼재하는 경우에는 연구 Task와 개발 Task가 의존성이 생기므로 문제가 더욱 복잡해진다.

연구 Task이든 개발 Task이든 Task의 time frame과 milestone별 성취에 대한 관리는 정형적으로 관리될 필요가 있다.
다만, 연구 Task의 예측률은 상대적으로 많이 떨어지므로 개발 Task의 time frame을 기조로 연구 Task의 성취를 제한적으로 반영해가는 형태가 될 것 같다.

현실적으로는 연구 Task와 개발 Task는 Task 관리 뿐 아니라 멤버들의 역할 조화가 큰 이슈가 된다. 같은 조직 내에서 연구와 개발 Task를 모두 감당해야 하는 경우에는 더욱 팀웍과 성취감 부여가 이슈가 된다.
Task별 성취에 대한 관리와 멤버별 연구 및 개발 능력의 판단, 멤버별로 성취도에 따른 새로운 성격의 Task 부여 등이 하나의 해결책이 될 수 있을 것이다. 같은 조직 내에서라면 연구 Task와 개발 Task의 엄격한 역할 구분은 오히려 독이 될 수 있다. 각 멤버별로 연구 능력과 개발 능력을 함께 성장할 수 있도록 배려하고 연구에만 전념하는 멤버는 특수한 경우에 한해 최소화하고 개발에서 성취를 이룬 멤버는 점차 좀더 도전적인 과제와 연구 성격의 과제로 도전할 수 있도록 성취도 체크를 마일스톤별로 할 필요가 있을 것이다.

관리는 단일해를 구할 수 없다
연구 관리는 어려운 문제이고 연구와 개발의 밸런스 뿐 아니라 수많은 다른 관리 능력을 요구한다.
오류와 개선은 모든 사람이 하는 프로세스의 필수 요소인 것 같다. 하나의 정답이 존재하는 것이 아니니, 시행 착오를 줄이기 위해 하나의 시행에서 더 많은 교훈을 추출해내고 다음 시행에 반영할 뿐이다.