[번역 : AOSA Volume 1, 23장] 비스트레일(VisTrails)

이 내용은 AOSA(The Architecture of Open Source Applications) Volume 1의 23장을 번역한 내용입니다. 참고로, 오역이 상당히 많으니 원문을 꼭 참고해서 보시기를 강추합니다.

비스트레일(VisTrails)은 데이터 탐색(exploration)과 시각화를 지원하는 오픈 소스 시스템이다. 비스트레일은 과학 워크플로우 및 시각화 시스템의 유용한 기능을 포함하고 있고, 많이 확장하고 있다. 케플러(Kepler, https://kepler-project.org)나 타베르나(Taverna, http://www.taverna.org.uk)와 같은 과학 워크플로우 시스템과 마찬가지로, 비스트레일도 일련의 규칙에 따라 기존 애플리케이션, 느슨하게 결합(loosely-coupled)한 리소스 그리고 라이브러리를 통합하는 전산 처리(computational processes)을 가능하게 한다. AVS와 ParaView와 같은 시각화 시스템과 마찬가지로, 데이터를 다양한 시각적 표현으로 탐색하고 비교하게 해서, 사용자가 이용할 수 있는 진보된 과학과 정보 시각화 기술을 지원한다. 결과적으로, 사용자는 데이터 수집과 조작에서 복잡한 분석과 시각화까지, 과학 발견(scientific discovery)의 중요한 단계를 포함하는 복잡한 워크플로우를 만들 수 있고, 전부 한 시스템으로 통합했다.

비스트레일의 특징은 그 자체가 이력(provenance) 인프라라는 것이다. 비스트레일은 탐색(exploratory) 작업 중에 따라오는 단계와 만들어진 데이터의 자세한 기록을 수집(capture)하고 유지한다. 전통적으로, 워크플로우는 반복적인 작업을 자동화하는 데 사용했지만, 현실적으로 애플리케이션에서의 작업은 탐색으로, 데이터 분석과 시각화와 같이, 거의 반복되지 않는다—기준이 바뀌고 있다. 사용자가 자신의 데이터에 대한 가설을 만들고 입증하기 위해, 다양하지만 연관 워크플로우를 반복적으로 조정하면서 만들어 간다.

비스트레일은 빠르게 변하는 워크플로우를 관리하기 위해 설계했다: 제품(예로, visualizations, plots)이 만들어 낸 워크플로우 및 실행의 이력을 유지한다. 또한, 어노테이션(annotation) 기능을 제공해서, 사용자는 자동으로 수집한(automatically-captured) 이력의 질을 높일 수 있다.

게다가, 결과를 재현할 수 있는 비스트레일은 사용자에게 협력적 데이터 분석을 도와주는 일련의 기능과 직관적인 유저 인터페이스로 이력 정보를 강화한다. 특히, 비스트레일은 임시 결과를 저장해서 반영적 유추(reflective reasoning)를 지원하고, 사용자에게 결과를 이끌어내거나 실행취소(backward)와 재실행(forward) 이유를 연속으로 따라오게 하는 동작을 검토하게 한다. 사용자는 직관적으로 워크플로우 버전을 탐색할 수 있고, 실행취소(undo)는 결과에 손실 없이 변하고, 여러 워크플로우를 시각적으로 비교하고 그 결과를 시각화한 스프레드시트에 나란히 보여준다.

비스트레일은 워크플로우 및 시각화 시스템의 폭넓은 채택을 방해하던 중요한 사용성 문제를 해결한다. 더 폭넓은 사용자에게 제공하기 위해, 프로그래밍 지식이 없는 사람도 포함해서, 일련의 기능, 워크플로우 설계 및 사용을 간단화한 유저 인터페이스를 제공한다[FSC 06]. 그리고 유추해서 워크플로우를 만들고 개선하는 능력을 포함해서(예로, 워크플로우 질의하기), 사용자가 추천 시스템[SVK+07]을 사용해서 상호작용해서 워크플로우를 만들어, 워크플로우 완성을 제안하는 것도 포함한다. 또한, 최종 사용자(비전문가)에게 배포할 수 있는 사용자 정의 애플리케이션을 쉽게 만들 수 있는 새로운 프레임워크를 개발했다.

비스트레일의 확장성은 새로운 기능을 빠르게 프로토타이핑하는 것에 더불어, 툴과 라이브러리 통합을 단순하게 하는 인프라의 결과이다. 이것은 환경 과학, 정신 의학, 천문학, 우주론(학), 고에너지 물리학, 양자 물리학과 분자 모델링 등을 포함한 광범위한 애플리케이션 영역에서, 비스트레일을 사용할 수 있게 도와준다.

비스트레일을 오픈소스 및 무료로 유지하기 위해, 오직 무료와 오픈소스 패키지만을 사용해서 빌드했다. 비스트레일은 파이썬으로 개발했고 GUI 툴킷(PyQt 파이썬 바인딩으로)으로 Ot를 사용한다. 사용자와 애플리케이션이 광범위하므로, 이식성(portability)을 염두에 두고 처음부터 다시 시스템을 설계했다. 비스트레일은 윈도, 맥 그리고 리눅스에서 동작한다.

그림 23.1:비스트레일 UI의 컴포넌트

23.1. 시스템 개요

원래, 데이터 탐색은 사용자가 연관 데이터를 알아내고, 데이터를 통합하고 시각화하고, 다양한 솔루션을 탐색하는 동안 동료와 협력하기 위해서 그리고 결과를 배포하는 데 필요한 창조적인 과정이다. 데이터의 크기와 분석의 복잡성을 고려하면, 과학적 탐색이 일반적이고, 더 나은 창조성을 지원하는 툴이 필요했다.

이런 툴을 위해서 두 가지의 기본 조건이 있고, 이것은 서로 관련이 있다. 첫째, 이상적이고 실행할 수 있는 정규 표현(formal descriptions)을 사용해서 탐색 과정을 지정할 수 있는 것이 중요하다. 둘째, 이런 프로세스의 결과와 더불어, 문제를 해결하기 위해 따라오는 다양한 단계에 대한 유추를 재현하기 위해, 이런 툴은 체계적으로 이력을 수집하는 기능이 있어야 한다. 비스트레일은 이런 조건을 염두에 두고 설계했다.

23.1.1. 워크플로우와 워크플로우 기반 시스템

워크플로우 시스템은 여러 툴과 결합한 파이프라인(워크플로우) 생성을 지원한다. 이 시스템들은 반복적인 작업과 결과 재현의 자동화를 가능하게 한다. 워크플로우는 상업용(예로, 애플 맥 OS X의 Automator 와 야후! Pipes)과 학술용(예로, NiPype, 케플러(Kepler)와 타베르나(Taverna))을 포함해서, 몇 개의 워크플로우 기반 애플리케이션이 입증했듯이, 다양한 작업에서 원시 셸 스크립트를 빠르게 바꿔나가고 있다.

워크플로우는 고 수준 언어로 개발한 스크립트나 프로그램과 비교해서 몇 가지 장점을 가지고 있다. 연속적인 작업의 경우, 한 작업의 출력이 다른 작업의 입력으로 연결해 이어지는 단순한 프로그래밍 모델을 제공한다. 그림 23.1은 기상 관측 데이터를 포함하고 있고 데이터의 산포도(scatter plot)를 생성한 CSV 파일을 읽는 워크플로우를 보여준다.

이 단순한 프로그래밍 모델은 프로그래밍 지식이 없는 많은 사용자에게 더 적합하고, 직관적인 비주얼 프로그래밍 인터페이스를 제공하기 위한 워크플로우 시스템을 가능하게 한다. 또한, 워크플로우는 명시적인 구조로 되어 있다: 노드는 매개변수와 같이 프로세스(또는 모듈)를 나타내고, 가장자리는 프로세스 사이의 데이터 흐름을 수집하는 것을 그래프로 볼 수 있다. 그림 23.1의 예에서, 모듈 CSVReader는 매개 변수로 파일이름 (/weather/temp_precip.dat)을 받고, 파일을 읽고, 내용을 차례대로 기온과 강우량 값의 산포도(scatter plot)를 만드는 matplotlib 기능에 보내는 GetTemperature와 GetPrecipitation 모듈에 보낸다.

대부분의 워크플로우 시스템은 특정 애플리케이션 영역을 위해 설계했다. 예로, 타베르나(Taverna)는 생물 정보학(bioinformatics) 워크플로우가 대상이고, NiPype는 뇌 영상(neuroimaging) 워크플로우를 만들게 한다. 비스트레일은 다른 워크플로우 시스템이 제공하는 대부분 기능을 지원하는 동시에, 여러 툴, 라이브러리 및 서비스 통합으로, 다양한 분야의 영역에서 일반적인 탐색 작업을 지원하게 설계했다.

23.1.2. 데이터와 워크플로우 이력

결과(와 데이터 제품)에 대한 이력 정보 유지의 중요성은 과학계에서 잘 인지하고 있다. 데이터 제품의 이력(또한, 감사 추적, 혈통 그리고 족보라고 알려짐)은 데이터 제품이 만들어낸 프로세스와 데이터에 대한 정보를 포함한다. 이력은 데이터의 질과 저작권을 결정하고 결과의 재현과 더불어 검증하기 위해, 데이터를 보존하는 핵심으로 중요한 문서를 제공한다[FKSS08].

이력의 중요한 컴포넌트는 인과관계에 대한 정보이다. 예를 들면, 데이터 제품을 만드는 입력 데이터, 매개변수와 함께 프로세스(단계 순서대로)의 설명이 있다. 따라서 이력 구조는 특정 결과 셋(result set)을 얻는 데 사용한 워크플로우(또는 워크플로우 셋)의 구조를 반영한다.

사실, 과학계에서 워크플로우 시스템의 광범위한 사용을 위한 촉매는 자동으로 수집한 이력을 쉽게 사용할 수 있다는 것이었다. 초기 워크플로우 시스템은 이력을 수집하기 위해 확장(extends)했지만, 비스트레일은 이력을 지원(support)하도록 설계했다.

그림 23.2: 어노테이션으로 향상된 탐색 이력

23.1.3. 유저 인터페이스와 기본 기능

시스템의 다양한 유저 인터페이스 컴포넌트는 그림 23.1과 그림 23.2에서 볼 수 있다. 사용자는 워크플로우 편집기로 워크플로우를 만들고 편집한다. 워크플로우 그래프를 빌드하기 위해, 사용자는 모듈 레지스트리(Module Registry)에서 모듈을 드래그해서 워크플로우 편집기 캔버스에 드랍할 수 있다. 모듈을 선택하면, 사용자가 모듈의 값을 설정하고 변경할 수 있는 매개 변수(매개변수 편집 부분에서)를 보여준다.

다시 정의한 워크플로우 스펙에 따라, 시스템은 아래에서 설명하고 있는 버전 트리 뷰(Version Tree View)에서 변경을 수집해서 사용자에게 이력을 제공한다. 사용자는 비스트레일 스프레드시트에서 워크플로우 그리고 결과와 상호 작용할 수 있다. 스프레드시트의 각 셀은 워크플로우 인스턴스(instance)에 해당하는 뷰를 나타낸다. 그림 23.1에서, 워크플로우 편집기에 보이는 워크플로우의 결과는 스프레드시트의 왼쪽 위 셀에 표시된다. 사용자는 직접 스프레드시트에서 다른 셀에서 매개별수를 동기화할 수 있는 것에 더불어, 워크플로우의 매개변수를 수정할 수 있다.

버전 트리 뷰는 사용자가 서로 다른 워크플로우 버전을 탐색하게 도와준다. 그림 23.2에서 보듯이, 버전 트리에서 노드를 클릭하면, 사용자는 워크플로우, 워크플로우와 연관된 결과(미리보기 화면) 그리고 메타데이터를 볼 수 있다. 메타데이터 일부는 자동으로 수집된다. 예를 들면, 특정 워크플로우를 생성한 사용자의 아이디와 생성 날짜가 있지만, 또한, 사용자가 워크플로우 및 쓰여진 설명을 식별하기 위한 태그를 포함해서 부가적인 메타데이터를 제공할 수 있다.

그림 23.3: 비스트레일 아키텍처

23.2. 프로젝트 연혁

비스트레일 초기 버전은 자바와 C++로 개발했다[BCC+05]. C + + 버전은 시스템을 위해 우리의 요구사항을 갖추는 데 중요한 역할인 피드백을 하는 몇몇 얼리 어댑터에게 배포했다.

여러 과학 커뮤니티에서 파이썬 기반 라이브러리와 툴 숫자가 증가 추세여서, 기본으로 파이썬을 사용하기로 선택했다. 파이썬은 빠르게 과학 소프트웨어를 위해서 범용의 현대적으로 잘 어울리는 언어가 돼가고 있다. 포트란(Fortran), C 그리고 C++과 같은 다른 언어로 개발한 많은 라이브러리는 스크립트 기능을 제공하는 방법으로 파이썬 바인딩을 사용한다. 비스트레일이 워크플로우에서 쉽게 다양한 소프트웨어 라이브러리의 통합을 목표로 하기에, 순수 파이썬 구현이 더 쉬워진다. 특별히, 파이썬은 LISP 환경에서 볼 수 있던 것과 비슷하게 동적 코드 로딩 기능이 있고, 동시에 훨씬 큰 개발자 커뮤니티와 매우 풍부한 표준 라이브러리를 가지고 있다. 2005년 후반, 파이썬/PyQt/Qt를 사용해서 현재 시스템의 개발을 시작했다. 이 선택은 특히 시스템 확장, 새로운 모듈과 패키지의 추가를 단순화했다.

비스트레일의 첫 베타 버전은 2007년 1월에 출시됐다. 이후, 25,000번 넘게 다운로드가 됐다.

23.3. 비스트레일 내부

그림 23.3에서 보듯이, 위에서 설명한 유저 인터페이스 기능을 지원하는 내부 컴포넌트는 고수준 아키텍처로 설명하고 있다. 워크플로우 실행은 기능 호출과 해당 매개변수를 추적하고 워크플로우 실행(실행 이력)의 이력을 수집하는 실행 엔진(Execution Engine)이 제어한다. 실행 일부로, 또한 메모리와 디스크 모두에 중간 결과를 캐시할 수 있다. 23.3장에서 살펴보듯이, 단지 모듈과 매개변수의 새로운 조합으로 다시 실행하고, 이것은 라이브러리(matplotlib)에서 적합한 함수를 호출해서 실행한다. 이력에 연결한 워크플로우 결과는, 전자 문서(23.4장)에 포함될 수 있다.

워크플로우 변경에 대한 정보는 로컬 디렉터리에 저장한 XML 파일과 관계형 데이터베이스를 포함한, 다양한 스토리지 백엔드를 사용해서 영속시킬 수 있는 버전 트리에서 수집한다. 또한, 비스트레일은 사용자가 이력 정보를 검색할 수 있게, 질의 엔진을 제공한다.

비록 비스트레일을 상호작용 툴(interactive tool)로 설계했지만, 서버 모드로 사용할 수 있다는 것을 주목한다. 워크플로우가 만들어지면, 비스트레일 서버가 워크플로우를 실행할 수 있다. 이 기능은 사용자에게 워크플로우와 상호작용하고 고성능 컴퓨팅 환경에서 워크플로우를 실행할 수 있게 하는 웹 기반 인터페이스 생성을 포함해서, 여러 시나리오에서 유용하다.

23.3.1. 버전 트리: 변경 기반 이력

그림 23.3: 비스트레일 아키텍처

비스트레일에서 도입한 새로운 개념은 워크플로우 변화[FSC+06] 이력의 개념이다. 단지 데이터 제품이 만들어낸 이력만 유지하는 이전 워크플로우와 워크플로우 기반 시각화 시스템과 대조해서, 비스트레일은 데이터 항목과 수집한 이력을 값 형식의 클래스(first-class)로 워크플로우를 다룬다. 워크플로우 변화 이력의 이용 가능성은 반성적 유추(reflective reasoning)를 지원한다. 사용자는 일부 결과의 손실 없이 여러 유추를 탐색할 수 있고, 시스템이 중간 결과를 저장하기에, 사용자는 저장된 정보로 이유와 추론을 할 수 있다. 또한, 탐색 프로세스를 단순화한 일련의 동작을 가능하게 한다. 예로, 사용자는 특정 작업을 위해 만든 워크플로우 공간을 탐색(navigate)하고, 워크플로우와 그 결과(그림 23.4 참조)를 시각적으로 비교하고 (큰)매개변수 공간의 탐색을 쉽게 할 수 있다. 게다가, 사용자는 이력 정보를 질의하고 예제로 배울 수 있다.

워크플로우 변경은 변경 기반 이력 모델을 사용해서 수집한다. 그림 23.4에서 보듯이, 데이터베이스 트랜잭션 로그와 비슷하게, 워크플로우(예로, 모듈 추가, 매개변수 수정 등)에 적용한 동작과 변화를 저장한다. 이 정보는 트리로 모델화하고, 트리의 각 노드는 워크플로우 버전에 해당하고, 부모와 자식 노드 사이의 엣지는 자식 노드를 얻기 위해 부모 노드에 적용한 변화를 나타낸다. 이 트리를 언급하기 위해 버전 트리(version tree)와 비스트레일(vistrail, visual trail의 약자)용어를 같은 의미로 사용한다. 변경 기반 모델이 일률적으로 매개변수 값과 워크플로우 정의 변경 모두를 수집한다는 것에 주의해라. 이 변화의 순서는 데이터 제품의 이력을 알아내기에 충분하고, 또한 시간이 흐르면서 어떻게 워크플로우가 변해가는지에 대한 정보를 수집한다. 모델은 단순하고 간편하다—워크플로우의 여러 버전을 저장하는 안보다 매우 적은 공간을 사용한다.

변경 기반 이력 모델은 많은 이점을 가지고 있다. 그림 23.4는 비스트레일이 두 워크플로우를 비교하기 위해 제공하는 시각적 차이 기능을 보여준다. 워크플로우는 그래프로 나타내지만, 변경 기반 모델을 사용해서, 두 개의 워크플로우 비교하는 것은 매우 간단하다: 그것은 버전 트리를 탐색하고 한 워크플로우에서 다른 워크플로우로 변환하는 데 필요한 일련의 동작을 식별하는데 충분하다.

버전 트리의 기본으로, 변경 기반 이력 모델의 또 다른 중요한 이점은 협업을 지원하는 방법으로 동작할 수 있다. 워크플로우 설계는 매우 어려운 작업이기에, 종종 여러 사용자의 협업이 필요하다. 버전 트리는 다양한 사용자(예로, 해당 워크플로우를 만든 사용자에 따라 노드 색칠하기)의 기여를 시각화하는 직관적인 방법을 제공하는 것과 더불어, 모델의 단조성(monotonicity)은 여러 사용자가 수행한 변화의 동기화를 위한 간단한 알고리즘을 가능하게 한다.

워크플로우가 실행하는 동안, 이력 정보를 쉽게 수집할 수 있다. 실행을 완료하면, 또한 데이터 제품과 그 이력의 밀접한 연결을 유지하는 것이 중요하다. 예를 들면, 데이터 제품을 만들어내는 데 사용한 워크플로우, 매개변수 그리고 입력 파일이 있다. 데이터 파일이나 이력을 이동하거나 수정할 때, 이력과 연관된 데이터나 데이터와 연관된 이력을 찾기가 어려울 수 있다. 비스트레일은 입력, 중간 결과 그리고 출력 데이터 파일을 관리하는 영속적인 저장 방법을 제공해서, 이력과 데이터 사이의 연결을 강화한다. 이 방법은 이력 정보가 데이터의 출처를 보장해서 쉽게(정확하게) 찾을 수 있기 때문에, 더 나은 재현성을 제공한다. 이런 관리의 또 다른 중요한 이점은 다른 사용자와 공유할 수 있는 중간 데이터의 캐시를 가능하게 한다는 것이다.

23.3.2. 워크플로우 실행과 캐싱

비스트레일 실행 엔진은 신규 및 기존 툴과 라이브러리의 통합이 가능하게 설계했다. 과학적 시각화와 전산 소프트웨어(computation software) 써드파티(third-party) 래핑에 사용하는 다양한 스타일에 대응하려고 노력했다. 특히, 비스트레일은 셸에서 실행하고, 입/출력으로 파일을 사용하는 프리컴파일(pre-compiled)된 바이너리로 존재하거나 입/출력으로 내부 객체를 전달하는 C++/자바/파이썬 클래스 라이브러리 중의 하나로 존재하는 애플리케이션 라이브러리와 함께 통합할 수 있다.

비스트레일은 각 모듈이 연산을 수행하고 모듈이 만들어낸 데이터는 모듈끼리의 연결로 전달하는 데이터플로우(dataflow) 실행 모델을 적용하고 있다. 모듈은 상향식(bottom-up)으로 실행한다; 각 입력은 반복적으로(recursively) 실행하는 업스트림(upstream) 모듈의 요청으로 만들어진다(A에서 B로 가는 순서의 연결이 있을 때, 모듈 A는 B의 업스트림이라고 한다). 중간 데이터는 메모리(파이썬 객체로)나 디스크(데이터에 연결하는 정보를 가지고 있는 파이썬 객체로 래핑해서)에 임시로 저장한다.

사용자가 비스트레일에 자신만의 기능을 추가할 수 있도록, 확장할 수 있는 패키지 시스템(23.3장을 참조)을 구축했다. 패키지는 사용자가 비스트레일 워크플로우에 자신 또는 써드파티 모듈을 포함할 수 있게 한다. 패키지 개발자는 일련의 연산 모듈(computational modules)을 확인해야 하고, 각 모듈은 입력과 출력 포트 확인과 더불어 연산을 정의한다. 기존 라이브러리에서, 연산 메소드는 기존 기능에 대한 입력 포트를 매개변수로 바꾸고, 결과 값을 출력 포트로 매핑하도록 명시하는 것이 필요하다.

탐색 작업에서, 공통의 하부구조(sub-structures)를 공유하는 비슷한 워크플로우는, 종종 밀접하게 연속으로 실행한다. 워크플로우 실행 효율을 개선하기 위해, 비스트레일은 재연산을 더하기 위해 중간값을 캐시 한다. 이전 실행 결과를 재사용하기 때문에, 암묵적으로 캐시할 수 있는 모듈이 정상 동작한다고 가정한다: 같은 입력이 주어지면, 모듈은 같은 결과를 만들 것이다. 이 요구사항은 분명히 클래스 동작을 제약하지만, 합리적이다.

그러나 캐시가 쓸모없는 명백한 상황이 있다. 예를 들면, 파일을 원격 서버에 업로드 하거나 디스크에 저장하는 모듈은 결과가 상대적으로 중요하지 않으며, 상당한 부작용이 있다. 그 밖의 모듈은 무작위로 사용할 수 있고, 선택하지 않는 것(non-determinism)이 바람직할 수 있다: 이런 모듈은 캐시 비활성화 플래그를 설정할 수 있다. 그러나 일부 모듈에서 동작이 바뀔 수 있다는 것은 자연스럽지 않다: 두 개의 파일에 데이터를 기록하는 기능은 파일의 내용을 출력으로 래핑할 수도 있다.

23.3.3. 데이터 직렬화와 저장

이력을 지원하는 시스템의 핵심 컴포넌트 중의 하나가 데이터의 직렬화와 저장이다. 원래 비스트레일은 내부 객체(예, 버전 트리, 각 모듈)가 포함하고 있는 단순한 fromXML 과 toXML 메서드로 데이터를 XML로 저장했다. 내부 객체의 스키마 변화를 지원하기 위해, 이 기능은 또한 스키마 버전 사이의 변화를 인코드했다. 프로젝트가 진행됨에 따라, 사용자 기반은 성장했고, 관계형 저장을 포함해서, 다양한 직렬화를 지원하기로 했다. 게다가, 스키마 객체가 변화함에 따라, 스키마 버전 관리, 버전 간의 변환, 그리고 엔티티 관계 지원과 같은 공통 데이터 관리와 관련해서 더 좋은 인프라를 유지하는 것이 필요했다. 그렇게 하려고, 새로운 데이터베이스(DB) 계층(layer)을 추가했다.

디비 계층은 3가지 핵심 컴포넌트로 구성되어 있다: 도메인 객체, 서비스 로직 그리고 퍼시스턴스(persistence) 메서드. 도메인과 퍼시스턴스 컴포넌트는 버전을 관리해서, 각 스키마 버전은 버전 별 클래스 셋을 가지고 있다. 이 방법으로, 각 스키마 버전을 읽는 코드를 유지한다. 또한, 클래스는 한 스키마 버전에서 다른 버전으로 객체에 대한 변화를 정의한다. 서비스 클래스는 인터페이스를 위한 메서드를 제공한다. 서비스 클래스는 데이터와 인터페이스하는 메서드를 제공하고, 스키마 버전의 감지와 변환을 처리한다.

코드 작성의 상당 부분은 지루하고 반복적이기에, 객체 레이아웃(임의 메모리 인덱스)과 직렬화 코드 모두 정의하는 템플릿과 메타 스키마(meta-schema)를 사용한다. 메타 스키마는 XML로 작성하고, 기본 XML과 비스트레일이 추가할 수 있다고 정의한 관계형 매핑외에, 직렬화의 경우에 확장할 수 있다. 이것은 하이버네이트(Hibernate)나 SQLObject와 같은 객체-관계 매핑 프레임웍과 비슷하지만, 한 스키마 버전에서 다음 버전으로 재 매핑(re-mapping) 식별자와 변환 객체와 같은 작업을 자동화하는 일부의 특별한 루틴을 추가한다. 게다가, 많은 언어에 대한 직렬화 코드를 생성하기 위해 같은 메타 스키마를 사용할 수 있다. 원래 메타-파이썬(meta-Python)을 작성한 후에, 메타 스키마에서 얻은 변수로 파이썬 코드를 실행해서 생성한 도메인 및 퍼시스턴스 코드는, 최근 마코 템플릿(Mako templates)으로 마이그레이션 했다.

자동 변환은 자신의 데이터를 새로운 버전의 시스템으로 마이그레이션해야 하는 사용자를 위한 핵심이다. 우리의 설계는 개발자에게 조금 덜 힘들게 변환하도록 후크(개발자들을 같이 이끌어가는 수단)를 추가했다. 각 버전 코드의 복사본을 유지하기 때문에, 변환 코드는 단지 한 버전을 다른 버전으로 매핑하는 것이 필요하다. 루트 수준에서, 어느 버전이 다른 버전으로 변환되는 방법을 확인하기 위해 맵을 정의한다. 일반적으로, 멀리 떨어져 있는 버전에 대해서는, 여러 중간 버전을 통해 이어져서 수반한다. 처음에는, 다음 버전만 지원하는 맵이었다, 즉 새 버전은 이전 버전으로 변환할 수 없었지만, 리버스 매핑(reverse mappings)이 최근 스키마 매핑에 추가되었다.

각 객체는 객체의 다양한 버전을 가져오고 현재 버전을 반환하는 update_version 메서드를 가지고 있다. 기본적으로, 이 메서드는 각 객체가 예전 객체의 매핑 필드를 새로운 버전의 매핑 필드에 갱신하는 재귀 변환을 한다. 이 매핑은 기본으로, 각 필드는 같은 이름의 필드에 복사하지만, 특정 필드의 기본 행위를 “오버라이드(override)”하는 메서드를 정의할 수 있다. 오버라이드는 기존 객체를 가져오고 새로운 버전을 반환하는 메서드이다. 대부분의 스키마 변경은 단지 적은 필드에 영향을 주기 때문에, 기본 매핑이 대부분은 해결하지만, 오버라이드는 로컬 변경을 정의하는 유연한 방법을 제공한다.

23.3.4. 패키지와 파이썬을 통한 확장성

비스트레일의 첫 프로토타입은 고정 셋 모듈을 가지고 있었다. 고정 셋 모듈은 비스트레일의 버전 트리와 다중 실행 캐싱에 대한 기본 아이디어를 개발하기 위한 이상적인 환경이었지만, 심각하게 장기적인 유용성을 제한했다.

전산 과학(computational science)에 대한 인프라로 비스트레일을 보고 있고, 그리고 그것은, 문자 그대로, 시스템이 개발될 다른 툴과 프로세스에 대한 스캐폴딩(scaffolding, 발판)을 제공해야 한다. 이 시나리오의 필수 조건은 확장성이다. 확장성을 달성하는 일반적인 방법은 대상 언어의 정의와 적당한 인터프리터 작성과 연관이 있다. 이것은 실행 내내 정교한 제어를 할 수 있기에 매력적이다. 이 관심은 캐싱 요구에 고려돼서 극대화되었다. 그러나 완전한 프로그래밍 언어를 구현하는 것은 우리의 주된 목표에 없는 큰 시도이다. 더 중요하게도, 단지 비스트레일을 사용하기 위해 시도하는 사용자에게 전적으로 새로운 언어를 배우도록 강요하는 것은 불가능하다.

우리는 사용자가 자신의 기능 추가가 쉬운 시스템을 원했다. 동시에, 소프트웨어의 상당히 복잡한 부분을 표현하는데 충분히 강력한 시스템을 원했다. 예를 들어, 비스트레일은 VTK 시각화 라이브러리를 지원한다. VTK는 컴파일, 설정 및 운영 체제에 따라, 약 1,000개의 클래스가 있다. 모든 경우를 위해 다양한 코드 패스를 작성하는 것이 역효과를 내고 결국에는 가망이 없어 보였기 때문에, 임의 패키지가 제공하는 비스트레일 모듈의 셋을 동적으로 결정하는 것이 필요하다고 결정했고, 자연스럽게 VTK는 복잡한 패키지에 대한 대상 모델이 되었다.
전산 과학은 원래 대상으로 한 영역중의 하나이고, 그 즈음해서 시스템을 설계했고, 파이썬은 과학자들 사이에서 “글루 코드(glue code, http://en.wikipedia.org/wiki/Glue_code)”로 유명해 졌다. 파이썬 자체를 사용해서 사용자 정의 비스트레일 모듈의 행동을 지정해서, 적용에 대한 큰 장벽을 거의 제거할 것이다. 알고 보니, 파이썬은 동적으로 정의한 클래스와 리플렉션을 위한 좋은 인프라를 제공한다. 파이썬의 거의 모든 정의는 값 형식의 클래스(first-class) 표현으로 동등한 형태를 보이고 있다. 패키지 시스템을 위한 파이썬의 두 가지 중요한 리플렉션은 다음과 같다:

• 파이썬 클래스는 callable 타입에 호출하는 함수로 동적으로 정의할 수 있다. 반환 값은 일반적으로 정의한 파이썬 클래스와 정확하게 같은 방법으로 사용할 수 있는 클래스의 표현이다.
• 파이썬 모듈은 __import__ 함수 호출로 불러올 수 있고, 결과 값은 표준 import 문에 식별자와 같은 방법으로 동작한다. 이 모듈의 경로는 런타임에 지정할 수 있다.

물론, 파이썬을 사용해서 가지게 된 단점도 있다. 우선, 파이썬의 동적인 특징은 비스트레일 패키지의 타입 세이프(type safety)와 같은 일부를 보장하고 싶은 경우, 일반적으로 할 수 없다. 더 중요한 것은, 비스트레일 모듈에 대한 요구사항의 일부인, 특히 참조 투명성에 대해서, 파이썬은 강제할 수 없다. 그래도, 파이썬의 문화적 방법(cultural mechanisms)에 주의해서 허용된 구조를 제한하는 것은 의미가 있다고 생각하고, 파이썬은 소프트웨어 확장을 위해서 매우 매력적인 언어이다.

23.3.5. 비스트레일 패키지와 번들

비스트레일 패키지는 일련의 모듈을 캡슐화한다. 디스크에서 패키지의 가장 일반적인 표현은 파이썬 패키지(운이 없다면, 명명 충돌이 있을 수 있다)와 같은 표현이다. 파이썬 패키지는 함수와 클래스 같은 파이썬 값을 정의하는 일련의 파이썬 파일로 구성되어 있다. 비스트레일 패키지는 특정 인터페이스를 따르는 파이썬 패키지이다. 비스트레일 패키지는 특정 함수와 변수를 정의한 파일을 가지고 있다. 가장 단순한 형태는, 비스트레일 패키지가 두 개의 파일인 __init__.py와 init.py를 포함하고 있는 디렉터리 형태이다.

첫 번째 파일 __init__.py는 파이썬 패키지의 필수 조건이고, 몇 가지 정의를 포함해야 하고, 이 정의는 상수여야 한다. 비록 이 상수 정의를 보장하는 방법은 없지만, 비스트레일 패키지가 이것을 따르지 못하면 버그로 간주한다. 파일에서 정의하는 값으로 패키지에 대한 유일한 식별자(globally unique identifier)는 워크플로우를 직렬화할 때 모듈을 구분하기 위해 사용하고, 패키지 버전도 포함한다(패키지 버전은 워크플로우와 패키지 업그레이드를 처리할 때 중요하다, 23.4장 참조). 또한, 이 파일은 package_dependencies와 package_requirements라는 함수를 포함할 수 있다. 비스트레일 모듈은 다른 비스트레일 모듈 옆의 루트 모듈 클래스의 서브클래스(subclass)를 허용하기 때문에, 특정 비스트레일 패키지가 다른 패키지 동작을 확장하는 것이 가능해서, 특정 패키지는 확장한 패키지의 초기화 전에 초기화해야 한다. 이런 패키지간 의존성은package_dependencies가 명시한다. 반면에, package_requirements 함수는 비스트레일이 필요한 시스템 수준의 라이브러리를 명시하고, 경우에 따라, 라이브러리의 번들 추상화를 통해서 자동으로 만족하도록 시도할 수 있다.

비스트레일에서 번들은 레드햇의 RPM이나 우분투의 APT와 같은 특정 시스템 툴로 관리하는 시스템 수준의 패키지이다. 이런 속성이 만족하면, 비스트레일은 직접 파이썬 모듈을 불러와서(importing) 패키지 속성과 적절한 변수 접근을 결정할 수 있다.

두 번째 파일, init.py는 모든 실 비스트레일 모듈 정의에 대한 진입 점을 포함한다. 이 파일의 가장 중요한 기능은 두 함수, initialize와 finalize의 정의이다. Initialize 함수는, 모든 의존 패키지 자신이 활성화된 다음에, 특정 패키지가 활성화될 때 호출된다. 이 함수는 패키지의 모든 모듈에 대해 설치(setup) 작업을 수행한다. 반면에, finalize 함수는 일반적으로 런타임 리소스(예로, 패키지가 만든 임시 파일을 정리할 수 있다)를 해제하는 데 사용한다.

비스트레일 패키지에서 각 모듈은 하나의 파이썬 클래스로 나타낸다. 이 클래스를 비스트레일에 등록하기 위해, 패키지 개발자는 각 비스트레일 모듈에 대해, add_module 함수를 한번 호출한다. 이 비스트레일 모듈은 임의의 파이썬 클래스일 수 있지만, 몇 가지 조건을 준수해야 한다. 조건 중에 첫 번째는, 각 모듈은 아마 평범하게 Module 이라고 정의한 기본 파이썬 클래스를 상속(subclass)해야 한다. 비스트레일 모듈은 다중 상속을 사용할 수 있지만, 오직 한 클래스만이 비스트레일 모듈이어야 하고, 다이아몬드 계층(diamond hierarchies, 다중상속의 구조) 의 모듈 트리는 허용하지 않는다. 다중 상속은 특히 클래스 믹스(mix-ins, 섞는)를 정의하는데 유용하다: 더 복잡한 동작을 만들기 위해 같이 구성할 수 있는 부모 클래스가 단순 동작을 코드화한다.

사용할 수 있는 포트 셋은 비스트레일 모듈의 인터페이스를 결정하고, 그래서 이런 모듈의 표시와 더불어 다른 모듈의 연결에 영향을 준다. 이런 포트는, 다음에, 명시적으로 비스트레일 인프라에 기술해야 한다. 이 작업은 initialize를 호출하는 동안 적절한 add_input_port나 add_output_port를 호출해서, 또는 각 비스트레일 모듈에 클래스별 _input_ports 와 _output_ports 목록을 지정해서 완료할 수 있다.

각 모듈은 compute 메서드를 재정의(overriding)해서 연산을 명시한다. 모듈간의 데이터 전달은 포트를 사용하고, get_input_from_port와 set_result 메서드로 접근한다. 전통적인 데이터플로우 환경에서, 실행 순서는 데이터 요청에 따라 지정된다. 우리의 경우, 실행 순서는 워크플로우 모듈의 위상 정렬(topological sorting) 로 명시한다. 캐싱 알고리즘은 비순환(acyclic) 그래프 가 필요해서, 역 위상 정렬 순서(reverse topological sorted order)로 실행을 예정해서, 이 함수 호출은 업스트림(upstream) 모듈의 실행을 트리거 하지 않는다. 신중하게 이것을 결정했다: 이것은 다른 모듈로부터 별도로 각 모듈의 동작을 고려해서 간단하게 만들고, 캐싱 전략을 단순하고 강력하게 만든다.

위상 정렬 : 보통, 그래프에서 A~D 까지 이동을 해야 하는데, A->B->D나 A->C->D 의 순서로 가야 A에서 D까지 이동을 할 수 있는 경우, A가 D까지 가려면 반드시 B나 C를 거쳐야 갈 수 있는 순서를 가지는 정렬. 즉, 엣지에 방향이 있어서 순환(cycle)이 없음.
비순환 그래프 : 한 노드에서 출발하여 지나간 경로를 다시 거치지 않으면 출발점에 도달할 수 없는 그래프로, Root를 가지고 있는 비순환 그래프가 트리이다.

일반적인 가이드로, 비스트레일 모듈은 compute 메서드를 검증하는 도중에 부작용이 있는 함수를 사용하지 말아야 한다. 23.3장에서 살펴봤듯이, 이 요구사항은 부분 워크플로우 캐싱을 가능하게 한다: 모듈이 이 속성이 반영했다면, 모듈의 동작은 업스트림 모듈의 출력 기능이다. 다음에, 모든 비순환 서브그래프는 다시 한번 연산해야 하고, 결과를 재사용할 수 있다.

23.3.6. 모듈에 데이터 전달하기

모듈과 모듈간 통신의 독특한 특징 중 하나가 모듈간에 전달하는 데이터 자체가 비스트레일 모듈이라는 것이다. 비스트레일에서, 모듈과 데이터 클래스는 단일 계층이다. 예를 들어, 모듈은 연산의 출력으로 자신을 제공할 수 있다(실제로, 모든 모듈은 기본적으로 “자신” 출력 포트를 제공한다). 주요 단점은, 종종 데이터플로우 기반(dataflow-based) 아키텍처에서 볼 수 있는, 연산과 데이터 간의 개념적 분리가 손실된다는 것이다. 그러나 두 가지 큰 장점이 있다. 첫 번째는 자바나 C++의 객체 타입 시스템과 매우 비슷하고 선택의 여지가 없었다: VTK와 같은 방대한 클래스 라이브러리의 자동 래핑을 지원하는 것이 매우 중요했다. 이 라이브러는 연산 결과로 객체가 다른 객체를 만들 수 있게 하고, 더 복잡해진 연산과 데이터 간의 구분을 래핑한다.

이 결정의 두 번째 장점은 워크플로우에서 상수 값과 사용자가 설정할 수 있는 매개변수를 정의할 수 있게 해서, 시스템의 통합을 더 쉽게 그리고 단일화한다. 예를 들면, 상수로 지정한 웹에 있는 파일을 로드하는 워크플로우를 생각해 보자. 이것은 현재 매개변수로 URL을 지정해서 GUI로 지정한다(그림 32.1의 매개변수 편집 부분을 참고해라). 이 워크플로우의 자연스러운 수정은 업스트림에서 연산된 URL을 호출(fetch)하기 위해 사용하는 것이다. 우리는 가능한 한 적게 워크플로우를 변경하고 싶다. 모듈이 자신을 출력할 수 있다고 가정하면, 단순히 매개변수에 해당하는 포트에 적당한 값으로 문자열을 연결할 수 있다. 상수 검증의 출력이 자신이기 때문에, 실제로 그 값이 상수로 지정된 것처럼 동작은 같다.

그림 23.5: PythonSource 모듈과 함께 새로운 기능 프로토타이핑 하기

상수 설계와 연관된 다른 고려사항이 있다. 각 상수 타입은 자신의 값을 지정하기 위한 다양한 이상적인 GUI 인터페이스가 있다. 예로, 비스트레일에서, 파일 상수 모듈은 파일 선택 창을 제공하고; 부울(Boolean) 값은 체크박스로 지정하고; 색상 값은 각 운영체제에 있는 컬러 피커를 가지고 있다. 이 일반성을 이루기 위해, 개발자는 기본 상수 클래스에서 사용자 정의 상수로 상속해야 하고, 적절한 GUI 위젯과 문자열 표현(그래서 임의의 상수는 디스크에 직렬화될 수 있다)을 정의해서 오버라이드를 제공한다.

간단한 프로토타이핑 작업을 위해, 비스트레일이 내장PythonSource 모듈을 제공하는 것을 주의하자. PythonSource 모듈은 직접 워크플로우에 스크립트를 입력하는 데 사용할 수 있다. PythonSource(그림 23.5 참조)를 위한 설정 창은 실행하는 파이썬 코드와 함께 다중 입/출력 포트로 지정되는 것을 허용한다.

23.4. 컴포넌트와 기능

위에서 설명한 것처럼, 비스트레일은 탐색 연산 작업을 만들고 실행을 단순화하는 일련의 기능과 유저 인터페이스를 제공한다. 다음은 이들 중 일부를 설명한다. 또한, 풍부한 이력 발행의 생성을 지원하는 인프라를 위해 기본으로 사용하는 방법을 간단하게 설명한다. 비스트레일과 그 기능에 대한 종합적인 설명은 온라인 문서를 참고해라.

그림 23.6: 비주얼 스프레드시트

23.4.1. 비주얼 스프레드시트

비스트레일은 사용자가 비주얼 스프레드시트를 사용해서 여러 워크플로우에서 결과를 탐색하고 비교할 수 있게 한다. 스프레드시트는 시트(sheets)와 셀(cells)로 구성된 자체 인터페이스가 있는 비스트레일 패키지이다. 각 시트는 일련의 셀을 포함하고 있고 사용자 정의 레이아웃을 가지고 있다. 셀은 워크플로우가 만들어낸 결과의 비주얼 표현을 포함하고 있고, 다양한 타입의 데이터를 표시하도록 사용자가 정의할 수 있다.

스프레드시트에 셀을 표시하기 위해, 워크플로우는 SpreadsheetCell 모듈을 기반으로 하는 모듈을 포함해야 한다. SpreadsheetCell 모듈은 스프레드시트의 셀에 해당하기에, 워크플로우는 여러 셀을 만들 수 있다. SpreadsheetCell 모듈의 compute 메서드는 실행엔진(그림 23.3)과 스프레드시트 사이의 통신을 처리한다. 실행 중에, 스프레드시트는 파이썬의 동적 클래스 인스턴스화를 활용해서, 요청한 타입에 따라 셀을 만든다. 따라서 사용자 정의 비주얼 표시는 SpreadsheetCell 서브 클래스를 만들고 그 클래스의 compute 메서드가 스프레드시트에 사용자 정의 셀 타입을 전달해서 달성할 수 있다. 예로, 그림 23.1의 워크플로우에서, MplFigureCell 은 SpreadsheetCell 모듈이고matplotlib가 만들어내는 이미지를 표시하도록 설계했다.

스프레드시트가 GUI 백엔드로 PyQt를 사용하기에, 사용자 정의 셀 위젯은 PyQt의QWidget를 서브클래스 해야 한다. 또한, 새로운 데이터가 도착하면, 스프레드시트가 위젯을 업데이트하기 위한, updateContents 메서드를 정의해야 한다. 각 셀 위젯은 선택적으로 toolbar 메서드를 구현해서, 사용자 정의 툴바를 정의할 수 있다; 툴바는 셀을 선택했을 때, 스프레드시트에서 툴바 영역에 표시될 것이다.

그림 23.6은 VTK 셀을 선택했을 때 보이는 스프레드시트이고, 이 경우, 툴바는 PDF 이미지 내보내기, 워크플로우에 카메라 위치 저장하기 그리고 애니메이션 만들기의 특정 위젯을 제공한다. 스프레드시트 패키지는 기록 재생(애니메이션)과 멀티 터치 이벤트 전송과 같은 공통 기능을 제공하는 사용자 정의 QCellWidget을 정의한다. QCellWidget은 새로운 셀 타입의 빠른 개발을 위해 QWidget 대신 사용할 수 있다.

비록 스프레드시트가 셀 타입으로 PyQt 위젯만 허용하지만, 다른 GUI 툴킷으로 작성한 위젯도 통합할 수 있다. 이렇게 하려면, 위젯이 네이티브 플랫폼(native platform)에 요소(elements)를 내보내야 하고, 그리고 다음에 PyQt가 요소를 사용할 수 있다. VTKCell 위젯은 실제로 C++로 개발되었기 때문에, 이 방식을 사용한다. 실행 시에, VTKCell은 시스템에 의존적인, 윈도 아이디(window id), Win32, 또는 코코아/카본(Cocoa/Carbon) 핸들을 저장하고, 스프레드시트 캔버스에 매핑한다.

셀처럼, 시트 또한 사용자 정의할 수 있다. 기본적으로, 각 시트는 탭 뷰에 있고 테이블 레이아웃의 형태이다. 그러나 한번에 여러 시트를 표시하도록, 시트를 스프레드시트 창에서 분리할 수 있다. 또한, StandardWidgetSheet를 상속해서 다양한 시트 레이아웃을 만들 수 있고, 또한 PyQt 위젯도 그렇다. StandardWidgetSheet는 셀 레이아웃과 더불어 편집 모드에서 스프레드시트와의 상호 작용을 관리한다. 편집 모드에서, 사용자는 셀 데이터와 상호작용보다 셀 레이아웃을 바꾸고 셀에 고급 동작을 수행할 수 있다. 이런 동작은 매개 변수 탐색에서 유사 적용(23.4장 참고)과 새로운 워크플로우 버전 생성을 포함한다.

23.4.2. 시각적 차이와 유추

비스트레일이 설계한 대로, 이력정보의 사용과 더불어 수집이 활성화되길 원했다. 먼저, 사용자가 버전 간의 정확한 차이를 보기 원했지만, 다른 워크플로우에 이 차이를 적용할 수 있는 더 유용한 기능을 알게 됐다. 비스트레일이 워크플로우의 변화를 기록하기 때문에, 이 작업은 둘 다 가능하다.

버전 트리가 모든 변경을 저장하고 각 동작을 되돌리 수 있기 때문에, 다른 버전에서 변경한 동작의 전체 순서를 찾을 수 있다. 일부 변경이 서로 상쇄시켜, 이 순서를 압축할 수 있게 한다는 것을 주의해라. 예를 들면, 나중에 삭제된 모듈의 추가는 차이를 연산할 때 검사할 필요가 없다. 마지막으로, 순서를 더 단순화하기 위한 일부 휴리스틱(heuristics)을 가지고 있다: 두 워크플로우에 같은 모듈이 존재하지만, 추가(adds)와 삭제(deletes)를 취소하는 분리된 동작으로 추가됐다.

변경에서, 우리는 비슷하고 다른 모듈, 연결 그리고 매개변수를 보여주는 시각적인 표시를 만들 수 있다. 이것은 그림 23.4가 보여주고 있다. 워크플로우 양쪽에 보이는 모듈과 연결은 회색이고, 나타나는 워크플로우에 따라 하나만 색을 띠게 된다. 다양한 매개변수와 일치하는 모듈은 밝은 회색으로 그림자 처리하고, 사용자는 각 워크플로우의 값을 보여주는 테이블에서 특정 모듈에 대한 매개변수 차이를 검사할 수 있다.

유추 작업(operation)은 사용자가 이런 차이를 이해해서 다른 워크플로우에 적용하게 한다. 사용자가 기존의 워크플로우(예로, 출력 이미지의 해상도 및 파일 포맷 변경)에 일련의 변경을 하면, 유추로 다른 워크플로우에 같은 변경을 적용할 수 있다. 이렇게 하려고, 사용자는 일련의 원하는 변경의 제한과 더불어 유추를 적용하기 원하는 소스 워크플로우와 타켓 워크플로우를 선택한다. 비스트레일은 템플릿으로 처음 두 워크플로우를 사이의 차이점을 계산하고, 다음에 세 번째 워크플로우에 적용하기 위해 차이를 다시 매핑하는 방법을 결정한다. 시작하는 워크플로우와 완전히 일치하지 않는 워크플로우에 차이점을 적용하는 것이 가능해서, 비슷한 모듈 사이에 통신을 허용하는 소프트 매칭이 필요하다. 이 매칭으로, 차이점을 다시 매핑할 수 있고, 그래서 변경 순서는 선택된 워크플로우에 적용될 수 있다[SVK+07]. 이 방법은 안전하지 않고 전혀 원하지 않는 새로운 워크플로우를 만들어낼 수도 있다. 이런 경우, 사용자는 특정 도입 실수를 해결하려고 시도할 수도 있고, 또는 이전 버전으로 돌아가고 수동으로 변경을 적용한다.

유추에 사용하는 소프트 매칭을 계산하기 위해, 전체 워크플로우 구조와 로컬 매치(같거나 매우 유사한 모듈)를 비교해 보길 원한다. 심지어 같은 매칭의 계산이 서브그래프 동일유형의 일치하는 정도에 기인하기 때문에 충분하지 않다는 것을 주의해라, 그래서 휴리스틱의 적용이 필요하다. 간단하게, 비슷한 이웃(모듈)을 공유하는 두 개의 워크플로우에 약간 비슷한 모듈이 두 개가 있다면, 이 두 모듈의 기능이 유사하고 또는 일치하리라 판단할 수 있다. 공식적으로, 각 노드는 원본 워크플로우에서 모듈의 짝일 수 있고, 엣지는 공유된 연결을 나타내는 제품 그래프를 만든다. 그런 다음, 인접 노드에 엣지로 걸치는 각 노드에서 점수를 확산하는 단계를 실행한다. 이것은 구글의 페이지 랭크와 비슷한 마르코프 프로세스(Markov process) 이고, 결과적으로 지금은 일부 글로벌 정보를 포함하는 일련의 점수를 남겨서 수렴할 것이다. 이 점수로부터, 아주 비슷하지 않은 모듈을 짝 지우지 않고 내버려 두기 위해 임계 값을 사용해서 최적의 매칭을 결정할 수 있다.

유추에 사용하는 소프트 매칭 : 정확하게일치해서검색하는기존의방식보다발전된형태로, 사용자의심리나상관관계가높은정보에가중치를부여해서원하는결과를검색하는방식
마르코프 프로세스(Markov process, http://en.wikipedia.org/wiki/Markov_process, 미래의 프로세스가 현재의 상태에 의해서만 결정되는, 과거와는 독립적인 랜덤 프로세스

23.4.3. 이력 질의

비스트레일이 수집한 이력은 일련의 워크플로우, 자신의 구조, 메타데이터 그리고 실행 로그를 포함한다. 사용자가 이력 데이터에 접근해서 탐색할 수 있는 것은 중요하다. 비스트레일은 텍스트 기반 그리고 비주얼 위지윅(WYSIWYG) 질의 인터페이스 모두 제공한다. 태그, 어노테이션 그리고 날짜와 같은 정보에 대해서, 선택적인 마크업으로 키워드 검색을 사용할 수 있다. 예로, 사용자(user:~dakoop)가 만든 plot 키워드로 모든 워크플로우를 찾고 있는 중. 그러나 워크플로우의 특정 서브그래프에 대한 질의는 사용자가 처음부터 질의를 만들거나 파이프라인에 기존 조각을 복사하거나 수정하는 QBE(query-by-example) 인터페이스로 더 쉽게 나타낸다.

http://en.wikipedia.org/wiki/Query_by_Example, 사용자가 데이터베이스에 있는 정보를 검색할때, 기존의 방법(SQL)을 좀 더 쉽게 만들어주는 방법, 예로 인터넷에서 검색하는 방법이 QBE에 해당한다.

이 QBE 인터페이스를 설계할 때, 매개 변수 구성에 일부 변화와 함께 기존의 워크플로우 편집기의 코드 대부분을 유지했다. 매개변수는, 정확한 값보다 범위나 키워드를 검색하는데 종종 유용하다. 따라서 매개변수 값 필드에 제한자를 추가했다; 사용자가 매개변수 값을 추가하거나 수정할 때, 정확하게 일치하는 기본값으로 제한자 중 하나를 선택해서 고를 수 있다. 비주얼 질의 구성과 더불어, 질의 결과도 시각적으로 보인다. 일치하는 버전은 버전 트리에서 강조하고, 선택된 워크플로우는 일치하는 부분이 강조돼서 표시된다. 사용자는 다른 질의를 시작하거나 리셋 버튼을 클릭해서 질의 결과 모드를 종료할 수 있다.

23.4.4. 영속 데이터

비스트레일은 각 단계의 결과가 만들어진 방법과 스펙의 이력을 저장한다. 그러나 워크플로우가 더는 사용할 수 없는 데이터가 필요한 경우, 워크플로우의 재현하기가 어려울 수 있다. 게다가, 오래가는 워크플로우에 대해서, 재계산을 피하고자 세션에 영속적인 캐시로 중간 데이터를 저장하는 것은 유용할 수 있다.

많은 워크플로우 시스템이 파일시스템 경로에 이력 데이터를 저장하는데, 이 방법은 문제가 있다. 사용자가 파일 이름을 변경할 수도 있고, 데이터를 복사하지 않고 다른 시스템으로 워크플로우를 이동하거나 데이터 내용을 변경할 수 있다. 이런 경우에, 이력을 경로에 저장하는 것은 적합하지 않다. 데이터를 해시하고, 이력으로 해시된 데이터를 저장하는 것은 데이터가 변경되었는지 결정하는 데 도움이 되지만, 데이터가 존재한다 해도, 데이터가 위치를 알려주지 않는다. 이 문제를 해결하기 위해, 이력에서 참조할 수 있는 데이터를 저장하기 위해 버전 관리 인프라를 사용하는 비스트레일 패키지인, 영속 패키지(Persistence Package)를 만들었다. 현재, 다른 시스템도 쉽게 적용할 수 있지만, 데이터를 관리하기 위해 Git를 사용하고 있다.

데이터를 식별하기 위해 일반적으로 UUID(universally unique identifiers)를 사용하고, 기트(git)에서 버전을 참조하기 위해 해시를 커밋한다. 실행에서 다른 실행으로 데이터가 변경된 경우, 새로운 버전이 리파지토리에 체크인된다. 따라서, (uuid, version) 튜플은 어떤 상태에서도 데이터를 검색하기 위한 복합 식별자가 된다. 게다가, 데이터의 해시를 저장하는 것과 더불어 그것(입력이 아니라면)이 만들어낸 워크플로우의 업스트림 부분의 서명도 저장한다. 이것은 별도로 식별할 수 있는 것과 더불어 같은 계산을 다시 시작할 때 재사용하는 데이터에 링크를 허용한다.

이 패키지 설계 시에 주된 관심은 사용자가 자신의 데이터를 선택하고 검색할 수 방법이었다. 또한, 데이터를 입력, 출력 또는 중간 데이터(워크플로우의 출력을 다른 워크플로우의 입력으로 사용할 수 있다)로 사용하는지에 상관없이, 같은 리파지토리에 모든 데이터를 유지하기 원했다. 사용자가 데이터를 식별하기 위해 적용할 수 있는 두 가지 유형이 있다: 새로운 참조를 만들기로 선택하거나 기존의 참조를 사용하기. 처음 실행 후에, 새로운 참조는 실행내내 지속하는 기존의 참조가 된다는 것을 주의해라: 사용자가 원한다면 나중에 새로운 참조를 만드는 것을 선택할 수도 있지만, 이것은 드문 경우다. 사용자는 종종 최신 버전의 데이터를 사용하기 원하기 때문에, 특정 버전 없이 식별된 참조는 기본으로 최신 버전이 될 것이다.

모듈을 실행하기 전에, 모든 입력이 재귀적으로 갱신되는 것을 상기해라. 업스트림 연산이 이미 실행한 경우, 영속 데이터 모듈은 그것의 입력을 갱신하지 않을 것이다. 이를 확인하기 위해, 영구 저장소에 업스트림 하위 워크플로우의 서명을 확인하고 서명이 있는 경우 사전에 계산된 데이터를 검색한다. 게다가, 특정 실행을 재현할 수 있도록, 이력으로 데이터 식별자와 버전을 기록한다.

23.4.5. 업그레이드

비스트레일의 핵심인 이력으로, 기존 워크플로우를 업그레이드하는 능력은 새로운 버전의 패키지를 실행하는 방식이므로 중요한 문제이다. 써드 파티(third-parties)가 패키지를 만들 수 있기에, 워크플로우를 업그레이드하기 위한 인프라와 더불어 업그레이드 경로를 지정해서 패키지 개발자를 위한 후크 둘 다 필요하다. 워크플로우 업그레이드에 연관된 핵심 동작은 모듈을 새로운 버전으로 교체하는 것이다. 기존 모듈에서 모든 연결과 매개변수를 교체해야 하므로, 교체하는 동작이 복잡하다는 것을 주의해라. 게다가, 업그레이드는 모듈에 대한 매개변수와 연결의 재설정, 재할당 또는 이름 변경이 필요할 수 있다. 예를 들면, 모듈의 인터페이스가 변경될 수도 있다.

각 패키지는(연관 모듈과 같이) 버전으로 태깅하고, 버전이 변경된 경우, 패키지의 모듈이 변경되었다고 간주한다. 일부 또는 대부분이 변경되지 않았을 수도 있지만, 코드를 분석하지 않고는 확인할 수 없다는 것에 주의해라. 그러나 변경하지 않은 모든 인터페이스의 업그레이드도 자동으로 시도한다. 자동으로 업그레이드하려고, 모듈을 새로운 버전으로 교체해 보고, 동작하지 않으면 예외처리한다. 개발자가 모듈의 인터페이스 변경하거나 모듈의 이름을 변경했을 경우, 명시적으로 변경을 지정할 수 있다. 이것을 더 쉽게 관리 하기 위해서, 단지 기본 업그레이드 동작이 수정해야 하는 유일한 위치를 지정하는 remap_module 메서드를 만들었다. 예로, 개발자가 입력포트 ‘file’을 ‘value’로 이름 변경하는 것은 특정 리패밍(remapping)으로 지정할 수 있어서, 새로운 모듈이 만들어질 때, 기존 모듈에서 ‘file’에 연결된 모든 연결은 ‘value’로 연결할 것이다. 내장 비스트레일 모듈에 대한 업그레이드 경로의 예는 다음과 같다.

def handle_module_upgrade_request(controller, module_id, pipeline):
   module_remap = {'GetItemsFromDirectory':
                       [(None, '1.6', 'Directory',
                         {'dst_port_remap':
                              {'dir': 'value'},
                          'src_port_remap':
                              {'itemlist': 'itemList'},
                          })],
                   }
  return UpgradeWorkflowHandler.remap_module(controller, module_id, pipeline, module_remap)

이 코드 조각은 기존의 GetItemsFromDirectory(1.6버전까지) 모듈 대신 Directory 모듈을 사용하도록 워크플로우를 업그레이드한다. 이 코드는 기존 모듈에서 ‘dir’ 포트를 ‘value’로 ‘itemlist’ 포트를 ‘itemList’ 포트로 매핑한다.

모든 업그레이드는 버전 트리에서 새로운 버전을 만들어서, 업그레이드 전/후 실행을 구분하고 비교할 수 있다. 이것은 업그레이드가 워크플로우(예, 패키지 개발자가 버그 픽스)의 실행을 변경하고, 이력 정보로 변경을 추적해야 하는 것을 가능하게 한다. 기존 비스트레일에서, 트리의 모든 버전을 업그레이드할 필요가 있을 수도 있다는 것을 주의해라. 복잡성을 줄이기 위해, 사용자가 탐색(navigate)한 버전만 업그레이드한다. 게다가, 워크플로우가 수정되거나 실행될 때까지, 모든 업그레이드의 지속을 지연할 수 있게 환경설정을 제공한다: 사용자가 기존 버전을 사용하는 경우, 업그레이드를 고집할 필요는 없다.

23.4.6. 풍부한 이력 결과의 공유와 출판

재현성은 과학적 방법의 초석(기초)이기에, 전산 실험(computational experiments)을 설명하고 있는 현재의 출판물은 반복되거나 일반화할 수 있는 결과를 가능하게 하는 충분한 정보를 제공하는 것이 종종 실패한다. 최근, 재현할 수 있는 결과의 발행에 새로운 관심이 있었다. 이 실천의 광범위한 적용의 큰 장애는, 결과를 재현해야 하는 것과 더불어 결과를 검증해야 하는 컴포넌트(예, 데이터, 코드, 매개변수 설정)를 모두 포함하는 번들을 만드는 것이 어렵다는 사실이다.

자세한 이력을 캡처하고, 위에서 설명한 많은 기능을 통해서, 비스트레일은 시스템에서 실행하는 전산 실험을 위한 프로세스를 단순화한다. 그러나, 이 방법은 문서를 링크하는 것과 이력 정보를 공유하는 것 둘다 필요했다.

딥 캡션(deep caption, 글이나 이미지등을 흥미롭게 만드는 2~3 문장의 내용) 과 같이, 그들의 이력에 링크된 논문의 결과를 보여주는 것이 가능한 비스트레일 패키지를 개발했다. 라텍스(LaText) 패키지를 사용해서 개발했고, 사용자는 비스트레일 워크플로우에 링크 수치를 포함할 수 있다. 다음의 라텍스 코드는 워크플로우 결과를 포함하고 있는 수치를 만들 것이다.

\begin{figure}[t]
{
\vistrail[wfid=119,buildalways=false]{width=0.9\linewidth}
}
\caption{Visualizing a binary star system simulation. This is an image
  that was generated by embedding a workflow directly in the text.}
\label{fig:astrophysics}
\end{figure}

Pdflatex를 사용해서 문서를 컴파일할 때, \vistrail 명령은 XML-RPC 메시지를 비스트레일 서버에 id 119 와 함께 워크플로우를 실행하기 위해 전송하는 매개변수와 함께 파이썬 스크립트를 호출한다. 같은 파이썬 스크립트가 서버에서 워크플로우의 결과를 다운받고 특정 레이아웃 옵션(width=0.9\linewidth)을 사용해서, 링크된 라텍스 \includegraphics 명령을 만들어서 PDF 문서 결과에 그것들(링크)을 포함한다.

또한, 웹 페이지, 위키(Wiki), 워드 문서 그리고 파워포인트 문서에 비스트레일 결과를 포함할 수 있다. 마이크로소프트 파워포인트와 비스트레일 사이의 연결은 COM(Component Object Model)과 OLE(Object Linking and Embedding) 인터페이스를 사용하고 있다. 파워포인트와 상호 작용하기 위한 객체는, 최소한 COM 인터페이스 IOleObject, IDataObject와 IPersistStorageinterface를 구현해야 한다. COM 인터페이스 구현을 위해 추상화한 Qt의 QAxAggregated 클래스를 사용하고, OLE 객체를 빌드하기 위해, IDataObject 와 IPersistStorage는 둘 다 Qt가 자동으로 처리한다. 따라서 단지 IOleObject 인터페이스를 구현하면 된다. 이 인터페이스의 가장 중요한 호출이 DoVerb이다. 이것은 객체 활성화와 같이, 파워포인트에서의 특정 액션에 비스트레일이 반응하게 해 준다. 이 구현에서는, 비스트레일 객체가 활성화될 때, 비스트레일 애플리케이션을 로딩하고 사용자에게 열고, 상호작용하고, 입력하기 원하는 파이프라인을 선택하는 것이다. 비스트레일을 종료한 후, 파이프라인 결과는 파워포인트에 보일 것이다. 또한, 파이프라인 정보는 OLE 객체에 저장되어 있다.

사용자에게 연관 이력과 함께 결과를 자유롭게 공유할 수 있도록, crowdLabs을 만들었다. crowdLabs은 협력해서 데이터 분석과 시각화하도록 과학자를 위한 환경을 제공하는 일련의 유용한 툴과 확장성 있는 인프라를 통합한 소셜 웹 사이트이다. crowdLabs은 비스트레일과 밀접하게 통합되어 있다. 사용자가 비스트레일에서 만들어진 결과를 공유하기 원한다면, 정보를 업로드하기 위해서 직접 crowdLabs 서버에 연결할 수 있다. 정보가 업로드 되면, 사용자는 웹 브라우저로 상호 작용과 워크플로우를 실행할 수 있다. 이 워크플로우는 crowdLabs을 동작시키는 비스트레일 서버가 실행한다. 재현할 수 있는 출판물을 만드는 데 사용하는 비스트레일 방법에 대한 자세한 내용은 http://www.vistrails.org를 참조해라.

23.5. 교훈

다행히, 2004년에 다시 이력을 지원하는 데이터 탐색과 시각화 시스템을 빌드하는 것에 대해서 생각하기 시작했다. 이 도전이 얼마나 어려운 것인지, 또한 지금 있는 지점까지 얼마나 오래 걸릴지 알지 못했다. 만약 알고 있었다면, 아마도 시작하지 않았을 것이다.

초기에, 잘한 하나의 전략은 새로운 기능의 빠른 프로토타이핑으로 선발된 사용자에게 빨리 보여줬다. 사용자로부터 받은 초기 피드백과 격려는 프로젝트를 앞으로 이끄는 데 중요하다. 이것은 사용자의 피드백 없이도 비스트레일을 설계하는 것을 가능하게 한다. 프로젝트에서 강조하고 싶은 한 측면이 있다면, 시스템 기능 대부분은 사용자 피드백에 직접 응답으로 설계했다는 것이다. 그러나 사용자가 요청한 것이 사용자(his/her)의 필요(사용자가 여러번 요청했다고 사용자의 요청에 대한 최고의 솔루션은 아니다)에 대한 최고의 솔루션이 아니라는 것은 여러번 주의할 만한 가치가 있다. 되풀이해서, 시스템에 유용하고 적절하게 통합하도록 확인하기 위해, 기능을 설계하고 재설계했다.

우리의 사용자 중심 접근 방식을 고려하면, 모든 기능이 자주 사용될 것이라고 기대할 수도 있다. 불행히도 이 경우는 일어나지 않는다. 종종 그 이유는 그것이 다른 툴에서 발견되지 않기에, 기능은 매우 “특별한” 것이다. 예로, 유추와 심지어 버전트리는 사용자 대부분이 잘 모르는 개념이고, 편하게 사용하기 위해서는 익숙해지는 시간이 필요하다. 또 다른 중요한 문제는, 문서화이고, 또는 문서화 부족이다. 다른 많은 오픈 소스 프로젝트와 마찬가지로, 우리는 기존의 것을 문서화하는 것보다 새로운 기능의 개발이 훨씬 더 되어있다. 문서화 지연은 유용한 기능을 충분히 활용하지 못하는 것과 더불어 메일링 리스트에 많은 질문이 올라오게 한다.

비스트레일과 같은 시스템을 사용하는 데 있어, 어려운 것 중 하나가 아주 일반적이다는 것이다. 사용성을 향상하기 위한 최대한 노력에도, 비스트레일은 복잡한 툴이고, 일부 사용자에게는 가파른 학습 곡선이 필요하다. 시간이 지나면서 개선된 문서로, 더 개선된 시스템, 그리고 더 많은 애플리케이션과 특정 도메인, 특정 필드에 대한 적용의 장애가 더 낮아질 것이라 믿는다. 또한, 이력의 개념이 더 광범위해져서, 사용자가 비스트레일 개발에 적용한 철학을 이해하기가 쉬워질 것이다.

23.5.1. 감사

비스트레일에 기여한 훌륭한 개발자들 모두에게 감사하고 싶다: 에릭 앤더슨(Erik Anderson), 루이 바보일(Louis Bavoil), 클리프턴 브룩스(Clifton Brooks), 제이슨 캘러핸(Jason Callahan), 스티브 캘러핸(Steve Callahan), 로레나 카를로(Lorena Carlo), 라우로 린스(Lauro Lins), 토미 엘크비스트(Tommy Ellkvist), 필립 메이트(Phillip Mates), 다니엘 리스(Daniel Rees) 그리고 네이선 스미스(Nathan Smith).

프로젝트의 비전을 개발하고 지원을 위해 노력한 안토니오 밥티스타(Antonio Baptista), 시스템을 개선하기 위해서 같이 협력하고 있고, 풍부한 이력 발행 기능의 개발과 배포를 위해 많은 자극을 준 매티아스 토로이어(Matthias Troyer)에게 특별히 감사한다.

비스트레일 시스템의 연구와 개발은 국립 과학 재단(National Science Foundation)의 IIS 1050422, IIS-0905385, IIS 0844572, ATM-0835821, IIS-0844546, IIS-0746500, CNS-0751152, IIS-0713637, OCE-0424602, IIS-0534628, CNS-0514485, IIS-0513692, CNS-0524096, CCF-0401498, OISE-0405402, CCF-0528201, CNS-0551724, 미국 에너지부 산하 SciDAC(Scientific Data Management Center), IBM Faculty Awards의 지원을 받고 있다.

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.