이바닥이 원래 그래
EBADAC - OOPARTS : Out Of Place Articles.
Archive for February, 2007
February 28, 2007 at 12:04 am · Filed under WebPlan, WebStandard, WorldWideWoops
OpenID의 목적은 새로운 Identity를 보장하기 위함이지, 블로그에 익명로그인을 위해 존재하는 것은 아닙니다.
특히 Simple Registration Extension을 지원하지 않고 프로필도 제공하지 않는 단지 Auth만을 제공하는 OpenID 서비스라면 더욱 그렇죠.
뭐 SRE를 반드시 지원해야 하는 문제는 아니고…
블로그에 OpenID를 이용할 수 있도록 해놓고 지금까지 두어개의 OpenID 커멘트가 달렸는데요…
불행히도(?) OpenID URL 중, myid.net은 email주소를 제외하고는 어떠한 정보도 알려주지 않습니다. 이래서야 URL이 있어도 그림의 떡.
어차피 블로그를 쓰시는 분이라면, 자신의 블로그 URL을 delegate해서 자신의 블로그로 연결시킬 수도 있습니다. 자신은 숨기고 myid.net의 인증만을 들이미는 것은 왠지 기분이 나빠져요. 꼭 인적정보를 까발리라는 게 아니라 자신의 블로그 URL로 delegate해주는 쪽이 좋지 않나 하는 말씀입니다.
그러니까 저는, yong.myid.net이 아니라, 블로거로서의 yy님을 마주대하고 싶은거라는거죠. 똑같은 OpenID 인증을 하시더라도, http://yong.myid.net 보다 http://janice.kaist.ac.kr/~gomeisa/blog를 써주시는 것이 훨씬 좋습니다. (OpenID를 이용하시는 분이 적어 부득이 yy님을 예로 들었습니다.)
제 OpenID는 eouia.openid.ne.jp도, eouia.myid.net도, eouia.openid.com도 아니라, http://dnzin.com/cunnningweb 입니다.
February 27, 2007 at 6:46 pm · Filed under WebPlan, WorldWideWoops
웹 2.0의 본질이 무엇인가 하는 이야기는 주제와 동떨어지므로 여기에서는 과감히 생략. 이 글에서 이야기하고자 하는 바는 소위 추천글사태로 모듬지을 수 있는 최근의 올블로그-를 화두로 ‘선한 사용자의 참여’에 대한 오해, 그리고 진화적으로 안정된 web 2.0에 대해 이야기해보도록 하겠습니다.
몇가지 생각해볼 화두가 있겠는데요,
첫번째는 ‘collaborate’와 ‘collective intelligence’는 같은 개념은 아니라는 것입니다.
올블의 추천 시스템은 전형적인 ‘collaborate’의 구현이라고 말할 수도 있을 것입니다. 여러 사람이 자원(로그인, 클릭에 소요되는 노력과 시간)을 조금씩 써서 공통의 목표(읽을만한 블로그 찾기)를 달성하는 것은 일견 꽤나 멋지고 바람직한 일처럼 보입니다.
그러나, collaborate의 성공을 위해서는 구성원 전체가 공통의 목표에 대한 동의외에도, 실질적으로 그 행위에 대한 결과가 노동을 투입한 당사자에게도 혜택이 돌아가야 합니다. 올블의 추천시스템은 이 부분이 빠져있죠. 애써서 남의 글에 ‘추천’을 해준들 나에게 무슨 소용이 있겠습니까.
남의 글에 ‘추천’하는 행위는 직접적으로,
1) 나의 한정된 노력과 시간과 관심이라는 자원을 소비하고,
2) 타인의 글을 ‘추천’함으로써, 올블메인이라는 한정된 재화를 놓고 벌이는 경쟁에서 자신의 글이 불리해집니다.
3) 게다가 자기 혼자 ‘추천’하고 다른 이가 동참하지 않는다면 그 불리함은 더 커지죠.
이렇게 ‘추천’하는 개인에게 불리한 시스템을 놓고 왜 ‘추천 안하냐’, ‘추천을 열심히 하자’라고 주장하는 것은 완전히 넌센스라고 해도 다름없지요.
게다가 실제로는 ‘모두가 추천을 열심히 누르는 착한 사람들’이 된다 해서 이 시스템이 잘 돌아갈 것이냐.. 요건 또 다른 이야기거리가 됩니다.
즉, ‘좋은 글 발굴’이라는 ‘공동의 선’을 ‘집단지성’으로 해결할 수 있지 않느냐는 대의명분을 가지고, 이른바 ‘선한 사람 되기’를 요구하는 목소리도 있는데요. 이른바 ‘collective intelligence’는 개인의 ‘의지’가 들어가는 순간부터 왜곡되기 시작합니다. 따라서 collective intelligence를 구현하기 위해서는 무엇보다도 사용자의 ‘의지’를 차단하는 과정이 필요합니다. 혹은, 사용자의 ‘의지’를 이겨낼 수 있는 정교한 시스템이 뒷받침되거나요.
Google의 PageRank는 collective intelligence의 대표적인 구현이라고 할 수 있습니다. ‘어디에서 얼마나 참조하고 있는가’로 랭크를 매기는 이 방법은 ‘의지’를 이용해서 조작하기에는 꽤 비싼 대가를 치뤄야하기 때문이죠. ‘참조’에는 비용이 수반되고, 실질적으로 ‘의도’가 아닌 ‘필연’에 의해 이루어지니까요. (그럼에도 불구하고 특화된 SEO를 통해 조작을 하고 있긴 합니다만.)
그에 비하면 올블의 추천 시스템은, 추천 클릭이 싼 비용은 아니라쳐도, 그렇다고 개인의 의지를 무력화시킬 정도로 엄청나게 비싼 비용도 아니지요. 이런 경우 집단지성은 발현되기 어렵습니다. (집단감성은 발현되기 쉽지만.)
collaborate이자 collective intelligence의 대표격인 wikipedia조차 사실상은 끝없는 노이즈와의 싸움이라 할 수 있지요. 그나마 그것이 잘 돌아가는 이유는,
1) 강력한 감시자가 있다.
2) 참여에 대한 자기만족이 크고 실질적으로 공동의 목표에 이바지하고 있다는 자각을 현실적으로 체감할 수 있다.
그러나 올블의 추천 시스템은 추천버튼 하나 누른다고 뭐가 엄청나게 보람찬 일을 하고 있다거나 추천에 대한 피드백이 즉각 돌아오나요? 이 문제를 해결하지 않는 이상 ‘열심히 추천클릭해보아요’라는 구호는 그냥 빈 구호가 될 뿐이지요.
어찌되었건 이 모든 것을 차치하고라도, 모두가 착한 사람이 되면 되지 않겠냐…는 건, 불가능의 여부를 떠나서, 별로 안정적이지도 못한 전략입니다.
생물학 이야기를 잠깐 해야겠습니다. 교양과정으로 ‘이기적 유전자’를 읽어보신 분은 아시겠지만, 소위 ESS(Evolutionary Stable Strategy)를 이 경우에 집어넣으면 딱 맞는 이야기입니다.
“선심파”와 “기회주의파”가 있을 때, 얼핏 생각하기에는 구성원 전원이 “선심파”일 때 공동체의 이익(과 구성원 개인의 이익)이 가장 크므로, 모두가 “선심파”가 되도록 진화할 것처럼 생각하지만, 실제로는 “선심파” : “기회주의파”의 비율이 특정한 상태가 되도록 진화가 이루어지게 되죠.(정확한 비율은 선심의 행위의 비용과 이득, 기회주의 행동의 비용과 이득에 따라 결정됩니다.)
올블의 경우에는 선심의 행위의 이익[좋은 글에 추천을 해준다]과 비용[로그인과 클릭], 그리고 기회주의행위의 이익[좋은 글로 추천된 것을 그냥 수고 없이 본다]과 비용[아무것도 안한다]를 따져보면, 기회주의 쪽이 너무 많이 이익이죠. 즉 구조상 선심파보다 기회주의파가 더 많은 상태가 더 stable한 상태가 되는 겁니다.
그런 걸 아무리 “착한 사람이 됩시다” 캠페인을 해봤자 애초에 달성될 수 없는 목표라는 거지요.
그렇다면, “착한 사람의 참여”는 결국 꿈같은 이야기일 뿐이냐….
그건 아니죠.
다만, 그를 위해서는 “착한 사람의 참여는 그 착한 사람에게 더 많은 이익을 돌려주는 시스템”이 되어야 한다는거죠.
물론 저는 추천이나 평점 시스템 자체를 신뢰하지 않기에(애시당초, 누군지도 모르는 다른 이들이 추천하고 주는 평점 자체가 어떻게 나에게 이익이 될 수 있을 지 신뢰할 수 없기 때문에), 추천등 왜곡될 가능성이 있는 시스템의 채택 자체를 반대하는 편입니다만… 그래도 꼭 추천시스템을 유지하고 싶다면… 간단하다면 간단한 해결책이 있긴 하죠.
“클릭하는 행위가 실질적으로 나에게 도움을 주어야 한다”가 되어야겠습니다. 뭐.. 돈으로 보상… 할 수도 있겠지요. 좋은 글을 많이 추천한 분들께 선물을 드려요 같은. (뻔한 부작용이 벌써 예상되긴 합니다.)
좀 더 나은 대안은, 예를 들어 “스크랩을 위해 클릭하면 자동으로 추천이 된다.” 같은 시스템이 될 수도 있겠죠. 자신의 필요에 의해 뭔가 액션을 - 당연히 행해야하는 - 취하면 그 부수적인 효과로 추천에 상응하는 통계를 잡을 수 있다거나 하는거죠. 꼭 스크랩이라는 소리가 아니라. 예를 들자면, “개인별 올블로그 오늘의 좋은 링크 북마크모음”이라든가, “해당 글에 대한 원격 블로깅 지원” 같은 실질적인 개인별 이익으로 보상이 있어야 한다는거죠.
그 보상이 크면 클 수록 “선심파” - 이쯤 되면 “이기적 블로거”라고 말할 수도 있겠습니다. - 가 유리해지는 비율로 안정되는 것이지요.
간단히 이야기하자면, 로그인하고 추천클릭해봤자 나한테 돌아오는 거 없으니, 그럴만한 보상 체계를 제시하는 쪽이 좋다는 충고입니다. 웹 2.0의 한계도 아니고, 사람들이 사악해서도 아니고, 그저 기획의 미비일 뿐이지요.
February 27, 2007 at 2:33 pm · Filed under WebStandard
[actionscript]
if (Accessibility.isActive()) {
_root.selfVoicing.play();
}
[/actionscript]
From : Detecting Screen Readers via Semantic Flash: Slippery When Wet (ALA)
그러나, 국산 스크린리더로는 안된다는 것…
조금 다른 이야기인데, 접근성을 위해서는 운영체제의 지원이 필수인데, 국가에서 지정해서 공공기관에 납품되는 PC에 들어가는 운영체제의 필수요건으로 스크린리더를 포함하도록 하는 게 좋지 않을까?
February 26, 2007 at 1:51 pm · Filed under WebDevelopment
가끔 헷갈렸는데 정리해본다.
1. URL로 특정된 HTML type 문서가 로딩된다.
2. HTML이 파싱된다.
3. link, script로 연결된 외부 스타일쉬트와 스크립트가 로딩된다.
4. 이상의 내용을 토대로 DOM이 만들어진다.(스크립트도 실행)
5. 만들어진 DOM을 브라우저에서 사용자에게 출력한다.
6. 이미지 및 외부 컨텐트가 로딩된다.
ps. window.onload 이벤트는 어느 시점에서 발생하는 걸까?
상식적으로 생각해보면 6번? 5번?
February 25, 2007 at 8:16 pm · Filed under WorldWideWoops
이번 윈터마켓은 사실 은퇴 등을 제외하고는 눈에 띄는 대박 이적은 없었던 것 같습니다. 호나우도가 재기에 성공할 수 있을 지 정도?
C.호날도가 이적할 것인지 아닌지를 놓고 설왕설래했지만, 결국 맨유에 남았지요. 시즌 종료후에는 모르겠습니다만.
어찌 되었건, 첼시나 맨유, 바르샤, 레알(레알은 요즘 좀 부실해졌지만.) 등 우주방위대급의 스쿼드를 보유하고 있는 팀으로 결정되겠죠. 이적료만 해도 장난이 아닐테니까요.
프로 축구팀의 목적은 사실, “흑자”입니다. 세미프로나, 아마라면 모르겠지만.
첼시나 레알같은 갈라티코급 운영을 하는 이유는, 단지 구단주가 부자 축구광이라서가 아니라, 더 좋은 선수를 가지고 있음으로써 더 나은 성적과 더 나은 마케팅을 할 수 있기 때문이지요. 그러니까 FootballManager 게임처럼 선수사모으기는 취미가 아니라, 세밀한 경영전략이라고 해야겠지요.
뭐, 그렇다면 챔피온스 리그는 그런 우주방위대들이 돌아가며 우승해야 정상이겠습니다만, 꼭 슈퍼스타들이 많다고 경기에 연전연승하는 건 아니지요. 근 20년간의 전적을 보자면 포르투라든가, 도르트문트, Ajax, 즈베즈다 같은 팀들이 깜짝 우승을 하는 경우들이 있었으니까요.
우주방위대에는 실상 단점도 있어서, 다른 팀같았으면 붙박이 주전이었을만한 선수도 기라성같은 스타들 틈에서 벤치나 2군으로 밀려나는 경우도 종종 있지요. 팀 입장에서야 다른 팀에 주느니 데리고 있겠다일 수도 있겠고, 좋은 값에 팔아버릴 요량일지도 모르겠으나, 당사자는 정말 피가 마를 것 같아요. 아, 하긴, 맨유의 2군벤치라도 지키고 있으면 영광이라고 생각하는 선수가 있을지도 모르죠. ^_^
왜 엉뚱한 축구 이야기를 하는가하면…
회사에서 구인 중인데요, 공교롭게도 괜찮은 인재다 싶어 컨택하는 족족, 특정한 모모 회사에 지원중… 이라고들 하시네요. ㅎ 국내 IT인력의 싹쓸이 중인가요? Google이 한동안 한국 개발자들 시장을 들쑤셔놓더니, NHN은 200명을 한번에 뽑고 있다죠? 이번에 어떤 곳은 정말 IT계의 우주방위대를 만들려나보다 싶을 정도로 파격적인 조건과 대우로 구인중이더군요.
한편으로는 부럽다는 생각도 들면서, 한편으로는 또 심하다는 생각도 들더라구요. 농담삼아 O신드롬이라고 회사내에서는 일컫고 있습니다.
모 벤처 경영자분께, 어떻게 좋은 개발 인력을 이렇게 쉽게 모으셨나요? 라고 물었더니 이렇게 답변하셨더라죠.
“넓직한 책상에 듀얼 모니터 놔두니까 서로 오겠다고 하던데요?”
뭐, 바르샤나 레알같은 회사도 있고, PSV나 레딩같은 회사도 있는 법이지요. C.호날도를 사오지는 못하지만, 토탈사커쯤은 해낼 수 있지 않을까… 하는 이야기를 회사분들이랑 나눠봤습니다.
February 23, 2007 at 4:03 am · Filed under WebDevelopment, WebStandard
이번에는 Consumer 구현입니다.
지난번에 이야기한 건 Provider편이었죠? 많은 부분 Provider와 겹치므로 슬쩍 새 창으로 띄워서 컨닝해가면서 따라오세요.
역시 마찬가지로 PHP 4.3.0 이상, bcmath나 gmp가 설치되어 있다고 가정하고, MySQL은 InnoDB를 사용합니다.
또한, 이미 OpenID Library가 설치되어있고 경로에 추가되어있다고 가정합니다.
Consumer편은 더 쉽습니다. 설명할 게 없을 정도.
일단, 세션스토어로 MySQL을 사용할 예정이니 Provider편과 마찬가지로 MySQLStore 객체를 만듭시다.
[php]
$connection = DB::connect($dsn);
$store = new Auth_OpenID_MySQLStore($connection, ’setting’, ‘association’, ‘nonce’);
//$store->createTables();
[/php]
물론, 최초 실행시에는 createTables()를 해줘야합니다.
만약 MySQL대신 다른 Store를 이용하고 싶다면 다른 Store 클래스로 객체를 만드시면 됩니다. Factory 패턴이기 때문에 따로 신경안써줘도 되는건 OO 공부하신 분들이면 다 아실테지요.
[php]
$store = new Auth_OpenID_FileStore($store_path);
[/php]
예를 들어 파일패스를 스토어로 쓰고 싶다면 이렇게 해주면 된다는 말씀.
이제 만들어진 스토어 객체로 Consumer 객체를 만듭시다.
[php]
$consumer = new Auth_OpenID_Consumer($store);
[/php]
일반적인 시나리오에서는, 사용자는 Consumer 사이트에 와서 자신의 OpenID를 Form으로 입력하겠죠. 어쨌거나 인증하고자 하는 OpenID값을 Consumer 객체에 던져주기만 하면 됩니다.
[php]
$openid = $_POST[’login_openid’]; // 뭐, 예를 들자면.. 이런 식이겠죠:)
$auth_request = $consumer->begin($openid); //오픈아이디 서버와 association을 시도하고 그 결과를 돌려줍니다.
if($auth_request) {
//success;
} else {
//fail;
echo “Authentication Fail”;
}
[/php]
$auth_request가 true이면 정상적으로 association이 이루어졌다는 뜻입니다. 만약 false라면 인증에 실패했다는 메시지를 사용자에게 보여주면 되겠죠?
association이 성공적으로 이루어졌다면 이제, 해당 openid에 대한 인증을 시도하면 됩니다.
[php]
$trust_root = ‘http://consumer.com’;
$process_url = ‘http://consumer.com/afterAuth’;
$redirect_url = $auth_request->redirectURL($trust_root, $process_url);
header(”Location: “.$redirect_url);
[/php]
$trust_root는 Provider에게 이 인증시도가 어떤 Consumer로부터 시도된 것인지 신뢰여부를 판단하게 해주는 일종의 키값이 됩니다. 완벽하진 않지만, trustroot와 인증시도 도메인간에 도메인이 다를 경우 피싱시도로 파악해서 인증을 거부하거나 할 수 있도록 하지요. 반대로, trustroot로 인정된 도메인의 경우에는 따로 지정하지 않는 한, 인증을 자동보장한다거나 하는데 쓰일 수 있겠지요.
$process_url은 OpenID Provider가 인증을 처리하고 난 후 그 결과값을 되돌려받을 Consumer 사이트의 url입니다.
위의 코드가 실행되면, $redirect_url이 되돌려집니다. $redirect_url은 Provider의 인증처리 페이지에 인증 Request를 Get 메쏘드로 전달하는 형태이지요. 즉, 이렇게 만들어진 $redirect_url로 redirect시켜주기만 하면 됩니다.
만약 단순한 인증으로 끝나지 않고, Simple Registration Extension를 이용해 사용자 정보를 얻어오길 원한다면
[php]
$auth_request->addExtensionArg(’sreg’, 요구필드타입, 요구필드이름리스트);
[/php]
를 redirecURL메쏘드 실행전에 실행시켜주면 됩니다.
요구필드타입은 required/optional이구요, 비록 required라고 해도 Provider에서 반드시 정보를 제공한다는 보장은 없으니(Simple Registration Extension를 지원하지 않거나, 사용자가 정보제공을 거부하거나…), required로 요구한 필드의 되돌아오는 값이 없다해도 에러는 아니라는 점.
그외에, policy_url을 이용해, 어떤 필드들을 왜 요구하는지 설명을 알려줄 수도 있지요.
요구필드로 현재 Simple Registration Extension 에 정의된 필드는,
nickname, email, fullname, dob, gender, postcode, country, language, timezone
의 8 가지인데요, 주의할 점은 각각의 필드의 리턴값은 RFC와 ISO에 정의된 표준 스펙이라는 겁니다. 그러니까, country를 알려달라고 요구해도, “Korea”라든가 “대한민국”같은 형식으로 돌아오지는 않는다는 거지요.
각각의 필드에 대한 스펙 및 Simple Registration Extension에 관한 더 자세한 설명은,
여기를 참고하세요.
에.. 하여튼간에, 실제로 Simple Registration Extension을 이용하려면,
[php]
$auth_request->addExtensionArg(’sreg’, ‘policy_url’, ‘http://consumer.com/policy’);
$auth_request->addExtensionArg(’sreg’, ‘required’, ‘email’);
$auth_request->addExtensionArg(’sreg’, ‘optional’, ‘nickname’);
$auth_request->addExtensionArg(’sreg’, ‘optional’, ‘gender’);
$redirect_url = $auth_request->redirectURL($trust_root, $process_url);
header(”Location: “.$redirect_url);
[/php]
처럼 하면 된다는 말씀.
이제 인증 요청이 끝났습니다. redirect를 통해 Provider에게 GET 메쏘드로 인증요청을 했으니 나머지는 Provider와 사용자간에 나름의 과정을 통해 인증여부가 회신되겠지요?
전에 지정해둔 $process_url로 회신이 돌아옵니다.
다음은 $process_url에서 GET으로 돌아온 회신에 대한 처리부분입니다.
[php]
$response = $consumer->complete($_GET);
switch($response->status) {
case Auth_OpenID_CANCEL :
// 사용자가 인증을 취소했을 때의 처리
break;
case Auth_OpenID_FAILURE :
// 무언가의 문제로 인해 인증이 실패했을 때의 처리(인증을 요구한 openid가 없다든가..)
break;
case Auth_OpenID_SUCCESS :
// 인증성공!!
break;
}
[/php]
인증은 모두 끝났습니다. 간단하죠? 
만약 Simple Registration Extension을 사용했을 경우, 요구했던 필드값들을 구해야겠죠?
[php]
$sreg = $response->extensionResponse(’sreg’);
echo $sreg[’email’];
[/php]
이걸로 진짜 끝.
간단하죠?
그러니까 OpenID 지원하는게 뭐 대단한 것도 아닌거에요. 무슨 코어모듈을 고쳐야 한다거나 하는 작업이 있을리도 없으니까, Consumer 지원하는 건 어려운 일이 아니에요. 물론 Provider가 되려면 좀 더 복잡한 작업이 필요하긴 합니다만, Provider는 많을 필요도 없고요.
OpenID의 의의를 이해하신다면, 별 특징이나 기능도 없는 Provider가 늘어나는 건 그저 사용자들에게 불편만 주고 OpenID의 장점을 전혀 못살리는 멍청한 짓이기도 하지요.
delegation을 이용하면 어떤 Provider를 쓰든 상관없는 거니까요. (오히려 Simple Registration Extension을 지원안하는 Provider라면 편의성이 떨어지는 셈이니 이용에 고민을 해봐야겠지요. 물론 보안문제가 아직 완벽하게 해결된 것은 아니므로 SRE를 믿느냐는 좀 다른 이야기긴 합니다만.)
국내에서 OpenID를 이야기하는 사람들이 많아지긴 했습니다만… 뭐랄까, 실제 개발자들에게는 그런 뜬구름잡는 이야기보다는 간단한 샘플소스에 대한 설명 하나가 더 필요한 시점아닐까 하는 생각이 드네요. 정말로 OpenID를 널리 퍼뜨리게 하고 싶다면요. 혹은, 그냥 기술적 우위를 뽐내는 걸로 만족하는 거라면 또 다른 이야기겠지만요.
February 21, 2007 at 8:44 pm · Filed under WebDevelopment, WebStandard
약속했던 대로, OpenID 구현에 대한 이야기입니다.
이번은 JanRain의 라이브러리를 이용한 초간단 OpenID Provider 제작편입니다.
JanRain의 라이브러리는 원래 Python으로 구현되었습니다만, 현재는 여러 언어로 포팅되어있지요. Ruby, Perl, PHP, DotNet, Java, ColdFusion 등이 가능합니다.
여기에서는 PHP Library를 이용하겠습니다.
주의 : php 4.3 이상. Bcmath, GMP 패키지 등이 설치되어 있어야 합니다.
MySQL의 경우에는 innoDB를 사용합니다.
1) 설치
Pear Installer가 지원된다면
pear install http://www.openidenabled.com/resources/downloads/php-openid/pear/Auth_OpenID-1.2.1.tgz
로 설치하면 간단 끝.
만약 경로를 따로 제어하고 싶다거나, 혹은 Pear를 쓸 수 없는 환경이라면, 그냥 다운로드 받아서 적당한 곳에 풀어주면 됩니다.
2) 구조
압축을 풀면 여러가지 디렉토리가 있는데, 실제적으로 중요한 곳은 /Auth입니다. 이 안에, OpenID 컨슈머와 프로바이더 모두를 위한 클래스들이 들어있습니다.
실제로 PHP4로 제작되어 있기 때문에 클래스 내부 코드들이 완벽한 OO 스타일을 유지하고 있다고 말하기는 어렵습니다. 코드들은 거의 미로수준. 게다가, 은근히 도큐먼트가 부실해서…
3) 구현
OpenID는 프로바이더와 컨슈머 사이에서 키를 발급하고 조회하는 메커니즘으로 운영됩니다. 발급된 키를 관리하는 방법은 여러가지가 있는데, 예를 들어, 메모리 세션을 이용하거나, 파일 세션, 혹은 DB 세션등을 이용하기도 하지요. 여기에서는 MySQL을 Store로 사용하겠습니다.
우선, 필요한 파일들을 include해야겠지요?
[php]
require_once(’Auth/OpenID.php’);
require_once(’Auth/OpenID/Server.php’);
require_once(’Auth/OpenID/MySQLStore.php’);
[/php]
내부적으로 다른 인클루드 파일들을 요구하기 때문에, include_path에 아까 설치한 Library위치를 포함시켜두면 좋겠습니다. (아니면 ini_set(’include_path’,) 를 설정하던가요.)
그리고 PEAR::DB를 이용한 DB커넥션을 Store로 사용할 것이므로 DB인스턴스를 만들어서 선언해줍니다.
[php]
$dsn = “mysqli://openid:password@localhost/openid”;
$connection = DB::connect($dsn);
[/php]
그리고는 MySQL을 이용하는 Store 객체를 반환받아야겠지요.
[php]
$store = new Auth_OpenID_MySQLStore($connection, ’setting’, ‘association’, ‘nonce’);
// $store->createTables();
[/php]
도큐먼트에 보면, 2번째 파라미터부터는 optional하다고 되어 있고, null값일 경우 default 정의된 테이블 이름으로 생성된다고는 되어있습니다만, 무엇의 문제인지 null값을 넣으면 제대로 생성되지 않더군요. 그리고 createTables()메쏘드를 실행해줍니다. 위에서는 주석처리해놓았는데, 사실 한번 테이블이 생성되면 저 메쏘드는 필요없어지기 때문입니다. 물론 여러번 실행시켜도 문제가 되지는 않습니다. (내부적으로 rollback)
이제, 해당 Store를 사용하는 OpenID Server 객체를 만들어야겠지요. 만약 다른 DB Store나 혹은 File Store를 쓰고 싶다면 해당 Store 클래스로부터 만들어진 객체를 $store로 넣어주면 됩니다.
[php]
$server =& new Auth_OpenID_Server($store);
[/php]
이제, 이 만들어진 Server 객체에 OpenID Request를 넘겨주면 되는데, 이 Request는 대개 Get메쏘드로 넘어온 값을 가지고 Request객체를 만들어 주면 됩니다.
[php]
//$value는 대개 Get으로 넘겨받은 OpenID request문자열입니다. 서버 구현에 따라 이 부분은 달라질 수도 있으니 알아서…
$request = Auth_OpenID::fixArgs($value);
$request = $server->decodeRequest($request);
[/php]
이 Request 객체의 멤버중에 mode라는 멤버가 있습니다. 이에 따라 해당 작업을 해주면 됩니다.
[php]
switch($request->mode) {
case ‘checkid_immediate’:
…
break;
case ‘checkid_setup’:
…
break;
default:
…
break;
}
[/php]
특별한 문제가 없는 한, association mode는 라이브러리에서 알아서 처리해줍니다. 물론 발급되는 키값을 바꾸거나 하고 싶다면 이 부분을 고쳐줘야겠지요. 어쨌거나, 특별히 고칠 부분이 없다면, 위의 default부분에, 아래의 코드를 넣는 것만으로 충분합니다. 이것은 user정보와는 상관없는 기본적인 handshake 단계의 통신이기 때문에 사실 건드릴 것도 별로 없는 셈이죠.
[php]
$response =& $server->handleRequest($request);
$webresponse =& $server->encodeResponse($response);
foreach ($webresponse->headers as $k => $v) {
header(”$k: $v”);
}
header(header_connection_close);
print $webresponse->body;
exit(0);
[/php]
checkid_setup과 checkid_immediate의 경우에는 프로바이더의 사용자 시나리오에 따라 복잡한 과정들이 처리되어야 하는데, 예를 들자면, 사용자가 인증을 허용하는지 여부등에 따라 반환되어야 하는 값이 달라져야겠지요.
만약 모든 조건이 클리어하다면, (예를 들어, Consumer사이트가 trustRoot에 포함되어 있고, 사용자가 해당 Consumer사이트로의 인증을 허락했다면…)
[php]
$response =& $request->answer(true);
$webresponse =& $server->encodeResponse($response);
foreach ($webresponse->headers as $k => $v) {
header(”$k: $v”);
}
header(header_connection_close);
print $webresponse->body;
exit(0);
[/php]
로 끝.
만약 Simple Registration Extended를 지원한다면, openid.sreg.required / openid.sreg.optional 의 형태(php에서는 openid_sreg_required / openid_sreg_optional 이라는 해쉬값으로..)로, 필요한 사용자의 데이터를 요구하게 됩니다. 이 경우에는,
[php]
$response->addField(’sreg’, 요구필드이름, 해당 데이터);
[/php]
형태로 추가해주면 되지요.(물론 $server->encodeResponse()전에..)
Provider의 사용자 시나리오에 따라서는, 로그인처리, 인증여부처리, 요구필드에 대한 허가 처리 등이 필요한 경우도 있을 수 있습니다. 그런 경우에는 Ajax나 혹은 일반 Form 형태로 사용자 브라우저에서 처리를 받은 후에, 현재 호출된 URL로 다시 redirect해주면 됩니다. (OpenID Request는 Get값으로 이루어지므로… 물론 처리페이지까지 OpenID Request들을 전달해서 그 페이지에서 처리하는 방법도 있겠지요.)
만약 올바른 요구와 답변이 아닐 경우에는,
[php]
$response =& $request->answer(false);
$webresponse =& $server->encodeResponse($response);
foreach ($webresponse->headers as $k => $v) {
header(”$k: $v”);
}
header(header_connection_close);
print $webresponse->body;
exit(0);
[/php]
로 해주면 됩니다.
나머지는 라이브러리에서 다 알아서 해주니까, Provider 개발자가 고민할 부분은, 사용자 시나리오를 어떻게 운영할 것인가.. 하는 부분이겠죠?
이상으로 OpenID 그까이꺼 만드는 법 Provider편 초간단 설명.
물론, 남의 라이브러리를 의지하지 않고, 프로토콜만 가지고 직접 구현할 수도 있겠습니다만, 뭐 굳이 그럴 필요 있나요?
Consumer편은 더 간단합니다만, 다음 기회에. 사실 Provider는 굳이 여러 곳에서 만들 필요는 없어요. 공연히 사용자에게 불편만 줄 뿐. 실상 Cyworld나 Naver Blog같은데서 지원하면 깨끗이 정리될 문제입니다만, 그럴 생각들은 없는 것 같고… (OpenID Provider라면 당연히 자사의 서비스에 Consumer도 붙여야 체면이 서겠습니다만… 과연 N이나 S가 그럴 것인지? ^_^)
February 19, 2007 at 12:32 pm · Filed under WorldWideWoops
일본 생활도 이제 며칠 안남았네요.
일본에서는 OpenID 대응 서비스를 만들었습니다. 실은 그런 목적으로 일본 간 건 아니었는데, 어쩌다보니 밤샘 프로그래밍으로 초속성 개발 - 중간에 2주가량 스톱상태이긴 했지만. - 을 했지요.
서울에 개발 스튜디오를 하나 만들어서 실질적인 개발은 서울에서 이루어질 예정입니다. 홍대 근처에 작은 스튜디오를 하나 얻었고 집기들도 전부 들여놨다지요. 
인재가 제일 중요한데, 지난번의 서울 방문은 사람들은 많이 만났으나 흡족한 결과를 얻지는 못했습니다. 하긴 국내에서는 아직 알려지지 않은지라.
최근 보면, 홍보전에 집중하는 회사들이 많아졌어요. 개발 전문가들이 모인게 아니라 홍보 전문가들이 모였나? 싶은 정도의 회사도 있고.
서울 스튜디오가 본격적으로 가동되고 몇 개의 간단하지만 아이디어 서비스들이 곧 한국에도 런칭되면 우리도 입소문 좀 탈라나요? 인재찾기는 느긋하게 가기로 했습니다. 급하다고 아무나 뽑을 수는 없지요.
이제 10일 즈음 후면 귀국이군요. 서울에서 뵙겠습니다.
February 15, 2007 at 7:41 pm · Filed under WorldWideWoops
웹서비스 하나 제대로 쓰려면 부지런해야 한단다.
사용법 노하우까지 알려주고 잘 쓰란다.
게으르면 안되는 것인가…
게으른 컴퓨팅이 목적인 나에게, 부지런함을 요구하는 서비스따위는 필요없다.
하긴, 자신이 필요하면 얼마든지 부지런해질 수도 있을테고, 부지런한 사람에게 더 많은 혜택이 돌아가는 것도 당연하긴 한데…
부지런하고 충성도 높은 사용자만을 위한 서비스란건, 결국…
소위 웹 1.0시대 이야기 아냐?
에… 결국 그런건가. 웹 2.0은 역시 그냥 마케팅 용어?
게으른 사람을 위한 서비스 어디 없나? 은근히 기분나쁘네.
February 15, 2007 at 6:24 pm · Filed under WorldWideWoops
예전에, MyID.net에 대해 “어째서 공식 블로그에 커멘트를 openid로 쓸 수 없는거야”라고 투덜댔었는데,
으흐흐흐….
일본에서 만든 www.openid.ne.jp 에 포럼을 붙이려고 보니… openid를 지원하는 포럼이 아직 없더군요. 두루팔을 깔기에는 너무 매니악하고. PhpBB-OpenID 프로젝트는 여전히 잠수중(?)이고.
MetaBBS에서 지원할 예정이라는 이야기만 믿고 계속 기다릴 수도없고.
어쨌거나, 이 기회에 지난번 발언에 대해 공개적으로 취소를, 그리고 관계자 분들께 사과드립니다. ^^;
Next entries »