특집기사:Xtend를 이용한 영역지향 문제 처리

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

문서에 대한 설명.

목차

[편집] 개요

알다시피, 개발자들은 문제 해결 전략에 아주 부적합한, 지랄같은 입력 모델을 공급받기 마련이다.

재사용이라 불리는, 고대의 전설을 좇는 거룩한 MVC 율법에 따라, 모델들은 모든 뷰 및 컨트롤러들에 대하여 비협조적이어야 할 고상한 의무가 있기 때문이다.

물론 모델의 디자이너는 가능한한 다양한 쓰임새들의 공통 관심사를 지원하려고 노력하겠지만, 그렇게 만만한 세상이 아니란 말씀. 그런 시도들 속에서 확장성과 원자성 같은 가치들은 곧잘 충돌을 일으키곤 한다. 설계자는 가능한한 미래를 내다보며 이들을 중재하겠지만, 요구사항이 급변하는 지금과 같은 세상에서, 이런 접근 법은 엄청난 설계 비용을 야기한다. 근데, 그렇게 해놔도 또 설계는 반드시 깨지기 마련이다.

아멘.

이 문서가 MVC를 까려는 것은 아니니 오해는 말아 주었으면 좋겠다. 다만 문제를 해결하기 위한 새로운 방법을 익히고자 하는 동기를 불러 일으키고 싶은 것 뿐이다.

여하튼 이런 문제를 해결하기 위한 몇몇 패턴이나, 새로운 형태의 언어, 그리고 기존 언어의 확장등이 존재한다. 이런 문제를 해결하는 주된 접근법은 영역을 모듈화 하는 것이고 이러한 트렌드를 영역 지향이라고 한다. 여기서는 자바의 확장 언어인 Xtend를 이용하는 방법을 소개할 것이며, 영역지향의 모든 특징을 소개하지는 않을 것이다.

[편집] 영역 지향

쓰임새 하나당 하나의 소스파일만 영향을 받으면 얼마나 좋겠냐만은, 하나의 쓰임새가 구현되기 위해서는 보통 많은 컴포넌트가 참여해야 한다. 이 참여 위상을 우선 덩어리라고 불러보자. 이런 저런 쓰임새가 늘어남에 따라, 여러 덩어리가 생겨난다. 이 덩어리들은 서로 겹치기도하고 동떨어지기도 하는등 외각선이 일치 하지 않고 여기 저기에 흩어지게 된다.

한 컴포넌트는 일관성이 없는 여러 쓰임새(덩어리)에 참여하게 되고, 이러한 현상은 쓰임새가 추가될 때 마다 더 심해진다. 문제 해결에 필요한 관심사가 한 곳에 집중되지 못하고 흩어지므로 문제 자체를 추적하고 읽는 것이 점점 더 어려워진다. 이렇게 흩어져서 구현되어 버린 문제를 전역적 관심사(Cross-Concerned)라고 한다. 물론 컴포넌트들이 본연의 고유 임무를 잘 설명하던 원자성을 조금씩 잃게 되는 것은 두 말할 필요도 없다.

여기서 각각의 덩어리를 영역(Aspect)이라고 한다.

영역지향의 주요 아이디어는, 특정 쓰임새를 물리적으로 한 군데 따로 떼어내서, 그 안에서만 영역에 관한 문제를 잘 설명할 수 있게하고, 기존에 존재 하는 다른 컴포넌트들을 전혀 건드리지 않는 것이다.

이는 궁극적으로 문제 해결에 대한 기술을 논리적으로도 물리적으로도 쓰임새를 중심으로하는 관점에서 한군데 작성되는 것을 목표로 한다.

[편집] Xtend

사실 Xtend는 좁고 구체적은 의미에서 영역 지향 관점의 기술은 아니지만, 영역지향 측면에서 다음과 같은 장점들이 있다:

Xtend 2.3 부터는 JDT로 디버깅 할 경우, 바로 Xtend 소스로 로케이팅 된다.

[편집] Inter-type 선언

우리에게 다음과 같은 모델이 공급되었다고 가정하자:

우리가 해결해야할 문제는 다음과 같다:

이메일의 내용은 다음과 같다:

안녕하세요 이지율 사우님, 
현재 사내 인트라넷에 전화번호가 등록되어 있지 않으니, 빠른 시일내에 등록 부탁드립니다.
감사합니다.

인터 타입이란, 모델의 소스를 수정하지 않고도, 모델 외부(특정 영역)에서 속성이나 메서드를 추가하는 기술을 말한다. 이는 특정 쓰임새에서만 유용한 속성이나 동작을 정의할 수 있게해, 쓰임새의 코드를 읽는 것을 매우 쉽게 만들어 준다:

Xtend에서는 다음과 같은 방법으로 인터 타입을 선언할 수 있다:

// Xtend에서 첫번째 인자는 주어로 취급될 수 있다.
def fullName(Employee p){
  p.firstName + p.lastName
}

이제 이 Xtend 클래스 내에서 Employee 인스턴스들은 fullName이라는 추가적인 속성을 가지게 된다. 따라서 다음과 같은 메일 내용을 생성하는 함수를 정의 할 수 있다:

// 인터 타입으로 선언된 Employee 인스턴스의 fullName 속성을 사용한다
def mailContent(Employee e)'''
  안녕하세요 «e.fullName» 사우님,
  현재 사내 인트라넷에 전화번호가 등록되어 있지 않으니, 빠른 시일내에 등록 부탁드립니다.
  감사합니다.
'''

[편집] 클로져

List<Employee>로 사원들의 목록이 공급된다고 가정하자.

우리 문제를 해결하려면 우선 메일은 등록되어 있지만, 전화번호는 등록되어 있지 않은 사원들의 목록을 먼저 얻어야 한다.

이는 Xtend에서 다음과 같이 간단하게 해결 가능하다:

var List<Employee> employees = ...
 
// 메일은 지정되어 있지만 전화번호가 등록되어 있지 않은 사원 목록
var filteredList = employees.filter[mail != null && phoneNumber == null]

이는 자바식으로 하자면 다음과 같은 모양이 된다:

List<Employee> filteredList = EmployeeListUtil.filter(employees, new EmployeeSelector(){
  public boolean select(Employee it){
    return it.getMail() == null && it.getPhoneNumber() != null;
  }
});

위는 Xtend가 어떻게 돌아가느냐에 대한 이해를 돕기위한 소스로 정확히 저렇게 번역되어 작동하지는 않는다. 정확한 전체 내용이 궁금하다면, Xtend 문서의 클로져 절을 참고할 수 있다.

위의 자바코드를 직접 작성하려면, EmployeeSelector 라는 인터페이스를 따로 선언해 둬야 할 뿐만 아니라, EmployeeListUtil 같은 것도 따로 만들어 둬야 한다.

Xtend에는 이렇게 보편적으로 사용되는 디자인 패턴에 해당되는 요소들이 xtend 라이브러리를 통해 제공되기 때문에, 그런 수고를 덜어준다.

일반적으로 디자인 패턴을 위한 인프라는 모델마다 따로 만들어서 공급되야 한다. 예를 들어 비지터 패턴은 모델 쪽이 accept(visitor)를 가지고, 비지터 인터페이스와 모델은 서로의 타입을 알아야 하기 때문에, Java에서는 패턴 인프라 자체를 재사용할 수 없다.

그러나 Xtend에서는 타입 전환이 자유로운 클로져(Anonymous Function)가 존재하기 때문에, 디자인 패턴의 재사용을 가능케 하고, 여러분은 이미 공급되는 패턴 객체들을 아무 모델에나 적용해 사용할 수 있게 된다.

자 이제 메일을 보내는 일만 남았다. 메일을 보내는 함수인 sendMail(String emailAddress, String content)가 있다고 가정한다:

var List<Employee> employees = ...
 
// 메일은 지정되어 있지만 전화번호가 등록되어 있지 않은 사원 목록
var filteredList = employees.filter[mail != null && phoneNumber == null]
 
// 일치하는 목록의 모든 사원들에게 메일을 보낸다.
filteredList.forEach[sendMail(it.mail, it.mailContent)]

원래 List<T>는 filterforEach 같은 함수가 없지만, 우리는 앞서 언급한 인터 타입 확장을 이용하면 얼마든지 List<T>에 함수를 추가할 수 있다는 사실을 배웠다. 그리고 이 함수는 Xtend에서 기본 공급되며, IterableExtensions 클래스에 의해 공급된다.

좀 극단적으로 쓰면 다음과 같이도 쓸 수 있다:

employees.filter[
  mail != null && phoneNumber == null
].forEach[
  sendMail(it.mail, it.mailContent)
]

인터 타입 선언과 클로져 덕택에, 극적인 가독성을 지닌 짧은 코드만으로 쓰임새 전체를 한 파일 안에 전부 기술 할 수 있다. 게다가 이 쓰임새에 의해 영향 받는 외부 컴포넌트는 전혀 없다.

Java 만으로 같은 일을 하려면, 가독성을 해지는 수많은 관행적인 루프문이나 계산 코드, 헬퍼 클래스들이 연합했어야 했을 것이다.

[편집] 빌더 함수

모델을 다룰 때 객체를 생성하는 일은 보통 두단계로 나뉘어진다.

  1. 객체를 생성한다.
  2. 기존모델과 새로 생성된 관계나 속성들을 정의한다.

그러나 이들은 쓰임새 관점의 개념으로는 보통 한 동작이다. 예를 들면: A 노드에 새로운 자식 B노드 추가. (새 자식 노드 추가)

이번에는 다음과 같은 모델을 가정하자:

자바 코드를 이용하여 이런 모델을 이용해 트리를 구성하는 것은 매우 성가시고 읽기 힘들다:

Person father = ...
 
// 객체의 생성
Person son = new Person();
 
// 객체의 초기화 및 관계 구성
son.setName("김정은");
father.getChildren().add(son);
 
Person son2 = new Person()
son2.setName("김정남");
father.getChildren().add(son2);
...

위의 예는 간단하지만, 모델을 구성하고 빌드하는 코드는 대게 가독성을 유지하는 것이 매우 어렵다. 클로져를 활용하면 이를 좀더 쉽게 만들 수 있다:

def newPerson((Person)=>void initializer){
  var p = new Person()
  initializer.apply(p)
}

위와 같은 간단한 생성함수를 선언하면 다음과 같이 사용할 수 있다:

var father = newPerson[
  name = "김일성"
  children += newPerson[
    name = "김정일"
    children += newPerson[name = "김정은"]
    children += newPerson[name = "김정남"]
  ]
];

필자가 삼대의 이름을 아는경우가 별로 없어 예로 들었을 뿐, 북한 체제의 찬양에는 일말의 관심도 없음을 이해해 주기 바란다.

[편집] With 연산자

[편집] 연산자 재 정의

지금까지 잘 따라온 독자라면 += 가 신경 쓰일텐데, Xtend에서는 연산자 오버로딩이 가능하기 때문에 이런일이 가능하다. 모든 Iterable이나 배열은 += 로 엘리먼트를 추가할 수 있다.

연산자 재정의 역시 가독성을 높혀주는 훌륭한 방법이며, C/C++과 달리 모델간의 연산 방법을 원하는 영역내에 한정 지을 수 있기 때문에, 좋은 영역 모듈화 도구이다.

예를 들어 다음과 같은 복소수를 위한 데이터 모델이 존재한다고 가정하자:

복소수 끼리 덧셈을 행하는 것이 필요한 쓰임새를 요구 받았을 때, 그를 담당하는 유틸리티를 만들거나, 모델을 수정해야 한다:

// 복소수
public class Complex{
  private double real;
  private double imaginary;
  ..
 
  // 이 메서드는 쓰임새에 의해 모델이 오염된 경우이다.
  public Complex add(Complex other){
    Complex result = new Complex();
    result.real = this.real + other.real;
    result.imaginary = this.imaginary + other.imaginary;
    return result;
  }
}

Xtend에는 정해진 시그내쳐와 일치하는 함수를 선언하여 연산자 동작을 정의 할 수 있다.

def operator_plus(Complex a, Complex b){
  var result = new Complex()
  result.real = a.real + b.real
  result.imaginary = a.imaginary + b.imaginary
  return result
}

그리고 이후 영역내에서 이렇게 사용할 수 있다:

var sum = new Complex(1, 1) + new Complex(2, 2)

이런 접근법은 원래의 모델인 Complex를 오염시키지도 않을 뿐더러, 쓰임새의 관점에 더 적합한 언어로 변한 것 처럼 보이기까지 한다!

[편집] 결론

앞서 나열한 특징들 이외에도 Xtend는 특정 쓰임새를 한 군데에서 읽기 쉽게 기술할 수 있게 하는 다양한 응용기술을 포함한다. 앞서 설명한 특징들이 응용된 형태들이므로, 이정도 설명으로도 충분히 Xtend가 영역지향 접근법에 상당한 장점을 가지고 있다는 사실을 이해할 수 있다고 생각한다.

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

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