점심시간을 끼어 ITRC Forum 2007에 다녀왔다. 업무시간을 조금 까먹으면서까지 다녀온 이유는 대학원 연구실 사람들을 보기 위해서였다. 그리고 석사과정에서 개발했던 VICODE가 어떻게 발전했는지 그리고 이번에는 어떤 예제를 들고 나왔을까 궁금하기도 했다.

11시 30분 조금 넘어 행사장 입구에 도착했다. 윤경이 누나가 마중 나와서 같이 우리 연구실 부스가 있는 곳 까지 걸어가던 중 인산인해로 인해 지체 되는 곳에서 셔터가 연신 터지고 있었다.

사용자 삽입 이미지

민망한 옷 차람의 8등신 언니들이 화려한 조명 아래 다양한 포즈를 선보이니 DSRL 카메라들이 군침을 흘릴 수 밖에.  일반 기업의 전시장이 있는 곳까지는 이처럼 화려했으나 대학원 등 교육기관의 연구 실적을 전시하는 행사장 안쪽으로 들어가자 조금 전까지 느낄 수 없었던 평화로움이 나를 감싼다.

가는길에 아키랩의 한준이와 SE랩의 현정이 누나도 만났다. 그리고 드디어 우리 연구실의 부스에 도착했다. 한태숙, 한환수 교수님이 계셨고 다른 교수님들과 말씀을 나누고 계시길래 우선은 가볍게 인사만 했다. 오랜만에 현구형을 뵐 수 있었고, 내가 하던 일을 이어서 고생하는 재호형, 교수님과 밤새 납땜질 하느라 피곤해 보이는 요셉이, 새신랑 척척박사 정한형을 만날 수 있었다.

그리고 작년보다 훨씬 화려해진 VICODE로 개발한 예제를 볼 수 있었다.

사용자 삽입 이미지

작년의 기차 건널목 컨트롤러에 비하면 진일보한 무인 주차 시스템이다! 이 것이 움직이는 것을 보면서 경이롭기까지 했다. 특히 재호형이 QT를 이용해 만든 시뮬레이션 프로그램은 정말 멋졌다.

우리 교수님은 처음 만남부터 나의 연예사에 관심이 많으시더니 오늘도 떠나는 나에게 서울에 왔으니까 여자를 만나라고 당부를 잊지 않으셨다. 머리 좀 기르고 꾸미라는 조언과 함께.  왁스 바르기에서 우려했던 것이 현실로 나타난 것이다. 

"교수님은 내 머리를 스포츠 머리라고 하셨어."
"교수님은 내 머리를 스포츠 머리라고 하셨어."
"야하이야아아아~"

아무래도 무난하게 머리 길러야겠다.

Multi-page Editor는 여러페이지를 가진 에디터로, VICODE에서 spec.xml을 편집하는 Specifiaction Editor를 다음과 같이 총 4페이지로 구성된 형태의 에디터로 작성하였습니다. 이 글에서는 에디터 자체에 대한 내용보다는 여러페이지로 구성된 에디터를 작성하는 경우에 구현방법과 고려해야할 사항들에 대해서 소개하겠습니다.

0123

Specification Editor에서 편집할 spec.xml 파일은 총 3가지 section으로 구성되어 있습니다. 에디터의 처음 3페이지는 각 section의 편집과정을 돕기 위해 컨트롤로 구성된 폼 에디터를 제공하며 마지막 페이지는 spec.xml을 직접 편집할 수 있도록 XML 에디터를 포함하고 있습니다.

구현 디테일로 들어가기 이전에 Multi-page Editor를 구현할 때 고려해야 할 사항에 대해서 설명하겠습니다. Multi-page Editor는 하나의 EditorInput을 여러 페이지에서 편집하게 되므로 편집하는 내용이 겹치는 경우에는 서로 다른 페이지 간의 값을 동기화 처리를 해주어야 합니다. 이 글에서 설명하는 페이지간의 동기화 방법은 직접 고안한 것이므로 효율적이지 않을 수 있습니다. ^^;

VICODE의 Specification Editor의 경우에 EditorInput은 spec.xml 입니다. 처음 3페이지의 폼 에디터와 마지막 페이지의 spec.xml 페이지는 편집의 범위가 겹치게 됩니다. 게다가 spec.xml을 구성하는 3가지 section 사이에서도 서로 값이 의존적으로 사용되기 때문에 각 페이지에서 변경된 값은 항상 다른 페이지에도 적용되어야 합니다. VICODE의 경우 다음과 같이 3가지 객체의 값이 동기화된 상태로 유지되어야 합니다.

spec.xml - AST - 각 페이지의 컨트롤이 가지는 값

AST는 spec.xml을 파싱해서 얻게 되는 Abstract Syntax Tree를 의미합니다. 에디터가 실행되면 spec.xml을 파싱해서 AST에 저장하게 되고 각 페이지의 컨트롤의 값은 AST의 값을 바탕으로 채워지게 됩니다. 이 것은 제가 말한 동기화의 아주 일부분이죠. 상세내용은 뒤에서 다루기로 하고 일단 코드를 보도록 하겠습니다.

우선 Editor의 확장점은 org.eclipse.ui.editors 입니다. Multi-page editor의 확장은 다른 editor의 확장방법과 다르지 않습니다. 다음은 확장을 정의한 plugin.xml의 일부입니다.

<extension
         point="org.eclipse.ui.editors">
      <editor
            class="kr.ac.kaist.vicode.editor.spec.SpecEditor"
            contributorClass="kr.ac.kaist.vicode.editor.spec.SpecEditorContributor"
            default="true"
            filenames="spec.xml"
            icon="icons/sample.gif"
            id="kr.ac.kaist.vicode.editor.spec.SpecEditor"
            name="Specification Editor"/>
</extension>

filenames 속성을 통해 spec.xml 파일에만 적용되도록 정의하였습니다. 이제 에디터를 구현한 SpecEditor 클래스를 살펴보겠습니다.

public class SpecEditor extends MultiPageEditorPart
    implements IResourceChangeListener
{
 private final String endl = "\n";
 private TextEditor editor;
 private String specFilePath;
 private int currentPageIndex = 0;
 private int editorPageIndex;
 private CommunicationPage communicationPage;
 private ApiPage apiPage;
 private RulePage rulePage;

 private Spec spec;

MultiPageEditorPart를 상속하여 구현합니다. 멤버변수로 눈여겨 보아야 할 것은 각 페이지를 참조할 수 있는 인스턴스와 AST를 저장하는 spec 입니다. ApiPage 등은 Composite을 상속한 클래스로 페이지를 구성하는 컨트롤을 정의하고 있습니다. editor는 마지막 페이지를 구성하는 XML 에디터의 레퍼런스 입니다. 이제 각 페이지를 어떻게 에디터에 추가하는지 살펴보겠습니다.

 protected void createPages()
 {
  createCommunicationPage();
  createApiPage();
  createRulePage();
  createXmlEditorPage();
 }
 void createRulePage()
 {
  rulePage = new RulePage(getContainer(), SWT.NONE, this);
  int index = addPage(rulePage);
  setPageText(index, "Rule");
  rulePage.setSpec(spec);
 }
 void createXmlEditorPage()
 {
  try
  {
   editor = new XMLEditor();
   editorPageIndex = addPage(editor, getEditorInput());
   setPageText(editorPageIndex, editor.getTitle());
  }
  catch (PartInitException e)
  {
   ErrorDialog.openError(getSite().getShell(), "Error creating nested text editor", null, e.getStatus());
  }
 }

createPages() 메서드에 페이지를 추가하는 코드를 작성해 주어야 합니다. 여기서 불리는 createRulePage()를 살펴보면 addPage() 메서드를 이용해서 에디터에 페이지를 추가하는 것을 확인할 수 있습니다. XML 에디터를 추가하는 createXmlEditorPage() 메서드에서는 addPage() 메서드의 두번째 인자에 Multi-page Editor의 EditorInput(spec.xml)을 넘겨줍니다.

Multi-page Editor에서 save가 발생한 경우 호출되는 doSave() 메서드를 작성해야 합니다.

 public void doSave(IProgressMonitor monitor)
 {
  if (currentPageIndex == editorPageIndex)
  {
    getEditor(editorPageIndex).doSave(monitor); // save
   Xml2Spec parser = new Xml2Spec(specFilePath);
   spec = parser.parseSpec(); // parsing to get AST

   communicationPage.setSpec(spec); // set AST to each page
   apiPage.setSpec(spec);
   rulePage.setSpec(spec);

  }
 }

Specification Editor에서 첫 3페이지는 저장 명령이 유효하지 않고 Apply 버튼을 클릭함으로써 수정내용을 AST와 파일에 적용하도록 구성되어 있습니다. Reply 버튼을 클릭하면 AST의 내용으로 컨트롤의 값을 복구 합니다. 반면에 4번째 페이지인 XML 에디터 페이지를 선택한 경우에 저장하게 되면 XML 에디터의 doSave() 메서드를 호출하여 spec.xml에 저장하게 됩니다. 저장이 완료되면 spec.xml의 내용이 갱신되었기 때문에 이를 다시 파싱하여 새로운 AST를 얻고 각 페이지에 setSpec() 메서드를 이용해 AST를 갱신해줍니다. 각 페이지는 이 AST를 이용해 컨트롤에 값을 설정하겠죠.

다음으로는 페이지가 변경되었을 때 호출되는 pageChange() 메서드를 볼까요?

 protected void pageChange(int newPageIndex)
 {
  switch (newPageIndex)
  {
  case 0:
   communicationPage.updatePage(); // AST to control
   break;
  case 1:
   apiPage.updatePage();
   break;
  case 2:
   rulePage.updatePage();
   break;
  case 3:
   updateSpecFile(); // AST to spec.xml
   break;
  default:
  }
  currentPageIndex = newPageIndex; // save current page index
 }

처음 3페이지가 선택된 경우에는 AST의 내용을 바탕으로 컨트롤의 값을 채워주는 함수인 updatePage() 메서드를 호출합니다. 4페이지가 선택된 경우에는 AST의 내용을 spec.xml에 저장합니다. 따라서 XML 에디터는 최근 변경된 spec.xml의 코드를 출력하게 됩니다.

흐름을 다시 정리해보면, 에디터가 열리면서 spec.xml을 파싱하여 AST를 저장합니다. 처음 3페이지가 선택된 경우에는 AST의 내용을 가지고 페이지를 구성하는 컨트롤의 값을 채웁니다. 이 컨트롤의 값을 수정한 후 Apply 버튼을 누르게 되면 AST를 갱신함과 동시에 spec.xml 파일을 AST를 가지고 저장합니다. 반대로 XML 에디터에서 수정하고 저장한 경우에는 저장된 spec.xml 파일을 다시 파싱하여 AST를 구하고 이 것을 각 페이지에 넘겨줍니다.

이해를 돕기 위해 아래에 SpecEditor.java, RulePage.java 파일을 예제로 남깁니다.
 
사용자 삽입 이미지

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

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

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

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

마지막 Term paper 제출을 끝으로 내 인생의 마지막(?) 수업이 마무리되었다. ACM 형식으로 4장의 논문을 쓰는 것은 생각보다 훨씬 어려운 일이였다. 글자가 매우 작고 문단 사이에 한줄도 띄워주지 않는다! 이런면에서는 IEEE가 친절하다. 쓰기 전 구상에 따르면 4장을 넘어가면 어쩌나 행복한 걱정을 하고 있었건만, 겨우 4장 근처에 도달할 수 있었다.  

비록 삼일동안의 초치기 작업이였으나, 석사논문주제가 될 것만 같은(?) 내용으로 논문을 작성하며 related work을 살펴보았기에 후일을 위해 도움이 되었다는 생각이 든다. Latex로 작성하는 두번째 논문! 중딩 교과서에 나올법한 영어를 구사하였지만 언제나 Latex로 작성 완료후, pdf로 변환하여 인쇄해서 바라보고 있으면 너무나 그럴 듯 한 모양에 마치 논문을 잘 쓴 것 같은 착각에 빠진다.

이 논문에서 제시하였던 future work을 실제로 고민하고 구현하는 일이 이번 방학의 미션이다. 물론 석사논문의 related work과 introduction 정도는 천천히 써두어야겠다. 그래야 허접한 실력이지만  영어로 논문을 쓸 수 있을 듯 ...  

논문을 쓰며 영작을 공부하고 싶어졌다. 2학기에 여력이 남으면 학교 어학원에서 영작 수업도 들어야겠다!

+ Recent posts