이 글은 Eclipse Corner Article에 기재된 Inside the Workbench: A guide to the workbench internals 의 내용을 기반으로 작성되었다. 링크된 Stefan Xenos의 원문은 문서 버전 1.5에 근거해서 발행되었으며, 필자의 번역본은 2006년 1월에 일부 내용이 수정된 버전 1.6을 근거로 작성하였다. 설명이 필요한 부분은 필자가 각주를 추가했다.

요약

  이  글은 Eclipse 3.1의 Workbench가 View와 Editor를 위한 기반 구조로서 어떻게 동작하는지 설명한다. 목표는 Workbench 내부의 주요한 클래스를 익히고 어떻게 그들이 서로 작용하는지 가르치는 것이다. 이 글은 View, Editor, Action Set 등에 대해 친숙하다는 것을 전제로 쓰여졌다.

Stefan Xenos, IBM
January 6, 2006


1.0 도입

 이 문서는 워크벤치의 내부를 설명하기 위함이지, API를 설명하려는 것은 아니다. 내부의 설계는 자주 바뀌기 마련이다. 만일, 보다 새로운 이클립스에 대해서라면, UI development resources page에서 이 문서의 최신 버전을 구할 수 있을 것이다.

그림 1: View와 Editor의 종속 관계


그림 1은 view와 editor가 어떻게 워크벤치에 의해 다루어지고 있는지를 나타낸다.


 Workbench는 한 개 이상의 WorkbenchWindow를 포함하는데, 다시 각각의 WorkbenchWindow는 0개 이상의 WorkbenchPage를 갖는다. WorkbenchWindow 는 창의 외곽, 다시 말해 trim 위젯[각주:1]들을 제공하며, WorkbenchPage는 창의 본 내용을 제공한다. 이론적으로는 한 WorkbenchWindow가 어떤 수의 page라도 가질 수 있지만, 실제로는 window 한 개 당 하나의 page를 넘지 않는다.

 View와 Editor들은 각각 ViewFactory와 EditorManager를 통해 page의 관리 하에 놓인다. EditorManager는 editor들의 목록과 그들의 공유 리소스를 저장하며, ViewFactory는 view의 목록을 참조 카운트와 함께 관리한다. Workbench 는 EditorReference와 ViewReference를 이용하여 동작하며, 이 글에서도 "editor"나 "view"라는 말은 이 레퍼런스 클래스들을 지칭하는 것이다. Editor와 View의 구별이 그렇게 중요하지 않은 상황에서는, 간단히 "part"라는 용어로 이들을 통칭할 수 있다. part 구현체(구체적으로는 IEditorPart 또는 IViewPart의 구현체이다)는 그것이 최초로 필요한 순간에야 비로소 생성된다. 그림 2에서 보여지듯이 Part에 대한 Reference들은 모든 tab이 가지고 있지만, 실제 그 구현체[각주:2]는 처음 보여질 때 한 번 생성된다.

  Page는 perspective를 가지는데, 이 Perspective는 화면 레이아웃과 그 레이아웃에서 어떤 action set이 사용가능한가에 대한 정보를 가지고 있다. 그림2에서는 Perspective가 view와 editor 영역을 포함하고 있는 것처럼 보일지 모르나, 그들은 단지 (화면에 어떻게 표현될지를 나타내는) 레이아웃을 가지고 있을 뿐이다. 몇 개의 perspective가 각각의 view를 사용하고 있는지를 나타내는 참조 카운트를 Page가 관리하고, 또한 part와 editor 영역에 대해서도 전권을 가지고 관리한다.

  그림 1에서 나타나지 않은 것이 PerspectiveHelper와 EditorAreaHelper 클래스이다. 이 클래스들은 주로 히스토리 관리의 용도로 사용되는데, 이 글에서도 PerspectiveHelper를 Perspective 클래스의 일부인 것 처럼, EditorAreaHelper를 WorkbenchPage클래스의 일부인 것처럼 다루는 것을 볼 수 있다.

그림 2: Workbench 객체들과 각각의 형태



2.0 파트의 내부

그림3: 파트의 구성도

  그림3과 같이, 파트 내부는 몇 개의 객체들로 구성되어 있다. WorkbenchPartReference는 파트의 최상위 표현이다[각주:3]. 쓰이는 곳에 따라, part reference는 IWorkbenchPartReference, IViewReference, IEditorRefenece, IPresentablePart, PartPane의 형태로 노출된다. 이것들은 결국 같은 객체에 대한 서로 다른 인터페이스이다. WorkbenchPartReference와 이를 상속한 클래스들이 I*Reference 인터페이스를 직접 구현하는 것이다. IPresentablePart는 part에 있는 메서드를 직접 재호출하는 단순한 adapter 클래스이다. PartPane은 워크벤치 layout내에 특정 part를 위치시킬 때 필요한 LayoutPart를 구현한다. 그리고 PartPane은 워크벤치의 layout에 있는 컨트롤을 포함시키기 위해 필요한 SWT자원을 관리하기도 한다.

  IEditorPart 나 IViewPart와 같은 part의 구현체는 reference가 소유한다[각주:4]. 이들의 구현체가 생성될 때 PartSite가 인자로 전달된다. 클라이언트 코드의 입장에서 IWorkbenchPartSite나 IEditorSite, 혹은 IViewSite의 형태인 PartSite는 클라이언트의 코드로 하여금 reference와 통신을 하고, Part의 구현체를 위해 만들어진 서비스를 이용할 수 있도록 한다.

 WorkbenchPartReference는 SWT 자원을 필요한 순간에야 비로소 할당[각주:5]한다. 일단 생성되면,  part reference는 반드시 명시적으로 폐기(dispose)되어야 한다. reference 폐기는 Part 구현 자체를 포함한 모든 리소스를 정리하고, 더 이상 추가의 자원을 할당하지 않을 것을 보장하는 것이다. 일단 특정 Part를 다시 사용할 필요가 없을 것이 확실하면, workbench page는 part reference를 폐기한다. SWT 컨트롤들과는 달리, 폐기된 이후에도 reference를 계속해서 사용하는 것이 유효하다. 폐기된 후의 part reference는 자신의 이름을 반환하고, workbench page의 어떤 메서드와도 사용할 수 없다는 것을 빼고[각주:6]는 어떤 흥미로운 점도 없을 것이다. reference의 라이프 사이클을 추적한다는 것이 클라이언트에게는 (거의 불가능할 정도로) 어려운 일이기 때문에, 폐기된 후에도 계속 reference의 public 멤버에 접근하는 것은 허용되고 있다.

2.1 Part Lifecycle

그림 4: WorkbenchPartReference의 상태


  그림 4는 state machine[각주:7]로서의 part의 라이프 사이클을 나타낸다. part reference는 현재 상태를 정수형 필드(멤버 변수)에 저장한다.

Notes:
  • Part는 구현체를 생성하고 있는 중에 특정 상태에 놓이게 된다. 이 상태에서, 구현체는 재귀적으로 재생성되거나 폐기될 수 없다.
  • Part 구현은 해당 Reference가 폐기되면 다시 생성될 수 없다.
  • Part는 한 번 생성 완료되면 lazy 상태로 돌아가지 못한다. 이것은 기능적인 요구사항이 아니라 3.1 구현의 제약이다.
  • 폐기된 이후에도 WorkbenchPartReference 의 public 멤버를 접근하는 것은 계속 유효하다. 그러나, 폐기된 reference는 workbench page의 메서드에 전달되어 사용될 수 없다. (말그대로 더 이상 Page의 일부가 아니기 때문이다.)

2.2 Part 생성

  그림 5: part 생성시의 메세지 순서

 


  그림5는 part의 생성 과정을 나타낸다. 가운데 평행선에 의해 part 생성은 두 단계로 나누어진다. 첫번째 단계에서는 part가 layout에 더해지고, 그리고 나서 실제적인 구현체가 첨부된다. 이것은 두 개로 구분되어지는 동작이며, 따라서 part는  그것이 눈에 보이기 전까지 한동안 그 구현체[각주:8] 없이 존재할 수 있다. 이 그림은 part reference간의 상호작용에 주로 초점을 맞추고 있어, 프리젠테이션에 part를 추가하는 것과 part site를 생성하는 것은 생략되어 있다.

  첨언: part가 성공적으로 생성될 수 있다면 (이를 위해서는 구현체의 init 메서드에서 발생해 WorkbenchPage.openEditor에 메서드까지 전달되는 예외인 PartInitException이 발생되지 않고 통과해야 한다.), layout 에 part를 첨부만 하는 것이 유용한 경우들이 있다. 이러한 경우에 layout에 part를 추가하기 전에 part를 미리 생성하고, 이를 이용해 두 개의 분리된 동작을 하나의 원자성을 지닌 행위로 합치는 것이 가능하다. 이것이 event 전달과 관련된 버그를 만드는지는 알려져 있지 않다.
  1. Trim은 메뉴나 툴 바, 상태 바 등이 위치해 있는 Page 외곽 부분을 의미한다. 아래의 그림 2를 참고한다. [본문으로]
  2. 여기서 구현체는 IWorkbenchPart의 구현체를 의미하며, Part Reference와 Part의 관계는 아래 '파트의 내부' 단원을 참고한다. [본문으로]
  3. 도입부에서도 말했지만 Workbench는 직접 Part 구현체를 다루는 것이 아니라 Part Reference 클래스를 통해 접근한다 [본문으로]
  4. WorkbenchPartReference는 IWorkbenchPart형 멤버변수를 가지고 있으며, 이를 통해 part의 구현체를 소유하고 있다. [본문으로]
  5. 이러한 동작원리는 종종 영어로 lazy라고 표현된다. [본문으로]
  6. 폐기는 part reference와 part의 연결이 끊어지는 것이라고 이해하면 된다. part 이름은 reference 내에 멤버 변수로 들어있는데, 이는 연결이 끊어진 것과 무관하게 참고할 수 있다. 그러나, workbench page의 메서드를 연결이 끊어진 part reference와 사용한다면 수행되지 못할 것이다. [본문으로]
  7. 일종의 상태 집합이라고 생각하면 된다. [본문으로]
  8. 이 글에서는 part reference (IWorkbenchPartReference의 구현 클래스)와 part 구현체(IWorkbenchPart 구현 클래스)를 반복적으로 대조하며 설명하고 있다. 여기서의 구현체는 part구현체이다. [본문으로]
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
« PREV : 1 : ··· : 26 : 27 : 28 : 29 : 30 : 31 : 32 : 33 : 34 : ··· : 87 : NEXT »

티스토리 툴바