특집기사:선언적 UI로의 변화

위클립스
이동: 둘러보기, 찾기
Article.png 특집기사 정보
Jeeeyul.jpg
저자 이지율

Eclipse 3.2 부터 현재에 걸쳐 일어난 가장 중요한 아이디어의 변화 중 하나는, 툴바나 메뉴의 표시가 코드 중심에서 XML 선언형식으로 변경된 것이다. 또한 이 아이디어는 E4워크벤치 돔화, XWT를 이용한 모든 UI의 선언화등의 과도기적 절차로 볼 수있다.

이 문서는 그러한 변화가 일어난 과정을 설명함으로써, 새로운 방식을 도입할 수 있도록 동기를 부여하는 것을 그 목적으로한다.

목차

[편집] JFace

이클립스SWT/JFace 애플리케이션이므로, 이클립스의 UI에 대해서 이야기하려면 JFace에 대해 먼저 이해가 조금 필요하다.

JFace의 철학에 따르면 사용자가 시스템과 상호작용하는 방식은 크게 다음으로 요약된다:

이런 아이디어에 입각하여, IAction 들은 툴바, 메뉴, 컴포지트 등에 채워질 수 있고, 이렇게 채우는 행위를 기여(Contribution)이라고 한다. 비즈니스 로직이나 일련의 기능을 사용자가 사용할 수 있도록, UI에 배치한다는 의미로 기여라는 용어가 사용된다.

이런일을 자동으로 수행 해 주는 구조적 컨트롤러를 컨트리뷰션 매니저(IContributionManager)라고 한다. 컨트리뷰션 매니저에서 일어나는 각IAction에 대한 기여를 다루는 단위가 액션 컨트리뷰션 아이템(ActionContributionItem)이다.

예제:

// 액션
IAction myAction = ...;
 
// 액션 컨트리뷰션 아이템
ActionContributionItem contributionItem = new ActionContributionItem(myAction);
 
// 액션을 메뉴와 툴바에 기여시킴
contributionItem.fill(myMenu, myMenu.getItemCount());
contributionItem.fill(myToolbar, myToolbar.getItemCount());

컨트리뷰션 매니저중 하나인 IMenuManager를 이용하면 여러개의 액션을 쉽게 다룰 수 있다:

IAction myAction = ...;
IMenuManager menuManager = ...;
 
menuManager.add(myAction);
menuManager.update(false);

간단한 RCPJFace 애플리케이션의 경우 이런식으로 IAction이 run() 메서드를 통해 비즈니스 로직을 직접 갖더라도 별 문제가 되지 않았고 빠르고 간결해 보인다. 그러나 곧 문제점들이 드러나기 시작했다.

[편집] 리타겟터블 액션

이클립스의 복사하기, 잘라내기, 언두, 리두 등과 같은 액션은 현재 상태(활성 에디터나 뷰, 선택, 셀 에디팅 상태 진입여부 등등)에 따라 다르게 작동해야 한다. 그리고 이러한 환경을 얼마든지 더 복잡해질 수 있는데, 사용자가 어떤 플러그인 구성으로 설치하여 이클립스를 사용할지 알 수 없기 때문이다.

그럼에도 이들은 동일한 UI로 기여되어야 한다. (시스템 메뉴의 편집 메뉴)

여기서 문제가 생긴다. 공통 UI를 만들기 위해서 JFace 아이디어에 따라 이미 액션이 작성되었을 것이다. 그런데 그 액션은 비즈니스 로직을 포함하지는 않는다. (상황에 따라 다르게 동작해야 하므로) 비즈니스 로직과 Action이 분리되야 하는 상황이 온 것이다. 이를 위해 액션바, 리타게터블 액션등등이 생겨났고, 이들의 개념은 필요에따라 세분화되고 발달되는 과정에 너무 어렵고 복잡해지고 말았다.

예를 들어 테이블의 한 로우(Row)를 선택하고 Copy 명령을 내렸을 때와, 그 로우에서 특정 셀을 편집하는 중에 Copy 명령을 내렸을 때 다르게 반응해야 할 것이다. 그런데 이 경우 뷰 사이트의 액션바에 Copy 액션을 등록해 두었다 하더라도 별 소용이 없을 것이다. 왜냐하면 액티브 파트가 변경되지 않았지만, 액션은 변경되어야 하는 상황이기 때문이다. 따라서 이 경우엔 비즈니스 로직만 변경하기 위해 리타게터블 액션을 쓸 수 없다.

물론 이러한 특정한 케이스마다 대응 API가 공급되기는 하지만, 이를 전부다 파악하고 배우는 것은 매우 어렵다.

Action은 본래 비즈니스 로직을 내부에 갖게끔 의도되었지만, 이제는 델리게이트, 또는 리타겟, 혹은 글로벌 액션 매니저에 의한 동적맵들과 같이, 많은 다른 방식들로 혼재되어 사용되기 시작했다.

[편집] 값비싼 초기화

그 후, 이클립스 플러그인들은 폭발적으로 늘어났다. 이에 따라 스케일과 관련한 문제가 생겨나기 시작했다. Action은 class로 기술되기 때문에 메뉴나, 툴바를 그리기 위해 반드시 클래스가 로드되어야만 한다. 클래스가 로드되면 플러그인의 클래스로더에 의해, 플러그인 초기화가 일어나게 되고, 디펜던시 트리를 따라 이와 같은일이 반복된다.

기능이 추가될 수록 어느정도의 선형 퍼포먼스 감소는 일반적이지만, 사용자가 기능을 사용도 하기 전에, 단지 메뉴나 버튼을 표시하기 위해 Action 클래스가 로드되며 해당 플러그인 및 디펜던시가 모드 로드되며 느려지는 것은 문제가 되었다.

이클립스를 시작시키는 일은 사용자에게 스트레스를 주는 일이 되기 시작했다. 레이지 패턴의 도입이 시급한 상황이 되었다.

[편집] 선언적 UI

이클립스의 선구자들은 UI가 선언적으로 나타낼 필요가 있다고 생각했고, XML만으로 메뉴나 툴바를 나타낼 수 있는 방법을 만들어 냈다.

그 결과를 구성하는 두가지 요소는 다음과 같다:

일반적인 아이디어는 다음과 같다.

  1. 확장점을 통하여 간단하게 어떤 명령(Command)을 XML로 정의한다. 예를 들어 *공격* 이란 명령어가 있다고 가정하자. 이 명령은 단지 "공격" 이라는 말 일 뿐, IAction과는 달리 어떠한 구현도 갖고 있지 않다.
  2. 사용자가 마린을 선택하고, 이 명령을 제출하면 마린은 사격을 시작할 것이다. 반면, 히드라를 선택하고 그렇게 한다면 침을 뱉기 시작할 것이다. 비즈니스 로직은 여기 어딘가 쯤에 있다.

실제 이클립스 플랫폼에서의 시나리오는 다음과 같다:

  1. 이클립스 커맨드 프레임워크도 마찬가지로 명령이 제출되면,
  2. 현 시점에서 그 명령을 처리하기 적합한 핸들러를 찾는다. 핸들러는 핸들러 확장점을 통해 기여 된다. 핸들러에 기술된 Core Expression으로 언제 이 핸들러가 임무를 담당하기 시작하는가와 언제 이 핸들러가 이 명령을 처리할 수 있는가에 대한 XML 평가식을 표현할 수 있기 때문에, 플랫폼은 핸들러를 정확히 선택할 수 있다.
  3. 플랫폼이 제출된 커맨드를 핸들러가 처리하도록 한다.

이 핸들러는 class로 기여되지만, 사용자가 실제로 명령을 내려, 플랫폼이 그 핸들러가 필요하다고 판단하여, 핸들러가 비즈니스 로직을 수행하기 직전까지, 어떠한 클래스가 로드되지 않고, 그 클래스를 가진 플러그인은 시작되지 않는다.

이 커맨드를 사용자가 제출하려면 어떤 형태든 UI또는 단축키(바인딩)등이 필요할 것이다. 이때 사용되는 것이 메뉴 확장점바인딩 확장점이다. XML을 이용하여, 어떤 위치에 어떤 커맨드를 노출시켜라 라고 기술할 수 있다. plugin.xml은 플러그인이 시작하지 않더라도 플랫폼에 의해 모두 로드되므로, 추가적인 로드 없이 UI를 만들 수 있게 된다. 메뉴 확장점핸들러와 마찬가지로 코어 익스프레션을 이용하여, 특정 커맨드가 언제 노출되어야 하는지를 기술하는 식을 가질 수 있다.

이렇게 모든 명령의 존재와, 명령이 어디에 기여될 것인지를 XML 만으로 기술 할 수 있다.

이러한 방식은 다양한 이득을 가져왔다:

이러한 아이디어는 E4에서 더욱더 발전된 형태로 나타나, 액션 뿐만아니라, SWT로 UI를 작성하던 것들도 대치하고 있다.

[편집] 참조

이 기사에 대한 의견은 토론 페이지를 통해 나눌 수 있습니다.

개인 도구
이름공간
변수
행위
포탈
탐색
도움
도구모음