|
첫 번째 단계는 가장 간단하다. twitter.com에서 계정을 작성하면 된다. 필자가 데모 목적으로 tweet_task라는 계정을 작성해 두었으므로 http://twitter.com/tweet_task에서 최신 상태 업데이트를 볼 수 있다.
Twitter 계정의 상태를 업데이트하는 데 사용되는 모든 클라이언트 애플리케이션과 마찬가지로 이 기사에서 빌드할 애플리케이션도 먼저 Twitter에 등록해야만 사용할 수 있다. Twitter OAuth 클라이언트 등록 페이지(http://twitter.com/oauth_clients/new)를 열고 양식을 완료한다(그림 1 참조).
그림 1. Twitter에 애플리케이션 등록하기
양식의 Application Icon 필드를 사용하여 클라이언트 애플리케이션의 아이콘으로 사용할 이미지를 입력하거나 찾아서 선택할 수 있으며, 이 이미지는 700k 이하의 GIF, JPG 또는 PNG 파일이어야 한다. Application Name에는 twitter라는 단어가 포함되지 않은 이름이라면 자유롭게 사용할 수 있다. (이 클라이언트를 사용하는 업데이트에 클라이언트 이름이 하위 제목으로 포함될 것이라는 점에 유의하자. 필자가 이 기사의 데모를 위해 tweet_task_client라는 이름을 선택했기 때문에 모든 상태에 via tweet_task_client라는 하위 제목이 표시된다.) Description 필드에 애플리케이션에 대한 간략한 설명을 입력한다. Application Website 필드는 비워둘 수 없으므로 애플리케이션의 URL을 입력한다. (작동하지 않는 URL이라도 입력해야 한다.) Organization 필드 및 이와 연관된 Website 필드는 선택사항이다. Application Type으로 Client를 선택하고 Read & Write를 Default Access Type으로 선택한다. 그런 다음 Use Twitter for login: 항목에서 Yes, use Twitter for login을 선택한다.
애플리케이션이 등록되면 컨슈머 키 및 컨슈머 시크릿 토큰이 포함된 화면이 표시된다. 이러한 정보를 기록해 두고 안전하게 보관한다.
Twitter4J는 내장 OAuth 지원을 제공하는 비공식 오픈 소스 Java 라이브러리이다. Twitter4J 웹 사이트(참고자료 참조)에서 최신 릴리스를 다운로드한 후 클래스 경로에 추가한다.
클라이언트가 계정의 상태를 업데이트할 수 있으려면 해당 계정에서 먼저 클라이언트에게 업데이트 권한을 부여해야 한다. 목록 1은 계정에 대한 애플리케이션의 권한 부여 URL을 생성하는 간단한 프로그램이다.
목록 1. Twitter4JRegister.java
import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.http.AccessToken; import twitter4j.http.RequestToken; public class Twitter4JRegister { public static void main(String args[]) throws Exception { Twitter twitter = new TwitterFactory().getInstance(); twitter.setOAuthConsumer("consumer key", "consumer secret"); RequestToken requestToken = twitter.getOAuthRequestToken(); AccessToken accessToken = null; BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(System.in)); while (null == accessToken) { System.out .println("Open the following URL and grant access to your account:"); System.out.println(requestToken.getAuthorizationURL()); System.out .print("Enter the generated PIN:"); String pin = bufferedReader.readLine(); try { if (pin.length() > 0) { accessToken = twitter .getOAuthAccessToken(requestToken, pin); } else { accessToken = twitter.getOAuthAccessToken(); } } catch (TwitterException e) { if (401 == e.getStatusCode()) { System.out.println("Unable to get the access token."); } else { e.printStackTrace(); } } } storeAccessToken(accessToken); Status status = twitter.updateStatus("Client installed"); System.out.println("Successfully updated the status to [" + status.getText() + "]."); System.exit(0); } private static void storeAccessToken(AccessToken accessToken) { try { FileOutputStream fileOutputStream = new FileOutputStream( "token.txt"); ObjectOutputStream objectOutputStream = new ObjectOutputStream( fileOutputStream); objectOutputStream.writeObject(accessToken.getToken()); objectOutputStream.flush(); fileOutputStream = new FileOutputStream("tokenSecret.txt"); objectOutputStream = new ObjectOutputStream(fileOutputStream); objectOutputStream.writeObject(accessToken.getTokenSecret()); objectOutputStream.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } |
목록 1의 코드를 Twitter4JRegister.java라는 이름의 파일에 입력하고 컨슈머 키 및 컨슈머 시크릿 자리 표시자를 사용자의 키 및 시크릿으로 바꾼 후 코드를 컴파일한다. 코드를 실행한 후 생성된 URL을 브라우저의 주소 표시줄에 입력한다. 앞에서 작성한 Twitter 계정의 사용자 이름과 비밀번호를 사용하여 로그인한다. PIN이 생성되고 표시되면 이 PIN을 콘솔에 입력한다.
토큰 및 토큰 시크릿 오브젝트는 token.txt와 tokenSecret.txt라는 두 개의 파일로 직렬화된다. 이러한 오브젝트는 이후 모든 트랜잭션에서 클라이언트가 계정에 대한 인증을 받을 때 사용된다. 이러한 파일의 백업을 저장해 둔다. 파일이 삭제된 경우에는 새 URL을 생성하는 프로그램을 다시 실행하여 파일을 다시 작성해야 한다. 계정의 사용자 이름 및 비밀번호는 코드에서 전혀 사용되지 않는다는 점에 유의한다. 토큰 및 토큰 시크릿은 데이터베이스나 레지스트리를 비롯한 원하는 위치에 저장할 수 있으며, 파일로 직렬화하는 방법은 이 기사에서 추천하는 하나의 제안이다.
이제 사용자에게 제공할 토큰이 마련되었으므로 토큰의 사용을 테스트하고 계정의 상태를 업데이트하는 클라이언트 애플리케이션을 작성할 수 있다. 목록 2에서는 Twitter4JUpdate
라는 클라이언트 애플리케이션을 보여 준다.
목록 2. Twitter4JUpdate.java
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterFactory; import twitter4j.http.AccessToken; public class Twitter4JUpdate { public static void main(String args[]) throws Exception { TwitterFactory factory = new TwitterFactory(); AccessToken accessToken = loadAccessToken(); Twitter twitter = factory.getOAuthAuthorizedInstance("consumer key", "consumer secret", accessToken); Status status = twitter.updateStatus("Client registered"); System.out.println("Successfully updated the status to [" + status.getText() + "]."); System.exit(0); } private static AccessToken loadAccessToken() { String token = null; String tokenSecret = null; try { FileInputStream fileInputStream = new FileInputStream("token.txt"); ObjectInputStream objectInputStream = new ObjectInputStream( fileInputStream); token = (String) objectInputStream.readObject(); fileInputStream = new FileInputStream("tokenSecret.txt"); objectInputStream = new ObjectInputStream(fileInputStream); tokenSecret = (String) objectInputStream.readObject(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new AccessToken(token, tokenSecret); } } |
앞에서와 마찬가지로 목록 2의 컨슈머 키 및 컨슈머 시크릿을 사용자의 컨슈머 키 및 컨슈머 시크릿으로 바꾼다. 토큰 및 토큰 시크릿 오브젝트를 제안된 파일 이외의 위치에 저장해 둔 경우에는 해당 오브젝트를 검색하는 loadAccessToken()
메소드를 다시 작성해야 한다.
Twitter4JUpdate.java를 컴파일한다. 계정의 상태가 올바르게 업데이트되는지 확인하기 위해 표시하려는 상태 업데이트를 사용하여 다음 명령을 실행한다.
java Twitter4JUpdate update |
twitter.com에서 입력한 업데이트가 올바르게 표시되는지 확인한다.
계정 상태를 업데이트하는 사용자 정의 Ant 태스크 작성하기
사용자 정의 Ant 태스크는 org.apache.tools.ant.Task
태스크를 확장한 다음 execute()
메소드를 대체하는 간단한 방법을 통해 작성할 수 있다(참고자료 참조). 모든 런타임 변수는 적절한 set 및 get 메소드가 포함된 private 클래스 속성으로 정의된다. 명령행 매개변수를 사용하여 계정의 상태를 설정하는 대신 빌드 파일에 문자열 값을 설정하면 태스크에서 이 문자열 값을 사용하여 상태를 업데이트하게 된다.
목록 3의 코드를 TweetTask.java라는 이름의 파일에 입력한 후 앞에서와 같이 컨슈머 키 및 컨슈머 시크릿 자리 표시자를 사용자의 키 및 시크릿으로 바꾼다.
목록 3. TweetTask.java
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import org.apache.tools.ant.Task; import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.http.AccessToken; public class TweetTask extends Task { private String status; public void execute() { try { TwitterFactory factory = new TwitterFactory(); AccessToken accessToken = loadAccessToken(); Twitter twitter = factory.getOAuthAuthorizedInstance( "consumer key", "consumer secret", accessToken); Status updatedStatus = twitter.updateStatus(status); System.out.println("Updated status to: " + updatedStatus.getText()); } catch (TwitterException e) { e.printStackTrace(); } } private AccessToken loadAccessToken() { String token = null; String tokenSecret = null; try { FileInputStream fileInputStream = new FileInputStream( "accessToken.txt"); ObjectInputStream objectInputStream = new ObjectInputStream( fileInputStream); token = (String) objectInputStream.readObject(); fileInputStream = new FileInputStream("accessTokenSecret.txt"); objectInputStream = new ObjectInputStream(fileInputStream); tokenSecret = (String) objectInputStream.readObject(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new AccessToken(token, tokenSecret); } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } |
목록 3에서는 목록 2의 main()
메소드를 태스크의 execute()
메소드로 리팩토링했으며, loadAccessToken()
메소드의 경우에는 static
한정자를 제거하여 클래스 메소드에서 인스턴스 메소드로 변경했다. (토큰 및 토큰 시크릿 오브젝트를 제안된 파일 이외의 위치에 저장해 둔 경우에는 목록 2에서 사용한 동일한 메소드를 다시 사용한다.) TweetTask.java를 컴파일한다.
이제 목록 4와 같은 Ant build.xml 파일을 작성하여 사용자 정의 TweetTask
클래스를 테스트한다.
목록 4. build.xml
<?xml version="1.0" encoding="UTF-8"?> <project default="default" basedir="."> <taskdef name="tweet" classname="TweetTask" classpath="Twitter4J Jar file" /> <target name="default"> <tstamp> <format property="build.completed" pattern="HH:mm:ss z dd-MM-yyyy" /> </tstamp> <tweet status="build completed at ${build.completed}" /> </target> </project> |
Twitter4J 웹 사이트에서 다운로드한 동일한 JAR 파일이 사용자 정의 태스크의 클래스 경로에 추가되었다. classpath
속성의 값을 다운로드한 파일의 이름으로 바꾼다. TweetTask.java 파일을 패키지(예: mypackage.customtasks
)에 배치한 경우에는 classname
속성에 이 사항이 반영되어야 한다. 이 기사에서 제안한 방법에 따라서 토큰 및 토큰 시크릿 오브젝트를 로컬 파일에 직렬화한 경우에는 token.txt 및 tokenSecret.txt 파일이 이 build.xml 파일과 같은 디렉토리에 있어야만 빌드를 완료할 수 있다.
Ant를 사용하여 build.xml 파일을 실행한다. 실행이 완료되면 Twitter 계정을 검사하여 사용자 정의 태스크가 계정의 상태를 build completed at 시간 날짜 형식으로 올바르게 업데이트했는지 확인한다(그림 2 참조).
그림 2. Twitter에 게시된 빌드 완료 업데이트
이제 프로젝트의 모든 관계자가 Twitter 피드를 팔로우하여 빌드 완료 시기를 확인할 수 있다.
이 기사에서는 Twitter의 OAuth 메커니즘을 사용하여 클라이언트 Java 프로그램에서 계정의 상태를 업데이트하는 방법을 살펴보았다. 오픈 소스 프로젝트의 빌드 엔지니어가 이 기술을 활용하면 빌드와 관련된 메일링 목록을 관리 및 업데이트하는 부차적인 업무에 시간을 낭비하지 않아도 된다. 개발자, 테스터를 포함하여 프로젝트에 관심이 있는 모든 사람이 Twitter 계정을 구독(또는 팔로우)하여 빌드 완료 즉시 통보를 받을 수 있다. twitter.com 또는 프로젝트 계정이 정상적으로 작동하지 않을 경우에는 메일 태스크를 대체 방법으로 사용하여 사용자에게 빌드 상태를 알려줄 수 있다.
지난 4년 동안 Twitter의 사용량은 급속도로 성장했으며, 그 뒤를 이어 status.net, Jaiku, NotePub 등의 여러 마이크로블로깅 대안도 등장하고 있다. 이 기사의 업데이트 태스크를 확장하면 이러한 서비스를 활용할 수 있을 뿐만 아니라 프로젝트의 Facebook 상태를 업데이트할 수도 있다.