만행

만행 1
현각 지음, 김홍희 사진/열림원
만행 2
현각 지음, 김홍희 사진/열림원

몇달 전 선애누나가 이 책을 읽으시면서 대략의 줄거리를 이야기 해주셨는데 그 것을 듣고 난 꼭 이 책을 읽고 싶었다. 꼭 사서 읽고 싶었는데 절판되어서 결국 못 구하다가 선애누나에게 빌려서 3일만에 읽어버렸다. 나 스스로 최근 종교에 대해서 많은 고민을 하고 있었기 때문에 현각스님이 천주교 집안에서 태어나 스님이 되기까지의 이야기가 너무나 궁금했다.

현각 스님이 되기 전의 폴은 호기심이 왕성한 아이였다. 그는 성경을 수도 없이 읽었고 신실한 믿음을 가지고 있었으며 예수님의 뜻을 따라 남을 돕는 삶을 살고자 노력했다. 폴은 카톨릭계 학교에 다녔는데 수녀님들은 그의 질문에 당황하고 힐책할 뿐 납득할만한 대답을 주지 못한다. 그 질문이 내가 기독교에 가지고 있는 것과 너무나 비슷했기 때문에 나 역시 책을 읽으면서 수녀님들의 대답이 실망스럽게 느껴졌다.

이를테면 “불신지옥”에 관한 것이나, 태어날 때 부터 불행을 가지고 태어나는 아이들에 대한 것이다. 하나님은 아이들을 사랑하신다고 하는데 태어날 때 부터 마약에 중독되어 태어나는 아이, 에이즈에 감염되어 태어나는 아이, 먹고 살기도 힘든 가난한 환경에서 태어나는 아이들을 어떻게 이해할 수 있을까? 폴의 의문을 접하며 나는 김혜자님의 <꽃으로도 때리지 마라>에서 그녀가 아프리카의 처참한 상황을 바라보며 외쳤던 외마디가 들려오는 듯 했다.

폴은 어려서 부터 진리를 찾고 싶어 했기에 예일 대학에 진학하여 본격적으로 철학과 신학을 파고 들었다. 그 과정에서 그는 키르케고르, 쇼펜하우어 등의 많은 철학자를 만났으나 명확힌 진리를 찾지 못하고 방황한다. 그후 하버드 대학원에 진학한 폴은 우연히 한국의 숭산스님의 이야기를 듣고 매료되어 한국을 찾고 종국에는 스님이 되어 폴이 아닌 현각이 되었다.

참선을 통해 자기 안에서 진리를 찾는 선불교의 스님이 된 현각은 오히려 자신이 수행자로서 참선을 하는 것이 예수님의 뜻을 이해하고 예수님의 뜻대로 사는 것에 도움이 된다고 이야기 한다. 어떤 종교집단에 소속되어, 어떤 형식을 따르는 것이 중요한 것이 아니라 예수나 부처와 같은 성인의 가르침을 따라 마음과 행동을 일치시켜 남을 돕는 삶을 사는 것이 중요한 것이 아닐까 하는 생각이 든다.

현각의 스승인 숭산스님은 세계에 현존하는 4대 생불로서 어린아이 같은 맑은 눈과 순수한 미소를 가진 분이라고 한다. 책을 읽으면서 나도 그분을 뵙고 싶고, 그 분의 설법을 들어보고 싶다는 생각이 들었다. 또한 불교라는 종교에 대한 강한 호기심이 생겨 현각스님과 숭산스님의 쓴 책을 읽어볼 계획이다. 진리란 무엇일까? 무엇이 올바른 삶일까?

SWT/JFace

이 글에서는 SWTJFace가 대략 무엇인지, 그리고 이클립스에서 차지하는 위상은 어떤 것인지에 대해서 개괄적으로 이야기하겠습니다. JFace는 일종의 프레임워크이다 보니 공부를 상당히해야 코딩이 가능하지만, SWT를 이용한 코딩은 AWT/Swing으로 UI를 작성해 보신 분이라면 쉽게 적응하실 수 있으리라 생각됩니다. 구조에 큰 차이가 없습니다.

SWT는 Standard Widget Toolkit의 약자로 이클립스에서 UI를 표현하는데 사용되는 API 입니다. SWT가 나오기전에는 AWT와 Swing을 사용했습니만, 써보신 분은 아시겠지만 UI가 어설프고 예쁘지가 않습니다. SWT의 특징은 현재 사용중인 OS에 어울리는 미려한 UI를 제공한다는 것입니다. JNI를 이용해 호스트 운영체제가 제공하는 사용자 인터페이스를 불러서 사용하기 때문이죠. 이클립스를 윈도우, 리눅스에서 각각 실행해보면 SWT와 Swing의 차이를 확인할 수 있습니다. Swing을 사용한 어플리케이션은 윈도우에서나 리눅스에서나 적당히 비슷하면서도 적당히 어설픈 UI를 보여줍니다.

이클립스 플러그인을 제작할 때, SWT는 빈번히 사용됩니다. 마법사의 각 페이지나 Preference 페이지를 작성할 때 등등 세부 사용자 인터페이스를 정의할 때 SWT 코딩을 해야 합니다. 이클립스에서 UI를 제공하는 클래스는 다음과 같이 createContents() 메서드를 오버라이딩 함으로써 유저 인터페이스를 정의합니다. 이때 사용되는 것이 SWT 입니다.

 protected Control createContents(Composite parent) {
  // TODO Auto-generated method stub
  initializeDialogUnits(parent);
  // Get composite and set layout manager
  Composite composite = new Composite(parent, SWT.NONE);
  GridLayout layout = new GridLayout();
  layout.marginHeight = convertVerticalDLUsToPixels
    (IDialogConstants.VERTICAL_MARGIN);
  layout.marginWidth = 0;
  layout.verticalSpacing = convertVerticalDLUsToPixels(10);
  layout.horizontalSpacing = convertHorizontalDLUsToPixels
    (IDialogConstants.HORIZONTAL_SPACING);
  composite.setLayout(layout);

AWT/Swing과 다른 몇가지 SWT의 특징을 언급하고 JFace로 넘어가겠습니다. 우선 Widget간의 부모/자식 관계를 맺는 방법에서 차이가 있습니다. AWT/Swing에서는 다음과 같은 방법으로 부모 인스턴스에 자식 인스턴스를 추가합니다. 패널에 버튼을 추가하는 것을 예로 들 수 있겠습니다.

부모_인스턴스.add(자식_인스턴스);

반면에 SWT에서는 자식 인스턴스를 생성할 때 부모의 인스턴스를 첫번째 인자로 넘겨줍니다. 예제코드에서 Composite을 추가하는 부분을 참조하세요. 그리고 두번째 인자로 스타일 비츠(style bits)라는 것을 정의합니다. SWT.NONE, SWT.PUSH, SWT.CHECK 등이 스타일 비츠에 해당합니다. 이 상수들을 |로 묶어 Widget의 속성을 결정합니다. 물론 각 Widget마다 유효한 스타일 비츠가 정해져 있습니다. 마지막으로 언급할 것은 SWT가 실제 운영체제의 리소스를 사용하기 때문에 더 이상 쓰지 않을 때 해제해야 한다는 점 입니다. 대부분의 SWT Widget은 앞서 살펴본 것 처럼 생성자에서 부모를 지정하기 때문에, 부모를 폐기하면 자식도 폐기된다는 규칙에 의해서 문제가 되지 않습니다. 하지만 부모의 Widget 없이 생성된 SWT 오브젝트인 Font, Image, Color 등등은 사용하지 않을 때 직접 폐기해야 합니다.

JFace는 SWT를 보완하기 위해, 모델 기반 접근 방법(model-based approach)을 기반으로 더 적은 시간에, 더 이해하기 쉬운, 재사용 가능한 코드를 작성할 수 있도록 설계되었습니다. JFace는 UI를 효과적으로 작성하기 위한 일종의 프레임워크라고 할 수 있습니다. JFace 뷰어를 예로 들자면, JFace 뷰어가 제공하는 클래스를 상속해 정해진 절차를 따라서(!) ‘뚝딱뚝딱’ UI를 코딩하면 ‘짠!’ 하고 그럴듯한 하이퀄리티(?)의 UI를 화면에서 확인할 수 있는 것 입니다. JFace는 모델-뷰 구조로 구성되어있기 때문에, 이미 어플리케이션에서 사용하던 모델을 자연스럽게 사용할 수 있습니다. 물론 모델과 뷰사이의 연결을 담당하는 코드를 작성해야 하겠지만요. (e.g. ContentProvider , LabelProvider) JFace는 UI의 얼개에 해당하므로 SWT 역시 함께 사용해야 합니다. 

Wizard

아주 오랜만에 이클립스 플러그인에 관한 글을 다시 적게 되었습니다. 연구실에 남아있을 마지막 2주일 동안 그 동안 못다뤘던 부분들을 정리하려 합니다. 오늘은 마법사에 대해서 다루겠습니다. 마법사(Wizard)가 무엇인지는 각종 개발툴을 써보셨다면 이미 잘 알고계실 것 같습니다.  VICODE 사용자 메뉴얼을 존대말로 쓰다보니 탄력받아(?) 존대말로 쓰게 되었네요.

마법사는 여러 페이지로 구성되어 있습니다. 각 페이지는 프로젝트를 생성하는 등의 작업을 위한 일련의 단계를 표현합니다. 그리고 각 페이지는 자신에게 필요한 정보가 입력되었는지를 판단하여 마법사에게 알립니다. 마법사는 페이지의 상태에 따라 다음 페이지로의 이동가능 여부를 판단하여 UI에 반영하는 것이죠. 모든 페이지가 완료 상태에 도달하면 Finish 버튼이 활성화 되어 마법사를 종료할 수 있습니다. Finish 버튼이 클릭되면 마법사는 각 페이지에서 받은 정보를 바탕으로 원하는 작업을 수행하게 됩니다.

코드레벨에서 살펴보면 마법사는 마법사 클래스각 페이지에 해당하는 클래스의 집합으로 구성됩니다. 마법사 클래스는 페이지 클래스를 참조하고 있고  addpages() 함수에서 페이지 클래스를 마법사에 등록합니다.

지금부터는 코드를 가지고 상세구현 과정을 살펴보도록 하겠습니다. 이클립스 플러그인의 시작은 확장점입니다. 마법사를 추가할 수 있는 확장점은 총 3가지가 있는데, 이 글에서는 프로젝트 생성 마법사를 추가하는데 사용되는 org.eclipse.ui.newWizards를 사용하겠습니다. 다음코드는 확장을 정의한 plugin.xml 코드의 일부분입니다.

   <!– new project wizard –>
   <extension
         point=”org.eclipse.ui.newWizards“>
      <category
            id=”kr.ac.kaist.vicode”
            name=”VICODE”/>

      <wizard
            canFinishEarly=”false”
            category=”kr.ac.kaist.vicode”
            class=”kr.ac.kaist.vicode.wizard.NewProjectWizard
            finalPerspective=”kr.ac.kaist.vicode.perspective”
            hasPages=”true”
            icon=”icons/esterel_image.gif”
            id=”kr.ac.kaist.vicode.newprojectwizard”
            name=”VICODE Project”
            preferredPerspectives=”kr.ac.kaist.vicode.perspective”
            project=”true”/>
   </extension>

마법사 확장점에는 여러가지 속성이 있습니다. Perspective 관련 속성에는 VICODE perspective의 id를 정의하였습니다. canFinishEarly는 모든 페이지를 다 거치지 않아도 완료할 수 있는 마법사인지를 정의합니다. hasPages는 여러 페이지를 가진 마법사인지를 정의합니다. 예제로 보여드릴 VICODE 프로젝트 생성 마법사는 2페이지로 구성되어 있고 모든 페이지를 거쳐야 하므로 위의 코드와 같이 정의하였습니다.

먼저 마법사 클래스(NewProjectWizard)를 살펴보도록 하겠습니다.

public class NewProjectWizard extends Wizard implements INewWizard
{
 private WizardNewProjectCreationPage mainPage;
 private WizardInitialPage initialPage;

 private IProject newProject;

 public boolean performFinish()
 {
  createNewProject();
  initialPage.finish(newProject);
  return true;
 }

 public void addPages()
 {
  mainPage = new WizardNewProjectCreationPage(“New VICODE Project (1/2)”);
  mainPage.setDescription(“Create a new VICODE project in the workspace”);
  mainPage.setTitle(“Create VICODE Project”);
  initialPage = new WizardInitialPage(“New VICODE Project (2/2)”);
  initialPage.setDescription(“You can specify top module name and communication event.”);
  initialPage.setTitle(“Module declaration for hardware and Communication Event”);
  addPage(mainPage);
  addPage(initialPage);

 }

프로젝트 마법사 클래스는 Wizard 클래스와 INewWizard 인터페이스를 상속합니다. 예제 마법사의 목표는 두 페이지에 걸쳐 정보를 받아 들인 후 프로젝트를 생성하는 것 입니다. 총 2페이지로 구성되어 있는데, 첫번째 페이지는 구현하지 않고 이미 작성된 프로젝트 생성 페이지를 가져다가 사용하였습니다. 이 페이지는 단순히 프로젝트 이름과 저장위치를 지정할 수 있도록 구성되어 있습니다. 두 번째 페이지는 VICODE 프로젝트를 생성하는데 있어 필요한 정보를 입력받기 위해 직접 구현한 페이지입니다.

addPages() 메서드에서는 각 페이지의 인스턴스를 생성하고 초기화한 후에 addPage() 메서드를 호출하여 마법사에 각 페이지를 등록합니다. Finish 버튼이 클릭되면 호출되는 performFinish() 메서드에서 마법사 완료시에 필요한 일들을 기술합니다. 실제 프로젝트가 생성되는 코드는 첨부파일을 참조하시기 바랍니다.


지금부터는 두번째 페이지에 해당하는 코드를 살펴 보겠습니다.

public class WizardInitialPage extends WizardPage
{
 public void createControl(Composite parent)
 {
  Composite composite = new Composite(parent, SWT.NONE);
  GridLayout gridLayout = new GridLayout();
  gridLayout.numColumns = 1;
  composite.setLayout(gridLayout);
  createModuleNameGroup(composite);
  createCommunicationGroup(composite);
  setControl(composite);

  updatePageComplete();
  setMessage(null);
  setErrorMessage(null);

 }
 private void updatePageComplete()
 {
  setPageComplete(false);
  // 페이지의 완결성 체크
  if (moduleNameText.getText().equals(“”))
   return;
  // 페이지의 완결성 체크를 건너 뛰었다면 페이지를 완료상태로 변경
  setPageComplete(true);
  setMessage(null);
  setErrorMessage(null);

 }

마법사의 모든 페이지 클래스는 WizardPage 클래스를 상속합니다. UI를 정의하는 다른 클래스와 마찬가지로 createControll() 메서드에서 SWT로 사용자 인터페이스를 작성합니다. 마지막에 호출되는 메서드인 updatePageComplete()는 페이지에 필요한 정보가 입력되어 있는지를 판단하기 위해 제가 작성한 메서드 입니다. 이 메서드는 각 컨트롤에서 값이 변경될때마다 호출되어 페이지가 완료상태인지를 setPageComplete() 메서드를 호출하여 마법사에 알립니다.

이상으로 이클립스 플랫폼에서 마법사를 구현하는 방법에 대해서 말씀드렸습니다. 아래 첨부한 소스코드를 참조하시면 이해하시는데 도움이 될 것 같습니다.

bk20.java

리콜

사용자 삽입 이미지
요즘 내가 하고 있는 일은 유종의 미를 거두고 원할한 인수인계를 위해 내가 개발한 VICODE의 사용자, 개발자 메뉴얼을 작성하는 것이다. 간단한 예제에 대하여 개발하는 과정을 직접 따라가며 메뉴얼을 작성하던 중 사진 아래에 보이는 임베디드 보드를 활용하여 실제로 시스템을 구현하는 단계에 이르렀다.

VICODE의 핵심기능 중 하나는 임베디드 리눅스에서 돌아가는 소프트웨어와 임베드드 보드에 붙어 있는 FPGA의 하드웨어간의 인터페이스를 자동으로 생성하는 것이다. 하드웨어와 소프트웨어 사이의 연결통로를 자동으로 생성해주어 소프트웨어는 라이브러리를 사용하듯 API를 호출하여 하드웨어와 통신할 수 있도록 하는 것이다.

원하는 시나리오는 다음과 같다. 소프트웨어가 A()라는 함수를 호출하고 B()라는 함수를 호출하면 LED 1번에 찬란하게 빛이 들어와야 한다. 그러나 결과는 깜깜 무소식! 순간 내 머리속을 스치는 단어는 “리콜”. (석사학위논문은 지도교수가 6개월안에 취소할 수 있는데 우리는 이를 흔히 “리콜”이라고 부른다.) 순간 마음이 분주해졌다. 소프트웨어 버그였다면 비교적 금방 찾겠지만 소프트웨어와 하드웨어사이의 통신은 몇 단계를 거치기 때문에 무엇이 문제인지 찾기 힘들다. 결국 묵혀둔 연구노트를 펼쳐 원인을 발견하고 문제해결에 성공. 희망의 LED가 찬란하게 빛났다.

아직 연구실에서 해야할 일이 많지만 내가 원해서 하는 일이기에 즐겁게 하고 있다. VICODE를 이어서 개발하게 될 재호형이나 올해 연구실에 들어올 석사신입생들의 시행착오를 조금이라도 줄여줄 수 있다고 생각하니 뿌듯한 마음이 든다. 떠나는 뒷모습이 아름답도록(?) 남은 기간 내게 주어진 일들을 즐겁게 매듭짓자!

카네기 행복론

카네기 행복론
데일 카네기 지음, 최염순 옮김/씨앗을뿌리는사람

<카네기 인간관계론>과 함께 평생을 두고두고 반복해서 읽고 실천해야 할 책을 만났다. 난 참 걱정이 많은 사람이였다. 몇 년 전까지만 해도 내 별명은 “걱정돌이”였다. 일어나지 않을 일들에 대해서 쓸데없이 걱정하고 마음쓰는 것은 항상 나를 갉아먹었다. 그러던 것이 대학교를 졸업하고 대학원을 진학하면서 자신감이 붙어서인지, 마음가짐이 달라져서 인지, 책을 읽고 깨달은 바가 있어서 인지는 정확하지 않지만 전보다 많이 태연해졌다.

<카네기 행복론>의 원제는 <HOW TO STOP WORRYING AND START LIVING>이다. 걱정 없이 사는 것이 결국 행복한 삶을 이루는 전제조건임을 이해한다면 책의 제목은 썩 잘 어울리는 것 같다. 정말 완벽하게 걱정을 극복하기 위한 여러가지 생활수칙이나 마음가짐을 제사하고 있다. 심지어 “피로와 걱정을 방지하고 늘 원기 있게 사는 방법”까지 소개하고 있다. 책의 마지막에는 여러 사람들이 “걱정 근심을 극복한 사례”가 실려있다.

사실 이 책에 나열되어 있는 여러가지 방법은 내가 다른 책이나 인터넷에 돌아다니는 글에서 한 두번은 접했을 법한 것들이다. 그러나 이 책은 그 것들을 체계적으로 정리하고 많은 사람들의 임상(?)경험을 토대로 소개하고 있기에 설득력을 더하고 있다.

특히 “인간은 정신적인 작업만으로 피곤을 느끼지 않는다는 것”과 “피로의 대부분은 정신적, 감정적인 태도에 기인한다”는 부분이 흥미로웠다. 피로의 원인은 고민, 긴장, 감정의 혼란이라고 한다. 또한 권태로움 역시 피로의 결정적인 원인이 된다고 한다. 내게 주어진 일을 재미있게 해낼 수 있는 지혜와 인생의 고민을 슬기롭게 받아들이고 극복하려는 노력이 필요하다. 걱정과 고민으로 힘겨운 나날을 보내고 계신분께 강력추천!