2010년 3월 25일 - cmislib 소개: Python용 클라이언트측 CMIS API, 결론 및 참고자료에 시리즈의 Part 2에 대한 링크가 추가되었다.
cmislib 소개: Python용 클라언트측 CMIS API
CMIS(Content Management Interoperability Services) 스펙을 위한 바쁜 계절이 다가오고 있다. OASIS는 1.0 릴리스를 준비 중이고 저장소 벤더는 서버측 구현을 준비하기 위해 열심히 노력하고 있고 컨텐츠 관리 커뮤니티의 개발자는 표준 방식으로 리치 컨텐츠 저장소에 대한 탐색과 작업을 용이하게 하는 클라이언트 및 API를 릴리스하고 있다.
컨텐츠 중심 애플리케이션을 빌드해 본 경험이 있는 경우에는 일반적으로 기본 컨텐츠 저장소에 접근하는 방법을 알아내는 것이 첫 번째 문제라는 것을 알고 있다. 팀에서는 먼저 저장소의 SDK에 대한 집중 교육을 받는다. 그런 다음 사용자는 프리젠테이션 계층과 컨텐츠 서비스 계층 간 통합을 포함한 애플리케이션을 설계한다. 마지막으로 계획에 대해 실행한 후 치즈 프라이를 즐기면서 성공을 축하하면 된다. 하지만 유감스러운 점은 이렇게 섭취한 칼로리가 허리 둘레에 미치는 영향이 아니라 모든 저장소에는 고유 API가 있기 때문에 각각의 새로운 프론트엔드 및 백엔드 조합에 대해 프로세스가 반복된다는 것이다. 또한 애플리케이션이 복수의 저장소에 액세스하는 경우(이러한 경우가 자주 있음) 복수의 인터페이스에 대해 배우고 복수 인터페이스로 코딩해야 한다.
다행히도 이 문제점은 이전에 해결되었다. 패턴은 SQL 표준화 이전에 존재했던 패턴과 동일하다. IBM®에서 만든 관게형 데이터베이스와 기타 Bean은 1970년대 초기에 등장했지만 SQL 쿼리 언어에 대한 첫 번째 공식적인 표준을 만들기 위한 노력은 1986년에야 시작되었다. 이러한 노력이 시작된 이후(특히 1992년의 주요 개정 이후) 개발자는 프론트엔드 애플리케이션을 작성하고 여러 관계형 백엔드에 대해 적용될 수 있다고 합리적으로 확신할 수 있게 되었다. CMIS에는 SQL이 관계형 데이터베이스 애플리케이션에 대해 수행했던 컨텐츠 중심 애플리케이션을 위해 동일한 사항을 수행할 수 있는 잠재력이 있다. CMIS는 기본 저장소 구현 또는 선택한 프론트엔드 프로그래밍 언어에 관계없이 백엔드와 상호작용하는 표준 방식을 위해 제공된다. 여기서는 행과 열 대신 일반적으로 계층 구조의 폴더 구조로 되어 있는 구조화되지 않은 컨텐츠와 반구조화된 컨텐츠(일반적으로 일종의 파일)에 대해 설명한다.
그림 1. 이미지가 포함된 프론트엔드 또는 백엔드에 관계없이 공통 인터페이스를 제공하는 CMIS
이 기사는 cmislib라는 Python의 CMIS 저장소에 대한 작업에 필요한 클라이언트측 라이브러리에 대한 것이다. 현재 Apache Chemistry 프로젝트의 일부로 관리되는 라이브러리의 목표는 Python 개발자가 CMIS 준수 백엔드에 대해 작업할 수 있는 컨텐츠 중심 애플리케이션을 쉽게 작성할 수 있도록 하는 것이다. 많은 사용자는 API를 통해 CMIS의 기능을 쉽게 이해할 수 있다.
API가 왜 작성되었는지, API가 어떤 역할을 수행하는지, API가 어떻게 개발되었는지(원하는 언어로 작성하려는 경우)와 작동 중인 cmislib의 몇 가지 간단한 예제에 대해 살펴보자. 이 시리즈의 다음 기사에서는 라이브러리의 실제 애플리케이션에 대해 설명한다.
Python에서 CMIS용 클라이언트측 API를 작성하는 것은 여러 가지 이유에서 좋은 아이디어인 것 같았다. 몇 가지 이유는 전략적이며 이상적이다. 다른 이유는 좀 더 전술적이고 이기적이다. “공공의 이익”에 부합하는 이유부터 시작해 본다.
CMIS 준수 공급자는 웹 서비스 바인딩과 RESTful AtomPub(Atom Publishing Protocol) 바인딩 둘 다를 제공해야 한다. 각 바인딩은 상대 바인딩에 비해 고유의 장점을 가지고 있지만 한 가지 차이점은 여러 서버에서 CMIS 서비스가 검색되어 호출되는 방법에 있다. 웹 서비스 바인딩에는 자동으로 클라이언트 코드를 생성하는 데 사용할 수 있는 WSDL 파일이 포함된다. 웹 서비스 바인딩을 사용하려는 경우에는 CMIS 서버의 WSDL로도 자체 클라이언트측 API를 생성할 수 있다.
반면 RESTful AtomPub 바인딩에는 서비스에 대해 설명하는 표준 방식이 없다. RESTful한 바인딩으로서 모든 서비스는 URL을 통해 액세스되지만 CMIS 스펙의 특정 URL을 각각의 벤더가 결정한다. 따라서 RESTful AtomPub 바인딩을 사용하여 모든 CMIS 준수 공급자에서 작동하는 코드를 작성하려는 경우에는 클라이언트측에서 약간의 작업을 더 수행해야 한다. 프로젝트에서 해당 작업을 반복하는 대신 오픈 소스 프로젝트를 사용하여 모두를 위해 이를 한 번 수행하는 것이 좋다.
다음 이유는 애플리케이션 개발자와 컨텐츠 저장소 벤더의 채택과 관련된 것이다. 개발자는 온라인 회의 및 블로그 게시물과 트위터 트래픽을 감시할 수 있지만 이들을 직접 확인할 때까지 CMIS는 단지 또 하나의 과대 포장된 전문 용어일 뿐이다. 소프트웨어가 여전히 상자에 포장되어 제공되는 경우에는 “Now with CMIS!”라고 표시된 밝은 색의 “폭발” 그래픽을 상상할 수 있다. 깔끔하고 생산적이며 설치가 쉬운 Python은 과대 포장 뒤에 숨겨진 모습을 찾으려고 하는 사용자가 이러한 사용자 및 이들의 애플리케이션을 위해 CMIS가 실제로 무엇을 할 수 있는지 확인하기 위해 선택할 수 있는 가장 적합한 항목처럼 보인다. cmislib API는 구현 세부 사항으로부터 개발자를 보호하고 직관적이고 오브젝트 지향적이며 상호 운용 가능한 방식의 작업을 제공한다. 개발자가 보여지는 대로 이를 사용하여 사용자 정의 컨텐츠 중심 애플리케이션이 컨텐츠가 Python으로 빌드되었는지 여부에 관계없이 풍부한 컨텐츠 저장소와 상호 운용되도록 하는 표준 방식으로 CMIS를 사용하기를 바란다.
CMIS를 채택하는 벤더가 하나 또는 둘밖에 되지 않으면 본래 목적에 어긋나게 된다. 따라서 표준의 혜택을 보는 사용자가 벤더의 채택을 독려하기 위해 할 수 있는 작업을 수행하는 것이 합리적이다. cmislib 배포판에는 유닛 테스트가 단순히 개발 베스트 프랙티스로 포함되어 있다. 테스트 스위트는 API가 개발될 때 기능이 회귀되지 않도록 하는 데 적합하고 반복 가능한 방식으로 상호 운용성의 유효성을 검증하는 간편한 방법이기도 하다. 하지만 가장 눈에 띄는 것은 유닛 테스트가 벤더에 대한 테스트 스위트 역할을 한다는 점이다. IBM, Alfresco™, OpenText 및 Nuxeo는 모두 cmislib를 활용하여 구현과 관련된 문제를 찾아냈다. 이는 cmislib 벤더가 작업을 유효성 검증하기 위해 커뮤니티에 의해 빌드된 모든 종류의 CMIS 도구 및 클라이언트를 사용한 것으로 제한되지 않으며 이 점이 매우 유용한 부분이다.
조직은 개인을 위하고 개인은 조직을 위한다는 것은 좋은 동기가 되지만 코드로 작성되는 경우는 드물다. 오픈 소스 프로젝트는 모두 개발자가 해결해야 하는 문제에서 시작한다. 이 경우에 이러한 문제는 클라이언트가 Python 기반 웹 애플리케이션 개발 프레임워크인 Django™와 오픈 소스 컨텐츠 관리 플랫폼인 Alfresco 간 통합을 제공할 수 있도록 Optaros®가 수행한 인트라넷 프로젝트에서 시작한다. CMIS가 OASIS에서 하나의 아이디어 수준이었을 때 개발되었기 때문에 통합은 서버측의 Alfresco 웹 스크립트(자체 RESTful API를 Alfresco로 진행시키는 데 필요한 프레임워크)에 의존하여 Django 기반 프리젠테이션 계층과 Alfresco 저장소 사이에서 HTTP를 통해 XML을 앞뒤로 이동한다. 제대로 작동하기는 하지만 Alfresco에만 해당된다. Django 통합을 리팩토링하여 CMIS를 활용하는 것은 좋은 생각처럼 보인다. 하지만 Django에만 적용되도록 하는 대신 먼저 cmislib를 하위 레벨 Python API로 롤아웃하도록 선택했다. 이 경우의 장점은 cmislib를 활용하여 Django 외에도 다른 Python 프로젝트(예: Zope® 및 Plone®)와 사용자 정의 Python 애플리케이션을 더 편리하게 CMIS 저장소와 통합할 수 있다는 것이다.
이기적인 이유 중 마지막은 개발자의 생산성에 관련된 것이다. 대부분의 엔터프라이즈에서는 하나의 저장소만 처리하지 않는다. 또한 솔루션이 작동될 특정 저장소를 예상할 수 없거나 적어도 중간에 옵션을 전환해야 하는 경우가 발생할 수 있다. CMIS 표준은 이러한 문제를 해결하는 데 확실히 도움이 되지만 실제로 작업을 생산적으로 완료하기 위해서는 클라이언트측 라이브러리가 필요하다. 다른 프로젝트는 이미 CMIS를 위해 Java™ 및 PHP 기반 클라이언트 라이브러리를 제공하려는 계획을 진행 중이다. 하지만 Python은 프리젠테이션 계층에 많이 보급되어 있기 때문에 CMIS에 대한 Python 기반 클라이언트 라이브러리가 중요하다.
cmislib의 목표는 CMIS의 기본 구현 세부 사항을 추출해 내는 것이다. 개발자는 CMIS 저장소 위에 솔루션을 빌드하기 위해 CMIS가 어떻게 작동하는지 배우기를 원하지 않거나 배울 필요가 없다. 대신 cmislib는 컨텐츠 저장소에 대해 작업하거나 CMIS 스펙을 읽는 모든 사용자에게 바로 익숙해지는 이해하기 쉬운 오브젝트 모델을 제공한다. 콜렉션, 항목 및 피드 대신 개발자는 저장소, 폴더, 문서 및 ACL과 같은 자연스러운 컨텐츠 관리 개념을 다룬다.
언급한 바와 같이 cmislib는 RESTful AtomPub 바인딩을 사용하여 CMIS 서버와 통신한다. 중요한 개발 고려사항은 cmislib에는 히트하고 있는 백엔드 저장소에 대한 벤더별 정보가 없이 라이브러리가 CMIS 공급자를 블랙 박스처럼 처리하도록 하는 것이었다. cmislib를 사용하여 CMIS 공급자에 연결하는 경우에는 CMIS 공급자의 시작점 또는 서비스 URL 및 일부 신임을 제공한다. 라이브러리는 서버 응답을 조사하여 서버와 추가로 상호작용하는 방법을 알아본다.
예를 들어, 현재 체크아웃된 문서 목록을 가져오려고 한다고 가정한다. CMIS 스펙은 다음 사항을 알린다.
- 체크아웃된 문서의 콜렉션이 있다.
repositoryId는getCheckedOutDocs서비스를 호출할 때 필수 인수이다.- 여러 가지 선택적 인수가 전달될 수 있다(대부분 결과 세트 페이징과 관련됨).
- 서비스로부터의 응답은 Atom 피드이다.
하지만 스펙에서는 콜렉션을 검색할 정확한 URL은 알려주지 않는다. 이 URL은 벤더가 결정한다. cmislib가 처리하는 사항 중 하나는 해당 URL이 무엇인지와 Python 방식으로 작업할 수 있는 Python 오브젝트로 응답을 변환하는 방법을 알아내는 것이다. Listing 1에서는 Python 쉘에서의 이러한 상호작용을 보여 준다.
Listing 1. 저장소에서 체크아웃된 문서 나열하기
>>> rs = repo.getCheckedOutDocs() >>> len(rs) 2 >>> for doc in rs: ... doc.title ... u'Response XML (Working Copy)' u'd1 (Working Copy)' |
이와 비슷하게 문서에서 체크아웃을 수행하려고 한다고 가정한다. 스펙에서는 체크아웃을 수행하려면 Atom 항목을 체크아웃된 콜렉션에 게시해야 하고 저장소에서는 방금 체크아웃한 오브젝트의 PWC(Private Working Copy)를 나타내는 Atom 항목을 리턴한다고 알려 준다.
cmislib를 사용하는 경우에는 콜렉션 판별, Atom 항목 XML 빌드 및 게시 또는 XML 응답 처리에 대해 걱정하지 않아도 된다.
대신 오브젝트에 대한 checkout 메소드를 호출하기만 하면 cmislib에서는 PWC를 나타내는 문서 오브젝트를 다시 제공한다.
Listing 2에서는 이러한 상호작용을 보여 준다.
Listing 2. 문서 체크아웃하기
>>> doc.title u'testdoc' >>> pwc = doc.checkout() >>> pwc.title u'testdoc (Working Copy)' >>> doc.checkedOut True |
cmislib는 가능한 한 스펙과 가깝게 작성되는 것이 중요했다. 따라서 첫 번째 단계는 Eclipse와 스펙을 나란히 열어 놓고 클래스와 메소드를 없애는 것이었다. 필자는 인라인 주석에 스펙에 대한 교차 참조를 추가했기 때문에 이후에 메소드를 구현하기 위해 돌아왔을 때 스펙에서 적용 가능한 지점을 신속하게 찾았다.
필자는 처음부터 빌드 프로세스, 문서 및 소스 코드 제어를 설정했다. 해당 항목을 조기에 설정하는 것이 중요했기 때문에 추가적인 개발자가 프로젝트에 참여하여 빠르게 증가할 수 있었다.
코드는 반복적으로 발전했다. 각각의 반복은 새로운 기능에 대한 유닛 테스트 작성에서 시작하여 유닛 테스트를 통과할 때까지 계속 메소드의 실제 코딩을 수행했다. 필자는 저장소에서의 기능 쿼리와 일반적인 접근 방식을 유효성 검증하는 데 필요한 오브젝트 및 오브젝트 특성 검색과 같은 기본사항에서 시작했다. 그런 다음 전체 쓰기 조작, 체크아웃/체크인, 관계 및 ACL로 진행했다.
참조 구현이 없고(Apache Chemistry의 참조 구현에 있는 AtomPub 바인딩이 당시에 읽기 전용이었음) 벤더가 구현에 대해 계속 작업 중이었기 때문에 처음부터 테스트는 약간 어려웠다. CMIS를 조기에 채택한 Alfresco가 가장 성숙한 구현을 가지고 있기 때문에 필자는 Alfresco부터 시작했다. 대부분의 유닛 테스트가 Alfresco에 대해 깔끔하게 완료된 즉시 필자는 공개적으로 사용 가능한 CMIS 구현을 가진 추가적인 벤더에 대한 테스트를 시작했다. IBM은 친절하게도 자발적으로 구현을 사용할 수 있도록 해 두었다. 이 두 번째 구현을 추가하는 것은 새로운 사실이었지만 모든 벤더와 cmislib에 대한 많은 실습이 수반되었다. 클라이언트측과 서버측 모두에서 이 유형의 상호 운용성 테스트가 없었으면 신속하게 발견되지 않았을 문제를 찾았다.
cmislib와 같은 API 또는 CMIS 도구를 개발하는 경우에는 가능한 한 많은 다양한 서버에 대해 테스트하는 것이 중요하다. 스펙은 새로운 것이며 벤더 구현은 여전히 성숙되고 있다(드래프트 스펙을 완전히 준수하도록 요구하는 벤더 구현으로부터도). 발견되는 가장 일반적인 문제는 세 가지 유형으로 구분된다.
- 불완전한 구현. CMIS는 아직까지는 매우 새로운 서비스이다. 누락된 서비스(현재는 ACL, 관계, 정책 및 변경 로그에 대한 지원이 가장 적음), 아직 지원되지 않는 필수 기능(예: 제공되지 않는 필수 콜렉션 및 링크) 및 하드코드된 값을 찾는 것이 일반적이다.
- 스펙 해석상의 차이. CMIS 스펙은 잘 작성된 읽기 쉬운 문서이지만 여전히 해석이 필요한 부분이 있다. 예를 들어, 드래프트 6 이전에는 체크아웃된 콜렉션의 컨텐츠가 명확하지 않았다. 체크아웃된 오브젝트 또는 오브젝트 자체의 PWC(Private Working Copy)를 포함하도록 되어 있었는가? 여러 벤더는 이를 서로 다르게 해석하여 해석에 따라 구현했다. 이러한 특정 문제는 이후 정리되었지만(PWC가 해답임) 이로 인해 상호 운용 가능한 클라이언트를 작성하는 것이 어려워진다는 것을 알 수 있다.
- 잘못된 가정. 스펙에 대한 벤더의 특정 확장은 명확한 경우도 있지만 명확하지 않는 경우도 있다. 하나의 서버에 대해 API를 코딩하여 해당 API가 참조 구현인 것처럼 처리하는 경우에는 다른 구현도 동일한 방식으로 작동할 것이라는 가정을 세운 것이다. 지금 문제되는 것은 스펙을 100% 준수하고 기능상 완벽한 AtomPub 바인딩이 포함된 CMIS 참조 구현이 없다는 것이다.
이 시리즈의 다음 기사에서는 디지털 자산 및 메타데이터를 사용하여 CMIS 저장소를 벌크 로드하는 데 사용할 수 있는 Python 스크립트에 대해 안내하여 라이브러리의 실제 애플리케이션을 보여 준다. 아래의 기본 예제는 cmislib 문서에서 가져오며 Python 대화식 쉘에서 API를 사용하여 공통 조작을 수행하는 방법을 보여 준다. 조작에는 저장소에 대한 정보 가져오기, 폴더 및 문서에 대해 작업하기와 CMIS 쿼리, 경로, 오브젝트 ID 또는 관계별로 오브젝트 찾기가 포함된다.
CmisClient 및 저장소 오브젝트는 CMIS 저장소에 대한 모든 정보에 대한 일반적인 시작 위치이다. 인스턴스를 가져오는 것은 간단하다. 저장소의 서비스 URL 및 신임만 알면 된다. 방법은 다음과 같다.
- 명령행에서 python을 입력하여 Python 쉘을 시작한 후 Enter를 클릭한다.
-
CmisClient 가져오기:
>>> from cmislib.model import CmisClient
-
CmisClient가 저장소의 서비스 URL을 가리키도록 지정:
>>> client = CmisClient('http://cmis.alfresco.com/s/cmis', 'admin', 'admin')
-
저장소에는 ID가 있다. 이 ID를 알고 있으면 ID를 사용하여 저장소를 가져올 수도 있다.
이 경우에는 클라이언트에게 기본 저장소를 요청한다.
>>> repo = client.defaultRepository >>> repo.id u'83beb297-a6fa-4ac5-844b-98c871c0eea9'
-
이제 저장소의 특성을 가져올 수 있다. 이 for 루프는 cmislib가 저장소에 대해 알고 있는 모든 정보를 제공한다.
(간결성을 위해 목록을 잘랐음)
>>> repo.name u'Main Repository' >>> info = repo.info >>> for k,v in info.items(): ... print "%s:%s" % (k,v) ... cmisSpecificationTitle:Version 1.0 Committee Draft 04 cmisVersionSupported:1.0 repositoryDescription:None productVersion:3.2.0 (r2 2440) rootFolderId:workspace://SpacesStore/aa1ecedf-9551-49c5-831a-0502bb43f348 repositoryId:83beb297-a6fa-4ac5-844b-98c871c0eea9 repositoryName:Main Repository vendorName:Alfresco productName:Alfresco Repository (Community)
저장소 오브젝트가 있으면 폴더 및 문서와 같은 저장소의 오브젝트에 대한 작업을 시작할 수 있다.
-
루트에서 새 폴더를 작성한다. 실제로 이를 따라하는 경우에는 공용 저장소에 대해 테스트하는 경우 폴더의 이름을 고유한 이름으로 지정한다.
>>> root = repo.rootFolder >>> someFolder = root.createFolder('someFolder') >>> someFolder.id u'workspace://SpacesStore/91f344ef-84e7-43d8-b379-959c0be7e8fc'
-
그런 다음 일부 컨텐츠를 작성할 수 있다.
>>> someFile = open('test.txt', 'r') >>> someDoc = someFolder.createDocument('Test Document', contentFile=someFile)
-
원하는 경우에는 새로 작성된 문서의 특성을 덤프할 수도 있다(목록의 일부임).
>>> props = someDoc.properties >>> for k,v in props.items(): ... print '%s:%s' % (k,v) ... cmis:contentStreamMimeType:text/plain cmis:creationDate:2009-12-18T10:59:26.667-06:00 cmis:baseTypeId:cmis:document cmis:isLatestMajorVersion:false cmis:isImmutable:false cmis:isMajorVersion:false cmis:objectId:workspace://SpacesStore/2cf36ad5-92b0-4731-94a4-9f3fef25b479
여러 가지 방법으로 오브젝트를 확보할 수 있다.
- CMIS 쿼리를 실행할 수 있다.
- 특정 경로 또는 오브젝트 ID에 해당하는 오브젝트를 제공하도록 저장소에 요청할 수 있다.
- 폴더의 하위를 사용하여 저장소를 이동할 수 있다.
- 관계에 의해 결합된 소스 오브젝트와 대상 오브젝트를 가져올 수 있다.
작업 시 이러한 옵션을 보여 주는 예제 중 일부는 다음과 같다.
- 전체 텍스트 검색을 사용하여 이전 섹션에서 작성된 문서를 찾는다.
>>> results = repo.query("select * from cmis:document where contains('test')") >>> for result in results: ... print result.name ... Test Document2 Example test script.js
-
또는 다음과 같이 경로를 사용하여 오브젝트를 가져올 수도 있다.
>>> someDoc = repo.getObjectByPath('/someFolder/Test Document') >>> someDoc.id u'workspace://SpacesStore/2cf36ad5-92b0-4731-94a4-9f3fef25b479'
-
또는 다음과 같이 오브젝트 ID를 사용하여 오브젝트를 검색할 수 있다.
>>> someDoc = repo.getObject('workspace://SpacesStore/2cf36ad5-94a4-9f3fef25b479') >>> someDoc.name u'Test Document'
-
폴더 오브젝트에는 페이징 가능한 결과 세트를 리턴하는 getChildren() 및 getDescendants() 메소드가 있다
>>> children= someFolder.getChildren() >>> for child in children: ... print child.name ... Test Document Test Document2
-
폴더 및 문서에는 관계 오브젝트 세트를 리턴하는 getRelationships() 메소드가 있다. 관계 오브제트는 관계의 끝 각각에서 소스 오브젝트와 대상 오브젝트를 제공할 수 있다.
>>> rel = testDoc.getRelationships(includeSubRelationshipTypes='true')[0] >>> rel.source.name 'testDoc1' >>> rel.target.name 'testDoc2' >>> rel.properties['cmis:objectTypeId'] 'R:sc:relatedDocuments'
이 시리즈의 다음 기사에서는 오브젝트 유형 정의를 검색하는 기능을 포함한 API의 다른 부분에 대해 작업하는 방법에 대해 살펴본다.
이 기사에서는 cmislib에 대한 간단한 개요, cmislib의 등장 배경, cmislib의 역할 및 몇 가지 기본 예제에 대해 설명했다. 이제 CMIS에 대한 관심이 더 많아졌기를 바란다. Python에 관심이 있다면 cmislib를 살펴본다. 링크는 참고자료를 참조한다. 관심이 없다면 다른 도구와 클라이언트 라이브러리를 찾아본다. 마지막으로 CMIS 커뮤니티에는 당신의 도움이 필요하다. 여러 가지 방식으로 도움을 줄 수 있다.
- 주로 사용하는 언어로 작성된 클라이언트 라이브러리가 없으면 오픈 소스 프로젝트로 해당 클라이언트 라이브러리를 작성한다.
- 저장소 벤더가 CMIS 구현을 테스트하는 것을 돕는다.
- 주로 사용하는 포털 또는 프리젠테이션 프레임워크에 대한 통합을 작성하여 CMIS 저장소에 대해 쉽게 작업할 수 있도록 한다.
- cmislib 및 Apache Chemistry와 같은 기존 오픈 소스 CMIS 프로젝트에 참여한다.
- OASIS 기술 위원회에 참여하여 CMIS 스펙을 지원한다.
교육
- A CMIS API library for Python, Part 2: Build real world ECM tools with Python and cmislib: Create a sample application(JJay A. Brown, developerWorks, 2010년 3월): 이 시리즈의 마지막 기사에서 CMIS와 Python을 결합하여 cmislib를 사용하는 ECM 도구를 빌드해 보자.
소스 코드를 살펴보고 명령행에서 도구를 사용하는 방법에 대해 알아보자.
- cmislib Google 코드 홈 페이지: cmislib에 대한 자세한 정보를 살펴보자.
- Getting Started with CMIS: 기본 RESTful Atompub 바인딩이 어떻게 작동하는지 알고 싶은가? Jeff의 블로그에 있는 튜토리얼을 읽어 보자.
- CMIS 포스터 동영상: 시각적인 튜토리얼을 확인하려면 YouTube에 있는 Jay Brown의 포스터 랩을 둘러보자.
- Content Management Interoperability Services를 위한 Mozilla Firefox 플러그인 개발하기(Gregory Melahn, Shun Zhang, Yan Chen, Hui Jian He 및 Ziao Wang, developerWorks, 2009년 12월): CMIS 개요와 CMIS 브라우저 플러그인의 예제를 확인할 수 있다.
- CMIS API 및 클라이언트 도구: 이 Lotus Quickr Wiki 페이지에서 CMIS에 대해 제안된 OASIS 표준을 사용하는 저장소 및 애플리케이션의 컴파일에 대해 살펴보자.
- OAISI에 있는 CMIS 기술 위원회: 여러 벤더가 제공하는 컨텐츠 관리 저장소에서 정보를 공유할 수 있도록 웹 서비스 및 Web 2.0 인터페이스를 사용하는 데 필요한 작업을 살펴보자.
- Python과 Django: 시스템을 더 효과적으로 통합할 때 신속한 작업을 위해 필요한 Python에 대해 자세히 살펴보자. 상위 레벨 Python 웹 프레임워크인 Django를 추가하여 효율적인 고성능 웹 애플리케이션을 신속하게 빌드해 보자.
- developerWorks의 XML 영역: XML 영역에서 스킬 향상을 위해 필요한 참고자료를 얻을 수 있다.
- IBM XML 인증: XML 및 관련 기술에 대한 IBM 인증 개발자가 되는 방법을 찾아볼 수 있다.
- XML Technical library: developerWorks XML 영역에서 다양한 기술 관련 기사와 팁, 튜토리얼, 표준 및 IBM Redbook을 볼 수 있다.
- developerWorks 기술 행사 및 웹 캐스트: 이들 세션에 참가하여 최신 기술에 대한 정보를 얻을 수 있다.
- Twitter의 developerWorks: 지금 참여하여 developerWorks의 트윗(tweet)을 팔로우(follow)하자.
- developerWorks
팟캐스트: 소프트웨어 개발자의 흥미로운 인터뷰와 토론을 확인할 수 있다.
제품 및 기술 얻기
- IBM FileNet and IBM Content Manager Technology Preview for OASIS CMIS: IBM FileNet® 및 IBM Content Manager 저장소의 CMIS REST/Atom 바인딩을 다운로드하여 살펴보자.
- IBM 제품 평가판: IBM SQA Sandbox의 온라인 시험판을 다운로드하거나 살펴보고 DB2®,
Lotus®, Rational®, Tivoli® 및
WebSphere®의 애플리케이션 개발 도구 및 미들웨어 제품을 사용해 볼 수 있다.
토론
- XML 영역 토론 포럼: 여러 XML 관련 토론에 참여해 볼 수 있다.
- developerWorks
포럼 & 블로그: 이러한 블로그를 읽어보고 참여할 수 있다.
Jeff Potts는 오픈 소스 구성 요소를 특징으로 하는 컨텐츠, 상거래 및 커뮤니티 솔루션을 결합하는 데 집중하는 세계적인 컨설팅 회사인 Optaros에서 엔터프라이즈 컨텐츠 관리 프랙티스 부서의 시니어 디렉터로 근무하고 있다. Jeff는 ECM 프랙티스 부서를 12년 넘게 이끌어 왔고 IT 부서와 전문적인 서비스 조직에서 IT 및 기술 구현 분야에 18년 넘게 근무했다. Jeff는 클로즈드 소스 컨텐츠 관리 플랫폼과 오픈 소스 컨텐츠 관리 플랫폼에 대한 상당한 경험이 있으며 특히 현재 Alfresco 커뮤니티의 구성원으로 활동하고 있다. 2008년에 Jeff는 Alfresco Developer Guide(Packt Publishing)를 저술하여 2008년 Packt's Author of the Year Award를 수상했다. 2008년 초기에 Jeff는 프로젝트에 cmislib를 제공하여 Apache Chemistry에 참여했다. Jeff의 블로그인 http://ecmarchitect.com에서 대화에 참여할 수 있다.