메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

소셜 오브젝트를 Atom 형식으로 표현

Activity Streams 표준 소개

Ben Werdmuller, Consultant and writer, Freelance
Ben Werdmuller is a web strategist and developer who specializes in open source platforms. He co-founded and was the technical lead for Elgg, an open source social networking framework. Ben blogs regularly at http://benwerd.com/.

요약:  소셜 네트워킹 사이트의 치솟는 인기 덕분에, 사람들이 온라인을 통해 하고 있는 일을 표현하는 웹 피드에 대해 새로운 표준이 등장하게 되었습니다. Atom 형식을 확장한 Activity Streams를 사용하면 웹 사이트에서 사회적 활동을 상호 공유할 수 있습니다. Activity Streams 형식이 소셜 오브젝트를 어떻게 표현하는지 알아보고, PHP에서 활동 피드 인코더를 빌드하는 방법을 학습하고, 기업에서 Activity Streams를 활용할 수 있는 분야를 찾아보십시오.

원문 게재일:  2010 년 6 월 15 일 번역 게재일:   2010 년 7 월 30 일
난이도:  중급 영어로:  보기 PDF:  A4 and Letter (69KB | 18 pages)Get Adobe® Reader®
페이지뷰:  3545 회
의견:  


웹에서 피드는 시스템에서 읽을 수 있도록 컨텐츠를 요약한 것으로, 보통 연도순의 반대 순서로 배열된다. 대부분의 피드는 전통적으로 많이 사용되는 RSS 또는 Atom XML 기반 형식으로 블로그 컨텐츠를 상호 공유하는 데 사용되었다. 컨텐츠가 사이트에 게시되면 사용자에게 친숙한 수집가를 통해 컨텐츠를 읽거나 네트워크 소프트웨어 제품에서 컨텐츠를 변환 및 해석할 수 있다.

PHP 준비

본 기사의 PHP 예제를 따라가려면 PHP 5 이상과 그 언어에 대한 전반적인 이해가 필요하다. PHP 다운로드 페이지에 대한 링크는 참고자료를 참조한다.

신디케이트된 피드는 1999년 부터 이런 방식으로 사용되었다. 하지만, 근래에는 웹 사용자들이 Facebook, MySpace 및 Twitter와 같은 사이트를 통해 더 사회적인 방법으로 컨텐츠를 사용하고 있기도 하다. 이들 사이트는 사람들이 다른 사용자들을 "친구"로 등록하여 통합 대시보드를 통해 친구들의 활동을 집계할 수 있게 하는 방식으로 운영된다. 이런 사이트의 사용자들은 단일 컨텐츠 스트림을 구독하는 것이 아니라, 개별 사용자가 작성, 업로드 및 공유하는 모든 것을 볼 수 있을 것으로 기대하며 개별 사용자에게 등록한다.

활동 스트림(activity stream)(때때로 lifestream이라고도 함)은 특정 사이트에서 어떤 사람이 시도하는 모든 활동을 모은 콜렉션이다. 웹 사용자들이 정보의 소비를 위해 점점 더 활동 스트림에 의존함에 따라, 활동 스트림 데이터를 상호 공유하고 구독할 수 있는 것이 이치에 맞는 일이다. 그러나 RSS와 Atom에서 소셜 메타데이터를 지원하지 않으므로, 사회적 활동을 상호 공유하기 위한 새로운 형식이 필요하다.

자주 사용하는 약어

  • RSS: Really Simple Syndication
  • URI: Uniform Resource Identifiers
  • URL: Uniform Resource Locator
  • XML: Extensible Markup Language

소셜 오브젝트를 표현하기 위해 Atom을 확장하도록 발전을 거듭하고 있는 표준인 Activity Streams의 세계로 들어가보자. Activity Streams는 등장한 지 얼마 안 되지만, 웹 애플리케이션 간의 활동을 상호 공유하기 위한 사실상의 표준으로 빠르게 자리매김하고 있다. 예를 들어, 현재 MySpace, Facebook 및 TypePad는 모두 Activity Streams XML 피드를 만들어낸다. 그러나 이 기술은 소비자 웹 환경만을 위한 것은 아니다. 회사 인트라넷과 내부 소프트웨어가 점점 사회적인 성격을 띠어감에 따라, Activity Streams를 하나의 기능으로 구현하기 위한 분명한 비즈니스적 이유가 뒷받침된다. 이 기사에서는 Activity Streams를 자세히 설명하고, 엔터프라이즈 환경에서 효과적으로 활용할 수 있는 방안을 생각해보고, PHP를 사용하여 Activity Streams를 해석하기 위한 몇 가지 예제를 제시한다.

Activity Streams의 기원

Activity Streams는 출발점으로서 WordPress 블로깅 플랫폼용으로 개발된 플러그인을 사용하여 분산된 소셜 웹을 빌드하기 위한 오픈 소스 프로젝트인 DiSo 프로젝트(참고자료 참조)에서 그 모습을 처음으로 드러냈다. DiSo 모델에서는 각 사용자의 프로파일이 인터넷에 연결된 인프라에서 호스트될 수 있는 별개의 WordPress 블로그이다. 이런 WordPress 사이트 간에 인터넷을 통해 사회적 활동이 일어난다.

신디케이션 형식은 이 접근 방식의 중요한 부분이다. 하나의 거대한 디지털 구현 환경에 수억 명의 구성원이 있는 Facebook과 같은 사이트와는 반대로, DiSo에서는 WordPress 사이트당 한 명의 사용자만 있는 것으로 가정하고 운영된다. 따라서 친구들이 어떤 활동을 하고 있는지 한눈에 볼 수 있는 유일한 방법은 그들의 피드를 구독하고 피드를 내부 데이터 구조로 구문 분석하여 집계된 인터페이스에서 보는 방법이다.

XML은 크로스 플랫폼이고 게시 및 구문 분석이 용이하며 전문적인 기술이 전혀 필요하지 않으므로 이 접근 방식을 구현하기에 완벽한 기술이다. DiSo 프로젝트에서는 한 단계 더 나아가 Activity Streams 표준을 Atom 피드 형식의 확장으로 생각했다.

Atom은 다음과 같은 특징을 가진 RSS의 대안으로 고안된 것이다.

  • 100% 벤더에 중립적일 수 있음
  • 누구든 구현할 수 있음
  • 누구든 자유롭게 확장할 수 있음
  • 깔끔하고 완전하게 지정될 수 있음

벤더 중립성, 확장성 및 완전한 스펙은 모두 미래를 대비한 표준에 필수적인 요소이다. Activity Streams 표준이 분산된 소셜 웹의 실용적이고 경쟁력 있는 중추로 자리를 잡으려면 역시 이런 원칙을 고수해야 한다. 그리고 Atom의 확장성 덕분에, Activity Streams에서는 기존 애플리케이션 논리와 기존 구문 분석기를 활용할 수 있다. 이론적으로, 이미 Atom을 다루기 위한 코드가 있거나 기존의 많은 라이브러리 중 하나를 사용하는 경우에는 추가로 개발해야 할 코드가 얼마 되지 않는다.

2009년 3월, MySpace는 Activity Streams 형식으로 피드를 게시하는 최초의 주요 소셜 미디어 공급자가 되었다. 그 이후로, Facebook, Hulu, TypePad 및 Opera를 포함한 많은 공급자들이 뒤를 이었다. 그러나 Activity Streams의 적용 범위는 Facebook과 같은 사이트로 제한되지 않는다. 예를 들어, 회사 내부 또는 회사 간의 사회적 활동에 대한 지식 축적과 인식 제고로 인트라넷이 크게 향상될 수 있다. Activity Streams 형식에서는 다중 스트림을 집계하여 회사의 상호 작용을 추적하고 상업적 소셜 미디어 사이트들의 목표 달성 진행 상태를 정량화할 수 있는 가능성도 생긴다. 관리, 분석, 알고리즘 또는 사용자 관점 등 어떤 관점에서 보든, 소셜 미디어의 사용 상태를 추적할 수 있는 능력을 통해 새로운 종류의 소프트웨어 애플리케이션을 위한 많은 기회가 발생한다.


활동 스트림의 해부

Activity Streams는 http://activitystrea.ms/spec/1.0/ XML 네임스페이스를 기반으로 하는 몇 가지 새로운 스키마 요소로 Atom을 확장한다.

Atom 피드는 몇 가지 초기 메타데이터(예: 피드 제목, 작성자, URL 및 피드에서 참조하는 전체 컨텐츠의 URL)를 포함하는 단일 기본 피드 요소로 구성된다. 이 기본 요소 내부에는 피드 내부의 컨텐츠 항목을 정의하는 임의 개수의 entry 요소가 있다. Listing 1은 필자의 웹 사이트에서 파생된 단일 entry 요소가 있는 샘플 Atom 피드를 나타낸 것이다.


Listing 1. 필자의 웹 사이트에서 가져온 샘플 Atom 피드

<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
  xml:base="http://benwerd.com/wp-atom.php"
   >
    <title type="text">Ben Werdmuller von Elgg</title>
    <subtitle type="text"></subtitle>

    <updated>2010-05-01T13:13:04Z</updated>

    <link rel="alternate" type="text/html" href="http://benwerd.com" />
    <id>http://benwerd.com/feed/atom/</id>
    <link rel="self" type="application/atom+xml" href="http://benwerd.com
/feed/atom/" />

    <entry>
        <author>
            <name>Ben Werdmuller von Elgg</name>
            <uri>http://benwerd.com/</uri>
        </author>
        <title type="html"><![CDATA[Sample article title]]></title>
        <link rel="alternate" type="text/html" href="http://benwerd.com/2010/05
/sample-article-title/" />
        <id>http://benwerd.com/2010/05/sample-article-title/</id>
        <published>2010-05-01T13:06:22Z</published>
        <content type="html" >
            ...
        </content>
    </entry>

</feed>

Activity Streams에서는 각각의 entry 요소 내에 있는 소셜 오브젝트에 대한 데이터를 삽입하여 Atom 모델을 확장한다. entry 요소의 하위 요소에 대한 기존의 가능성에는 영향을 주지 않는다. 예를 들어, titlecontent 하위 요소 내부의 동작에 대해 제목과 사람이 판독할 수 있는 설명을 포함시키거나, 표준 Atom 형식의 content 요소 내부에 소셜 메타데이터를 포함시킬 수 있다.

Activity Streams entry 요소에는 항상 다음을 나타내는 세 가지 주 요소가 포함된다.

  • 행위자: 작업을 수행하는 사람(예: John Doe)
  • 동사: 수행되고 있는 작업의 유형(예: added)
  • 오브젝트: 작업 대상 항목(예: Ben's photo)

어떤 상황에서는 entry 요소에 작업이 수행되거나 배치되었던 컨테이너 오브젝트인 대상이 포함될 수도 있다(예: John Doe added Ben's photo to John's photo gallery 작업의 John's photo gallery).

다음 요소들은 entry 요소 내에서 사용되어 동사, 오브젝트, 행위자 및 대상을 정의한다.

  • Activity:verb 요소에는 사용 중인 동사를 정의하는 Atom URI가 포함된다.
  • Activity:object 요소에는 다수의 activity:object-type 요소(다음 단락에서 설명함)뿐 아니라, 작업의 객체를 설명하는 데 필요한 다른 요소도 포함된다.
  • 행위자는 Listing 1에 표시한 것처럼 기존의 atom:author 요소에 의해 정의된다.
  • Activity:target 요소는 activity:object 요소와 비슷하지만, 특히 요소가 있는 대상을 정의한다.

activity:object, activity:targetatom:author 요소 내에는 상위 오브젝트를 정의하는 Atom URI를 포함한 하나 이상의 Activity:object-type 요소가 있다.

동사 및 오브젝트의 각 유형마다 유지할 수 있는 특성을 정의하는 Atom URI가 있다. 예를 들어, Listing 2는 사람, 공유할 동사 및 블로그 게시를 정의하는 기본 Activity Streams 스펙의 몇 가지 Atom URI를 나타낸 것이다.


Listing 2. 사람, 공유 및 블로그 게시를 위한 기본 Activity Streams URI

http://activitystrea.ms/schema/1.0/person
http://activitystrea.ms/schema/1.0/share
http://activitystrea.ms/schema/1.0/article

이런 URI들은 Activity Streams 스펙에서 사람이 읽을 수 있는 항목에 해당한다.

Listing 3에서는 Listing 1에 있는 예제 Atom 피드의 entry 요소를 블로그 항목을 게시하는 Ben Werdmuller를 나타내는 Activity Streams 표시로 변환했다.


Listing 3. Activity Streams 형식으로 된 Listing 1의 소셜 버전

<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xmlns:activity="http://activitystrea.ms/spec/1.0/"
  xml:lang="en"
  xml:base="http://benwerd.com/wp-atom.php"
   >
    <title type="text">Ben Werdmuller von Elgg</title>
    <subtitle type="text"></subtitle>

    <updated>2010-05-01T13:13:04Z</updated>

    <link rel="alternate" type="text/html" href="http://benwerd.com" />
    <id>http://benwerd.com/feed/atom/</id>
    <link rel="self" type="application/atom+xml" href="http://benwerd.com
/feed/atom/" />

    <entry>
        <id>http://benwerd.com/2010/05/sample-article-title/#actionID</id>
            <title type="text">Ben posted a blog entry.</title>
            <published>2010-05-01T13:06:22Z</published>
        <author>
            <name>Ben Werdmuller von Elgg</name>
            <uri>http://benwerd.com/</uri>
            <activity:object-type>
                http://activitystrea.ms/schema/1.0/person
            </activity:object-type>
        </author>
        <activity:verb>
            http://activitystrea.ms/schema/1.0/post
        </activity:verb>
        <activity:object>
            <title type="html"><![CDATA[Sample article title]]>
</title>
            <link rel="alternate" type="text/html"
 href="http://benwerd.com/2010/05/sample-article-title/" />
            <id>http://benwerd.com/2010/05/sample-article-title/</id>
            <published>2010-05-01T13:06:22Z</published>
            <content type="html" >
                ...
            </content>
            <activity:object-type>
                http://activitystrea.ms/schema/1.0/article
            </activity:object-type>
        </activity>
    </entry>
</feed>

다음 사항에 유의하자.

  • Activity Streams 어휘를 정의하기 위해 피드의 맨 위에 xmlns:activity=http://activitystrea.ms/spec/1.0/ 네임스페이스 선언이 추가되었다.
  • 전체 Atom entry 요소와 그에 포함된 activity:object 요소의 ID는 같을 수 없다.
  • 블로그 게시물에 관한 세부 사항—Listing 1의 표준 entry 요소에 있음—은 현재 필수적인 activity:object-type 요소 외에, activity:object 요소에 있다.
  • Activity Streams 피드를 지원하지 않는 구문 분석기와 함께 사용하기 위해 표준 atom:titleatom:content 요소는 그대로 유지되었다.

이 작업에는 단일 오브젝트만 있지만, 한 Activity Streams 항목에 여러 개의 오브젝트를 임베드하는 것이 유효하다.—Ben posted two blog entries 동작을 표현하기 위해 Listing 3을 수정하는 것을 예로 들 수 있다. 블로그 전체를 activity:target 요소로 추가하여 의미가 약간 다른 Ben added two entries to his blog 동작을 표현할 수 있다.

필자는 Listing 3의 피드 예제에서 일부러 기본적인 컨텐츠 유형을 사용했다. 하지만, Activity Streams 스펙은 동사와 오브젝트의 분화를 고려한 것이다. 예를 들어, 협업 프로젝트 관리 애플리케이션에서 사용자가 작업을 완료하는 시점을 가리킬 수 있다. 이 소프트웨어에서 완료(complete)에 대해 특수화된 동사와 작업(task)에 대해 특수화된 오브젝트를 정의할 수 있고, 이 각각에는 자체적인 사용자 정의 Atom URI가 있다. 하지만, Activity Streams와 호환되는 많은 도구들은 이런 용어들을 알지 못해 집계 중에 문제를 일으킬 수 있다. 이런 문제가 발생할 가능성을 줄이기 위해, Activity Streams 피드의 항목에는 같은 활동을 설명하는 둘 이상의 동사가 포함될 수 있다. 이런 예에서는 특정 동사나 오브젝트에 대해 상위의 전체 세트를 포함시키는 것이 좋은 아이디어다. Complete는 기본 동사 update를 단순히 특수화한 것일 수 있고, Task는 기본 오브젝트 note를 특수화한 것일 수 있다. 결과 Activity Streams 항목은 Listing 4와 같은 형태일 수 있다.


Listing 4. Activity Streams 피드에서 가상의 완료된 작업

<entry>
    <id>http://samplecompany.com/tasks/activity/23432/3242345/</id>
    <title type="text">Roger Taylor completed a task.</title>
    <published>2010-05-01T13:06:22Z</published>
    <author>
        <name>Roger Taylor</name>
        <uri>http://samplecompany.com/people/Roger+Taylor/</uri>
        <activity:object-type>
            http://activitystrea.ms/schema/1.0/person
        </activity:object-type>
    </author>
    <activity:verb>
        http://samplecompany.com/activity/schema/1.0/complete
    </activity:verb>
    <activity:verb>
        http://activitystrea.ms/schema/1.0/update
    </activity:verb>
    <activity:object>
        <title type="html"><![CDATA[Sample task]]></title>
        <link rel="alternate" type="text/html" href="http://samplecompany.com
/tasks/23432/" />
        <id>http://samplecompany.com/tasks/23432/</id>
        <published>2010-05-01T13:06:22Z</published>
        <content type="html" >
            ...
        </content>
        <activity:object-type>
            http://samplecompany.com/activity/schema/1.0/task
        </activity:object-type>
        <activity:object-type>
            http://activitystrea.ms/schema/1.0/note
        </activity:object-type>
    </activity>
</entry>

다음 사항에 유의하자.

  • 각각의 오브젝트 유형 URI는 고유의 activity:object-type 요소를 얻는다.
  • 각각의 동사 URI는 고유의 activity:verb 요소를 얻는다.
  • 특수화된 오브젝트 및 동사 유형에는 특수화된 고유의 URI가 있어야 한다.

필자가 이 기사를 쓰는 현재, Activity Streams 위키 문서에는 정식 스펙 문서에 정의된 기본 동사 유형 11개 및 기본 오브젝트 유형 19개를 포함하여, 21개의 동사 유형과 25개의 오브젝트 유형이 기록되어 있다. Activity Streams 구문 분석기는 이런 기본 동사와 오브젝트를 각각 인식하고 이들을 적절히 처리해야 한다.


Activity Streams 인코더 빌드

Activity Streams 표준은 단순하므로 인코더를 손쉽게 빌드할 수 있다. 여기서는 Activity Streams 피드를 문자열로 변환할 때(예를 들어, 이 피드를 포함한 PHP echo 문을 사용함) 이 피드를 나타내는 기본 PHP 인코더 오브젝트를 만들어본다. 전체 소스 코드는 다운로드를 참조한다.

우선, 스텁 클래스인 ActivityStreamEncoder를 작성하고 생성자 메소드를 정의하여 이 항목의 ID, 제목 및 설명을 선택한다. 개인용 배열인 $entries도 정의하여 Activity Streams 항목을 유지한다. Listing 5는 클래스와 생성자를 나타낸 것이다.


Listing 5. 생성자가 있는 기본 ActivityStreamEncoder 클래스

class ActivityStreamsEncoder {

    private $id = "";
    private $title = "";
    private $link = "";
    private $entries = array();
    
    function __construct($id, $title = '', $description = '') {
        $this->id = $id;
        $this->title = $title;
        $this->description = $description;
    }    
}

그 다음, 항목, 오브젝트 및 작성자에 대한 기본 클래스를 몇 가지 추가한다. 동사는 단순히 URI로 구성되기 때문에, 동사를 끝까지 문자열로 참조한다. 항목과 오브젝트는 기본적으로 게시 날짜를 현재 날짜로 설정한다(PHP time() 함수 사용). Listing 6은 항목에 대한 기본 클래스를 나타낸 것이다.


Listing 6. 기본 ActivityStreamEntry 클래스

class ActivityStreamsEntry {
    
    public $id = "";
    public $title = "";
    public $author;
    public $objects = array();
    public $verbs = array();
    public $published;
    
    function __construct() {
        $this->published = time();
    }
    
    function addObject(ActivityStreamsObject $object) {
        $this->objects[] = $object;
    }
    function addVerb(string $verb) {
        $this->verbs[] = $verb;
    }
    function setAuthor(ActivityStreamsAuthor $author) {
        $this->author = $author;
    }
    
}

ActivityStreamsEntry 클래스에는 작성자, 오브젝트 및 동사를 항목에 추가하기 위한 간단한 헬퍼 메소드도 포함되어 있어 이들 값의 적당한 변수 유형을 확인할 수 있다.

activity:object 요소의 하위 요소는 가변적이기 때문에, ActivityStreamsObject—오브젝트 클래스—의 특성은 각각 사용자 정의 getProperty()setProperty() 메소드를 사용하여 동적으로 가져오고 설정한다. 이것은 ActivityStreamsObjectActivityStreamsObject의 하위 클래스인 작성자 클래스를 보여주는 Listing 7에 정의되어 있다.


Listing 7. Activity Streams 오브젝트 및 작성자 인코더 클래스

class ActivityStreamsObject {
    public $properties = array();
    
    function getProperty($property_name) {
        if (isset($this->properties[$property_name])) 
return $this->properties[$property_name];
    }
    function setProperty($property_name, $property_value) {
        $this->properties[$property_name] = $property_value;
    }
    function __construct() {
        $this->published = time();
    }

    function addObjectType($object_type) {
        if (!isset($this->properties['object-type'])) $this->properties
                 ['object-type'] = array();
        $this->properties['object-type'][] = (string) $object_type;
    }
    
    function __toString() {
        $string = '';
        $string .= "\n<activity:object>";
        foreach($this->properties as $property => $value) {
            if (!is_array($value)) $value = array($value);
            switch($property) {
                case 'title':
                            $attr = 'type="html"';
                            break;
                case 'link':
                            $attr = 'rel="alternate" type="text/html" 
href="'.$value[0].'"';
                            $value = array(''); 
                            break;
                default:    $attr = '';
                            break;
            }
            if (sizeof($value))
                foreach($value as $val) {
                    if (empty($val))
                        $string .=  "\n\t<{$property} {$attr} />";
                    else if ($property == 'content' || $property == 'title')
                        $string .= "\n\t<{$property}
 {$attr}><![CDATA[{$val}]]></{$property}>";
                    else
                        $string .=  "\n\t<{$property} {$attr}>
{$val}</{$property}>";
                }
        }
        $string .=  "\n</activity:object>";
        
        return $string;
    }
    
}

class ActivityStreamsAuthor extends ActivityStreamsObject {
    function __construct() {
        $this->addObjectType("http://activitystrea.ms/schema/1.0/person");
    }
    function __toString() {
        $string = parent::__toString();
        $string = str_replace('activity:object>','author>',$string);
        return $string;
    }
}

여기서 클래스는 각각 activity:objectatom:author 요소의 구조적 버전을 나타낸다. (예를 들어, 이들 클래스를 브라우저로 반향하여) 이들을 문자열로 변환하려 할 때 구조적 XML이 자동으로 리턴된다. 각각의 Activity Streams 요소에 대해 동등한 PHP 클래스가 고유한 XML 표시를 담당하고 있는지 확인하여 Activity Streams 핸들러 오브젝트의 완전한 세트를 작성할 수 있다.

Listing 8에서는 전체 entry 요소를 나타내기 위해 유사한 클래스를 추가한다.


Listing 8. Activity Streams entry 요소를 나타내는 PHP 클래스

class ActivityStreamsEntry {

    public $id = "";
    public $title = "";
    public $author;
    public $objects = array();
    public $verbs = array();
    public $published;
    
    function __construct() {
        $this->published = time();
    }
    
    function addObject(ActivityStreamsObject $object) {
        $this->objects[] = $object;
    }
    function addVerb($verb) {
        $this->verbs[] = $verb;
    }
    function setAuthor(ActivityStreamsAuthor $author) {
        $this->author = $author;
    }

    function __toString() {
        
        $string = '';
        $string .=  "\n<entry>";
        $published = date('c',$this->published);
        $string .=  <<< END
        <id>{$this->id}</id>
        <title type="text"><![CDATA[{$this->title}]]></title>

        <published>{$published}</published>
END;
        if ($this->author instanceof ActivityStreamsAuthor) $string .=  
$this->author;
        if (sizeof($this->verbs)) foreach($this->verbs as $verb)
            $string .=  "\n<activity:verb>{$verb}</activity:verb>";
        if (sizeof($this->objects)) foreach($this->objects as $object)
            if ($object instanceof ActivityStreamsObject) $string .=  $object;
        $string .=  "\n</entry>";
        return $string;    
    }
}

Listing 8에서는 entry 요소 내부의 Activity Streams activity:verb, activity:objectatom:author 요소를 처리하기 위해 코드에 addVerb(), addObject()setAuthor() 메소드도 포함된다.

마지막으로, 유사한 addEntry() 메소드(Listing 8ActivityStreamsEntry 오브젝트를 스트림에 추가하기 위한 메소드)와 __toString() 매직 메소드를 포함하여 전체 Activity Streams 피드를 반향하기 위해 전체 ActivityStreamsEncoder 클래스를 수정할 수 있다. __toString() 메소드에는 Activity Streams 어휘를 올바로 사용하기 위해 필수적인 XML 헤더와 네임스페이스 선언이 포함된다. Listing 9addEntry()__toString() 메소드를 나타낸 것이다.


Listing 9. Listing 5의 ActivityStreamsEncoder 클래스를 위한 addEntry()__toString() 메소드

function addEntry(ActivityStreamsEntry $entry) {
        $this->entries[] = $entry;
    }
    
    function __toString() {
        // Display header
        $string = '';
        $updated_time = date('c',time());
        $string .=  <<<END
<?xml version="1.0" encoding="UTF-8"?>
<feed
xmlns="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns:activity="http://activitystrea.ms/spec/1.0/"
xml:lang="en"
>

<title type="text">{$this->title}</title>
<updated>{$updated_time}</updated>

<link rel="alternate" type="text/html" href="{$this->link}" />
<id>{$this->id}</id>
<link rel="self" type="application/atom+xml" href="{$this->id}" />

END;
        if (sizeof($this->entries))
            foreach($this->entries as $entry)
                if ($entry instanceof ActivityStreamsEntry) $string .= (string) $entry;
                
        $string .=  <<<END
</feed>
END;
        return $string;
    }

이렇게만 하면 된다. 구조적 Activity Streams 피드를 모으려면 Listing 10에서 본 것과 같이, 이런 일련의 오브젝트를 연결하여 브라우저로 반향하면 된다.


Listing 10. Listings 5에서 9의 PHP 코드를 사용하여 Listing 4의 Activity Streams 피드 렌더링

// Create a new Activity Stream
$stream = new ActivityStreamsEncoder('http://samplecompany.com/tasks/activity/', 
     'Task activities at Sample Company');

// Define the action's object
$object = new ActivityStreamsObject();
$object->setProperty('id','http://samplecompany.com/tasks/23432/');
$object->setProperty('title','Sample task.');
$object->setProperty('content','...');
$object->addObjectType('http://samplecompany.com/activity/schema/1.0/task');
$object->addObjectType('http://activitystrea.ms/schema/1.0/note');
$object->setProperty('link','http://samplecompany.com/tasks/23432/');

// Define the action's author
$author = new ActivityStreamsAuthor();
$author->setProperty('name','Roger Taylor');
$author->setProperty('uri','http://samplecompany.com/people/Roger+Taylor/');

// Define the overall entry, adding the object, verbs and author
$entry = new ActivityStreamsEntry();
$entry->addVerb("http://samplecompany.com/activity/schema/1.0/complete");
$entry->addVerb("http://activitystrea.ms/schema/1.0/update");
$entry->title = "Roger Taylor completed a task.";
$entry->id = 'http://samplecompany.com/tasks/activity/23432/3242345/';
$entry->addObject($object);
$entry->setAuthor($author);

// Add the entry to the stream
$stream->addEntry($entry);

// Echo the stream
header('Content type: text/xml');
echo $stream;

Listing 10의 코드에서는 표준 오브젝트 지향 PHP 메소드와 특성 호출을 사용하여 쿼리할 수 있는 활동 스트림의 구조적 버전을 유지한다. 피드를 표시하기 위해 echo가 호출되면 각 오브젝트의 내부 __toString() 매직 메소드가 호출되어 피드를 XML로 렌더링한다. Content type: text/xml 헤더는 광고를 위해 XML 파일을 표시할 브라우저로 먼저 전송된다.


Activity Streams 피드 구문 분석

PHP를 사용하면 어떤 종류의 XML 피드도 지극히 간단히 구문 분석할 수 있다. 내장 SimpleXML 기능으로 구조체를 로드하기만 하면 된다.

PHP를 이용한 구문 분석

Elliotte Rusty Harold가 쓴 "PHP를 이용한 SimpleXML 프로세싱" 기사에 PHP로 형식이 잘 갖춰진 XML—Atom 포함—의 구문 분석에 대한 개요가 휼륭하게 기술되어 있다.

  • Simplexml_load_file($filename)은 파일에서 구조적 XML을 로드한다.
  • Simplexml_load_string($filename)은 문자열에서 구조적 XML을 로드한다.

ActivityStreams 클래스를 명백히 수정한 다수의 클래스가 자연스럽게 제시된다. 그 중 한 가지는 내장 PHP 클래스 SimpleXMLElement를 상속하는 하나의 다목적 ActivityStreamsElement 클래스로 각각의 하위 클래스를 통합하는 것이다. 그런 다음 간단히 SimpleXML을 호출하여 XML의 피드를 다음과 같은 핸들러 오브젝트로 처리할 수 있다.


$activityStream = simplexml_load_string($xmlFeed, "ActivityStreamsElement");

그러나 SimpleXML 구문 분석 기능에 의해 리턴되는 기본값인 일련의 구조적 SimpleXMLElement로 스트림을 처리하는 것은 Listing 11에 표시된 것처럼 배열에 있는 요소를 통해 루프하는 것만큼이나 쉽다. 하지만, AtomActivityStreams 네임스페이스를 모두 참조하려면 주의해야 한다.


Listing 11. SimpleXML Atom 피드의 요소를 통한 루프

$activityStream = simplexml_load_string($stream);
$activityStream =  $activityStream->children('http://www.w3.org/2005/Atom');
if (is_array(!$activityStream->entry) && sizeof($activityStream->entry)) {
    foreach($activityStream->entry as $entry) {
        // Handle entry
    }
}

항목, 항목 내의 오브젝트, 작성자 등을 처리하기 위한 순환 함수를 개발할 수 있다. 상위 Atom 피드와 같은 Activity Streams 피드는 빠르게 구문 분석하여 다양한 목적으로 사용할 수 있는 간단한 XML 파일이다.


결론

Activity Streams 형식은 간단하고 쉽게 개발할 수 있으면서도 폭넓은 컨텍스트에서 강력한 성능을 발휘하므로, RSS에 대한 소셜 웹 애플리케이션의 해답으로 주목받고 있다. 엔터프라이즈 설정에서는 더 강력한 보안 기능과 더 정교한 기능을 제공하기 위해 Activity Streams를 확장할 수 있는 가능성이 많이 있다. 비즈니스 활동을 다루기 위해 특수화된 오브젝트 및 동사 유형을 작성하는 것 외에, OAuth와 같은 기술을 사용하여 스트림에 서명함으로써 사용자 정의 및 사용 권한을 바탕으로 하여 회사 활동을 볼 수 있는 뷰를 작성할 수도 있다. 제안하는 Atom Media 확장을 통해 사진, 비디오/오디오 파일 및 비즈니스 프리젠테이션과 같은 미디어 항목을 Activity Streams 피드 내에 임베드할 수 있다.



다운로드 하십시오

설명이름크기다운로드 방식
Article source codeActivityStreamsEncoder.zip2KBHTTP

다운로드 방식에 대한 정보


참고자료

교육

  • Activity Streams: go-to 참고자료 사이트에 방문하면 Activity Streams 표준에 대한 업데이트를 구할 수 있다.

  • DiSo Project: 분산된 소셜 웹을 위한 개방적이고 비독점적이며 상호 운용 가능한 빌딩 블록을 손쉽게 작성하려면 이 이니셔티브에 대해 자세히 살펴본다.

  • Adding richness to activity streams(Chris Messina, 2008년 6월): Activity Streams를 세상에 소개한 블로그 게시물을 읽을 수 있다.

  • Creating an Atom feed in PHP(Brian M. Carey, developerWorks, 2009년 7월): PHP를 이용한 Atom 피드 작성 방법을 알 수 있다.

  • PHP를 이용한 SimpleXML 프로세싱(Elliotte Rusty Harold, developerWorks, 2006년 10월): PHP를 이용한 XML 피드(Atom 포함) 처리 방법을 안내한다.

  • Atom (standard): Wikipedia의 Atom 스펙 개요를 확인해볼 수 있다.

  • RFC 4827 - The Atom Syndication Format: 피드로 알려진 관련 정보의 목록을 설명하는 이 XML 기반 문서 형식에 관한 세부 사항은 Atom 스펙에서 확인할 수 있다.

  • RFC 3339 - Date and Time on the Internet: Timestamps: Atom에서 사용하는 날짜/시간 스펙에 대해 알아보자.

  • Atom wiki: 공식적인 Atom 참조 자료를 살펴볼 수 있다.

  • PHP tutorial: PHP의 기본을 학습할 수 있는 사이트이다.

  • 무료로 제공되는 이 developerWorks 튜토리얼을 신청하여 PHP를 이용해 프로그램하는 방법을 학습할 수 있다.
    • Learning PHP, Part 1(Tyler Anderson 및 Nicholas Chase, developerWorks, 2002년 6월): HTML 양식과 데이터베이스 연결을 통해 PHP 기본을 탐구해보자.
    • Learning PHP, Part 2(Tyler Anderson 및 Nicholas Chase, developerWorks, 2002년 6월): 파일 업로드뿐 아니라, XML 데이터의 작성, 조작 및 읽기 방법을 학습할 수 있다.
    • Learning PHP, Part 3(Tyler Anderson 및 Nicholas Chase, developerWorks, 2002년 7월): 파일을 스트리밍하고 오브젝트 메소드 및 예외를 작성하는 방법을 학습할 수 있다.

  • PHP project resources: PHP 개발자를 위한 광범위한 developerWorks 참고자료를 확인할 수 있다.

  • My developerWorks: developerWorks와 관련된 경험을 개인화할 수 있다.

  • IBM XML 인증: XML 및 관련 기술에 대한 IBM 인증 개발자가 되는 방법을 찾아볼 수 있다.

  • XML Technical library: developerWorks XML 영역에서 다양한 기술 관련 기사와 팁, 튜토리얼, 표준 및 IBM Redbook을 볼 수 있다.

  • developerWorks 기술 행사 및 웹 캐스트: 이들 세션에 참가하여 최신 기술에 대한 정보를 얻을 수 있다.

  • developerWorks on Twitter: 지금 바로 developerWorks의 트위터에 참가하자.

  • developerWorks 팟캐스트: 소프트웨어 개발자의 흥미로운 인터뷰와 토론을 확인할 수 있다.

제품 및 기술 얻기

토론

필자소개

Ben Werdmuller is a web strategist and developer who specializes in open source platforms. He co-founded and was the technical lead for Elgg, an open source social networking framework. Ben blogs regularly at http://benwerd.com/.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=XML, 오픈 소스
ArticleID=503614
ArticleTitle=소셜 오브젝트를 Atom 형식으로 표현
publish-date=06152010
author1-email=ben@benwerd.com
author1-email-cc=

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.