2006년 9월 8일 금요일

AHAH - AJAX의 보완.

여기저기 어디서나 AJAX 타령. 개나 소나 AJAX를 이용해 서비스를 만들고 있는데, 솔직히 말하자면 아이들에게 칼들려 놓는 것처럼 위태위태하다. 그러다보니 이런 만행도 일어나고.
실제로 웹서비스 개발 중에 AJAX를 사용해보면 그닥 만만한 작업은 아니다.

1) XML 스키마를 정의하고 개발중에 관리하는 것은 꽤나 귀찮은 일이다.
2) 서버사이드에서 XML로 인코딩하고, 클라이언트사이드에서 XML을 파싱한다. 단지 화면에 약간의 HTML 컨텐트를 보여주기 위해 들어야 하는 품이 제법 많다.
3) 서버사이드에 XML을 만들고 발송하는 서버프로그램을 별도로 제작해야한다.
4) 접근성을 위한 대체텍스트 혹은 대체페이지를 개발하기 위한 품이 별도로 들어간다.
5) 잘 아시다시피 클라이언트사이드에서 JavaScript 디버깅하는 것은 매우 골치아픈 일이다.

고작 HTML 조금 동적으로 보여주기 위해 AJAX를 써야 하는가?
여기 대체재 AHAH가 있다.

AJAX는 Asynchronous JavaScript and XML을 가리킨다. 그럼 AHAH는?
Asychronous HTML and HTTP를 말한다.

언제 나온 새 기술인가 하고 의아해하는 분들이 있다면 조금 실망할지도 모른다. 실은 XMLHttpRequest 객체를 활용하는 또다른 방법일 뿐이다.

이미 AJAX를 많이 다뤄본 분들은 XMLHttpRequest.responseXML 대신 XMLHttpRequest.responseText가 편하다는 것을 깨달은 분들이 있을 것이다.
맞다, 그것이 AHAH이다. responseXML대신 responseText를 쓰면 AJAX라고 부르지 말고 AHAH라고 불러주자. 그간, responseText를 쓰면서 XML도 아닌데 AJAX라고 불러도 되나 찜찜하셨던 분들이라면 기꺼워 할 것이다. (나는 그랬다.)

?? 둘 사이에 무슨 차이가 있길래?

AHAH와 AJAX의 가장 큰 차이는, AHAH는 (x)HTML을 이용한다는 점이다. 주의할 점은, Text가 아닌 HTML이라는 점. responseText를 쓰되 그 전달값으로 HTML 서브셋을 쓴다는 소리다.

XHTML역시 XML의 일종이므로 XMLHttpRequest를 이용할 수 있다.

다음은 클라이언트사이드에서 AHAH를 이용하는 JavaScript 함수의 예제이다.
[javascript]
function SendAHAH(url,target) {
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = function() {
ReceiveAHAH(target);
};
req.open("GET", url, true);
req.send(null);
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = function() {
ReceiveAHAH(target);
};
req.open("GET", url, true);
req.send();
}
}
}

function ReceiveAHAH(target) {
if (req.readyState == 4) {
if (req.status == 200 || req.status == 304) {
result = req.responseText;
document.getElementById(target).innerHTML = result;
} else {
document.getElementById(target).innerHTML="AHAH error:\n" +
req.statusText;
}
}
}
[/javascript]

코드를 보면 AJAX랑 별 다를 것도 없다. 실제로 이미 이와 비슷하게 코딩해서 작업하는 분도 많을 것이다.

그럼 왜 AHAH인가?

1. 파싱이 필요없다.
데이터를 XML로 바꾸고, 다시 그 XML을 파싱해서 필요한 정보를 뽑고... 그것을 다시 DOM을 구성하는 AJAX의 과정이 필요없어진다.
document.getElementById(target).innerHTML = result;
이것으로 만사해결. 아예 처음부터 HTML로 보내고 받은 HTML을 target에 채워넣어주기만 하면 된다.
DOM과 JavaScript에 익숙하지 않은 개발자라면 기뻐할 일이다.

2. 웹접근성이 깔끔히 해결된다.
AJAX를 사용하는 종래의 DHTML은 접근성 면에 문제가 많았다. 동등한 정보를 제공하는 대체텍스트나 대체페이지를 제공해야하는데 그러기 위해서는 XML외에도 따로 똑같은 내용을 담은 HTML을 만들고 연결해야 한다. 당연히, 이 과정을 무시하는 개발자들이 대부분이고(심지어는 왜 대체페이지를 제공해야 하는지 모르는 개발자가 더 많겠지만.), 따라서 근래의 AJAX를 사용한 서비스들은 대부분 접근성에서 많은 문제가 있었다.
비록 접근성을 중요하게 생각하는 개발자라 하여도, XML데이터 외에 별도의 HTML데이터를 만들어야 한다는 것은 부담스러운 일이다.
그러나 AHAH를 사용하면 아예 처음부터 HTML을 되돌려주므로 접근성을 완벽히 보장할 수 있다.
다음 코드를 보자.

[html]
...

...

...

title="카테고리 목록">
카테고리 목록 바로가기

[/html]

getCategoryList.php가 이 페이지의 카테고리 목록을 다음처럼 보여준다고 하자.
[html]

[/html]

여기, 세가지의 접근성을 고려한 기법이 들어갔다.

1) head안의 link에 AHAH 서버페이지를 적어준다. 검색엔진봇이나 텍스트 브라우저, 텍스트리더기들은 이 link에 기술된 URL에 들어있는 HTML 정보에 문제없이 접근가능하다.
2) target 엘리먼트에 longdesc 속성으로 해당 AHAH 서버페이지를 적어준다. 여기에서는 div에 걸었으므로 엄밀하게 말해서는 맞는 방법이 아니지만, 만약 target 엘리먼트가 img라면 매우 좋은 방법이 될 수 있다.
3) target 엘리먼트안에, AHAH로 대치되기전까지 사용될 대체텍스트를 넣어둔다. 만약 JavaScript가 disabled되어있거나 지원하지 않거나 혹은 기타등등 에러가 발생해서 컨텐트를 동적으로 받아올 수 없다면 이 대체텍스트가 화면에 뿌려질 것이다. 사용자도 JavaScript가 안되어서 텅빈 화면을 멍하니 바라보는 것이 아니라, 대체텍스트나 수고스럽긴 해도 클릭 한번이면 대체페이지가 보이게 되는 것이다.

이 기능들을 AJAX로 구현하려고 하면 혀가 빠진다. MVC 프레임워크를 쓴다 하여도 XML데이터를 별도의 HTML로 재가공하는 View 기능을 만들어야 하기 때문이다. 그러나 AHAH를 쓰면 이렇게 간단히 해결된다. Hurrrah!

3. 동적 스크립팅이 쉬워진다.
AJAX의 단점중에 하나는, 서버사이드에서는 데이터를 전달할 뿐이고, 그에 대한 처리는 클라이언트사이드에서 담당해야 한다는 것이었다. 미리 정의된 데이터를 정의된 방식으로 처리할 수 밖에 없다. 데이터의 형식이 바뀌거나 처리방법이 바뀐다면 클라이언트사이드의 페이지를 열어서 일일이 수정해야 한다.

그러나 AHAH를 쓰면 동적 스크립팅이 쉬워진다. 클라이언트사이드의 수정없이 서버사이드에서의 변경만으로 얼마든지 브라우저에서 JavaScript 실행을 컨트롤할 수 있다.

위에서 소개한 ReceiveAHAH()를 조금 변형시켜보자.
[javascript]
var bSaf = (navigator.userAgent.indexOf('Safari') != -1);
var bOpera = (navigator.userAgent.indexOf('Opera') != -1);
var bMoz = (navigator.appName == 'Netscape');
function ReceiveAHAH(target) {
if (req.readyState == 4) {
if (req.status == 200 || req.status == 304) {
result = req.responseText;
document.getElementById(target).innerHTML = result;
execJS(result);
} else {
document.getElementById(target).innerHTML="AHAH error:\n" +
req.statusText;
}
}
}

function execJS(node) {
var st = node.getElementsByTagName('SCRIPT');
var strExec;
for(var i=0;i
if (bSaf) {
strExec = st[i].innerHTML;
}
else if (bOpera) {
strExec = st[i].text;
}
else if (bMoz) {
strExec = st[i].textContent;
}
else {
strExec = st[i].text;
}
try {
eval(strExec);
} catch(e) {
alert(e);
}
}
}
[/javascript]

전달받은 HTML중에 <SCRIPT>를 찾아 실행시켜준다. 즉, 클라이언트쪽에서 JavaScript를 준비하지 않아도, 서버사이드에서 필요한 JavaScript를 만들어서 넘겨주면 얼마든지 실행된다는 소리다. 물론 AJAX로도 비슷한 기능을 구현할 수 있다. 허나 저거보다 짧고 쉽게 할 수는 없다.
(IE는 내부적으로 HTML태그를 대문자로 유지하므로 실제로 응용할 때에는 String.upperCase 메쏘드를 이용해서 브라우저별로 SCRIPT 와 script를 분리해서 찾도록 할 필요가 있다. 또 주석의 형태와 세미콜론 사용에 유의해야 한다.)

IE에서만 통용되었던 비호환방식의 dynamic scripting이 AHAH를 씀으로써 아주 간단히 크로스브라우징상에서 구현가능하다.

물론 AJAX가 DOM 컨트롤이라든가 JavaScript 제어를 세밀하게 할 수 있는 장점이 있지만, 장담하건데, 여러분이 AJAX로 시도하려는 작업의 95%는 AHAH만으로도 충분하다. 공연히 몸에 맞지 않는 옷입고 비틀거리지 말고, 쉽고 간단한 AHAH를 써서 효율 좀 올려보자. 물론 내 욕심은 AHAH를 사용하면 접근성 고려가 매우매우 간단해지므로 덤으로 접근성도 좀 신경써달라는 것이다.

AHAH는 Kevin Marks가 2005년 5월, JAH(Just Asynchronous HTML) 라는 이름으로 처음 기법을 고안했고,
Ernest Prabhakar가 2005년 웹 2.0 컨퍼런스에서 처음 AHAH라는 용어를 사용했다. 결국 현재에는 REX(REST-Enabled XHTML) microformat의 일부로 채택이 되었다. 어디 이상한 사이비 기법 아니니 안심하고 쓰시길.

관련 URL
JAH : http://epeus.blogspot.com/2005_05_01_epeus_archive.html#111588374981985824
REX : http://www.opendarwin.org/~drernie/talk/rest-enabled-xhtml-20051019.html

블로그용어사전 v060908

* 18개월 만의 업데이트 (옛날 버전-v050330은 여기에, 추가된 부분에는 밑줄.)


블로그 / blog
도대체 그것이 무엇인지 누구도 뚜렷하게 말할 수 없고 정의할 수 없는 어떤 것. 아직도 누군가는 1인 미디어라는 헛소리를 믿기도 한다. 현재까지는 프랑크푸르트학파에서 주장한 social-exhibishoinsm의 병리적 증상이라는 설이 학계에서 가장 인정받고 있는 편이다.


커멘트 / comment , 리플 / reply, 답글
메일을 대신하여 새롭게 떠오르는 광고 수단.


트랙백 / trackback
멀리 있는 이에게 시비 거는 데 사용하는 결투장. 학창시절 신발장에 들어있곤 하던 것의 인터넷 버전. 마찬가지로 짝사랑(스토킹)의 수단으로도 쓰인다.


RSS
사이트에서 볼 수 있는 내용을 일부러 다른 곳(예를 들어 리더기)에서 불편하게 보기 위해 만든 바보같은 규격. Really Stupid Syntax의 약자.


CC / Common Creative
붙이기만 하면 타인의 스크랩과 불펌 및 허락없는 인용등을 막아준다고 사람들이 믿는 부적의 일종. 교회나 사찰에서 구할 수는 없다.


블로거 / blogger
대단히 한가한 사람의 다른 표현.


블로깅 / blogging
블로거들이 남아도는 시간을 소비하기 위해 몰두하는 비생산적 행위.


엔트리 / entry, 아티클 / article, 포스트 / post, 글
10년 후 되돌아보고 창피함을 스스로 느끼기 위해 작성하는 피학성 정신질환의 최소 단위 증거.


블로고스피어 / blogosphere
폐인, 오타쿠 공동체.


퍼머링크 / permalink
원뜻과는 달리, 시도 때도 없이 변하곤 하는 엔트리의 URI를 가리키는 용어.


아카이브 / archive
아무도 뒤져보지 않는 쓰레기통의 다른 이름.


모블로그 / moblog
패킷사용량을 늘리기 위한 전화회사의 음모.


포드캐스팅 / podcasting
iPod 판매량을 늘리기 위한 Apple사의 음모.


메타블로그 / metablog
인터넷상의 불필요한 트래픽 유발지를 인덱싱함으로써 종량제 시행시 서핑하면서 피해야할 주소들의 모음.
KT가 종량제를 사실상 포기함으로 인해 그 의의가 반감됨


그룹 블로그 / group blog, 팀블로그 / team blog, 링블로그 / ring blog
운영자 혼자 사용하는 블로그를 말함.


UCC, UGC
UCC는 User Crushed Coffee의 약자로 편의점에서만 구할 수 있는 수입 커피 브랜드이다. 처음 UCC에 주목한 업체들은 사용자들이 직접 커피를 갈아먹는 것이 사용자들에게 더 풍부한 경험을 주고 그 커피를 서로 공유하게함으로써 놀라운 비즈니스 모델이 될 것이라 예상했다. 확실히 몇몇 업체는 성공했다. 다른 업체들은 언젠가는 성공할 거라고 생각하며 그 많은 커피콩들을 모아둘 창고유지비를 감내하고 있다.
한편 UCC라는 브랜드 자체가 짝퉁이며, UGC(User Grinded Coffee)가 오리지널 브랜드라고 주장하는 사람들이 있다.
어쨌거나 맛은 있으되, 영양가는 거의 없으며 무엇보다도 귀찮다. 적절한 보상이 없으면 더이상 호기심만으로 커피콩을 갈아대는 전문가들을 붙잡을 수 없다.


AJAX
콜게이트-팜올리브 사에서 만든 레몬향이 나는 세척제.
블로그에 사용하면 인터페이스와 트래픽을 깔끔하고 윤이나게 닦아준다고 한다.
너무 잘팔린 나머지, 사용하지 않아도 될 곳에 사용해서 문제. 보통은 "물이 빠진 것"을 "깨끗해졌다."라고 말하지는 않는다.
여튼 이 제품을 안쓰면 왕따라도 당하는 모양이어서 귀얇은 회사들은 박스채로 구입하고 있다.
발음은 [아약스]만 아니면 맘대로 발음해도 좋다.


태그 / Tag
다른 사람들로 하여금 그 글의 원래 키워드나 범주가 뭐였는지 헷갈리게 하기 위해 만드는 함정.
원래 태그란 짐짝등의 주인을 구별하기 위함이 아니었던가. 별명만 잔뜩 적어놓은 태그만 가지고 가방의 원래 주인을 찾아줄 수는 없다.


개인화 홈
남들과는 다른 나만의 개성있는 초기페이지를 꾸밀 수 있다고 주장한다. 그러나 그 초기페이지는 결국, 개발자가 제공한 것들 중에 몇가지 골라 선택하는 것 뿐. 그러니까 사실, 별로 개성적인 건 아니라는 것.


AdSense
"저 가난합니다. 돈이 없습니다. 이거라도 해서 코묻은 돈 벌어 애기 분유라도 타줘야겠습니다. 그러니 클릭하세요."의 줄임말.

2006년 9월 5일 화요일

나도 때려보자, 썩플.

과격한 제목으로 글을 시작하는 건 부담이다. :)
허나 요즘 유행하는 써플 때리기라는 신종 스포츠에 기꺼이 동참.

필립.K.딕의 "마이너리티 리포트"를 보면, 예언 당사자가 예언을 알게 되면서 어떻게 예언이 바뀌는지에 대해 나온다.
실험의 신뢰도를 높이는 기본조건중에 "이중맹검"이라는 항목이 있는데, 실험대상이 실험에 대해 몰라야 하며 동시에 실험자도 실험에 대해 몰라야 한다. (예를 들어 신약을 테스트할 때, 실험군과 대조군 환자모두 어느쪽이 신약을 받는지 스스로 몰라야 하며, 그 실험을 실시하는 시험자역시 어느쪽에 신약을 주었는지 실험이 종료될 때까지 몰라야 한다는 뜻이다.)
양자역학에서는 입자의 위치와 운동을 동시에 계측할 수 없다. 왜냐하면 관찰자의 관찰이라는 행위가 입자에 간섭을 주기 때문이다.

시시한 토막상식이다.

IT업계에 집단지성이라는 유령이 출몰하고 있다.
아아, 그 뜻은 좋은 거지.
문제는 그 구현은 그리 간단하지 않다는 것이다.

모 신문사는 대문에 오르는 기사순서에 네티즌의 "추천"이라는 행위를 반영한다고 한다.
"오늘의 인기글"은 왠만한 커뮤니티 등에서는 빠지지 않는 코너이다.
검색사이트였는지 잊고 있었던 모 포털(이라고 숨겨봤자 뭐하겠는가. 네이트의 신 서비스 썩플에 대한 이야기이다.)에서는 검색순위에 네티즌의 "추천"을 이용한다고 한다.

인기글은, 뭐 크게 상관은 없겠다. 집단지성이라는 레테르를 붙이진 않았으니까.
신문사 기사게제순서야 어차피 편집자의 맘이니 그런 식으로 편집한다 해도 누가 뭐라겠는가.

그러나 검색사이트에서 로그인한 사용자의 추천?
세상 참 편하게 산다 싶다.

영화나 상품은 구매한 사용자의 충성도를 기대할 수 있다. 소비되는 가치가 아무려면 웹페이지 한장 보다는 크겠지. 영화보고 와서 영화사이트에 별점 매기는 건 조금 번거롭긴 하지만 자발적인 참여를 기대할 만 하다.

하지만 검색은 아니잖아?
포털들이 왜 덩치를 키웠는가? 검색과 색인으로 시작했던 포털들이 덩치를 키운건, 검색과 색인은 사용자들의 최종목적이 아니기 때문이었다. 즉, 검색과 색인은 최종목적지를 위한 중간단계였을 뿐 빨리 최종목적지로 보내줄 수록 좋은(?) 검색엔진이라는 딜레마 때문에 사용자를 붙잡아 두기 위해 덩치를 키운 것이다.
뭐, 반대로 더욱더 빨리 최종목적지로 보내버리겠다는 DON'TBEEVIL Google이 있긴 하지만.

드디어는 검색을 위해 로그인을 해줘야만 할 것 같은 검색서비스라... 멋지구리.

1. 대부분의 사용자는 로그인하지 않아도 되는 서비스에는 로그인하지 않는다.
2. 로그인하지 않아도 되는 서비스에 사용자가 로그인하는 것은 특별한 "의도"를 가지고 있을 때이며, 대개 그 "의지"는 평상시의 자연스러움과는 달리 의도적인 강한 동인을 내포한다.
3. 그 "의도"는 필연적으로 평시의 자연스러운 정보의 흐름을 왜곡하려 한다.

결론 : 사용자의 "의식적 행위"에 기인하는 결과는 "집단지성"보다는 "집단감성"에 어울린다. 속되게 과장하자면 "빠돌-순문화"나 다름없다. 우리 오빠들이 1등 먹어야 해요. 기타는 XXX가 짱이지.

그럼 검색에 집단지성은 불가능한건가?
무슨 소리. 이미 Google이 처음부터 하던게 그거 아닌가. PageRank는 여러가지 고려사항이 있지만 기본적으로는 얼마나 많이 "참조"되었는가를 따진다. "참조"는 의지로 조절 가능한 것이 아니고, 또 설령 가능하다 하더라도 기회비용이 많이 든다. 따라서 간단하게 클릭질 하나로 결정되는 순위보다는 훨씬 신뢰할 수 있다. 집단 속에서 자연스럽게 체화되어 나와야 집단지성이라는 과분한 단어를 붙일 수 있는 것 아닌가?

아아, 한국적 특수성이라는 약방의 감초가 누군가의 입에서 나오겠지만, 그 놈의 한국적 특수성때문에 네이버 검색결과를 신뢰하지 못하잖아. 마치 어느 누구도 가판대 주간지에서 진실을 원하지는 않는 것처럼. 오로지 원하는 건 가쉽일 뿐. 가쉽검색에는 썩플이 최고입니다요.

네이버가 아닌 것이 천만다행. 그나마 네이트이니 그저 한번 씩 비웃어주고 끝날 수 있겠지만, 네이버였다면 벌써 클릭알바가 새로운 SEO 비즈니스 모델이 될 뻔하지 않았나.

차라리 검색순위를, "얼마나 Tong에 많이 클리핑되었는지", "얼마나 미니홈피에 많이 스크랩되었는지", "얼마나 egloos에 많이 링크되었는지" 를 계산해서 매긴다면 훨씬 객관적이면서도 자연스러운 집단지성 아니겠는가. 애꿎게 클릭한번 더하게 만드는 피곤한 서비스가 과연 성공할 것인지 심히 궁금.

1. 집단사고는 과연 회자되는 만큼 가치가 있는가? 통찰력있는 소수의 사고보다 나은 가치를 줄 수 있는가?
2. 집단사고는 결국 소수의 영향력있는 오피니언 리더의 아이디어를 좀더 대중지향적인 모습으로 예쁘장하게 눈속임한 결과는 아닌가?
2-1. 집단의 사고가 근본적으로 오피니언 리더의 영향을 배제할 수 없는 한 엄밀한 의미의 집단사고라 부를 수 있는가?
2-2. 집단사고는 단순히 "집단 속에 속해있는 나"가 헤게모니를 획득했다는 착각과 자기만족을 주는 것뿐은 아닌가?
3. 집단사고는 그 방향성과 목표를 "evil"하지 않게 유지할 수 있는가? 혹은 컨트롤할 수 있는가?
3-1. 컨트롤할 수 있다면 그것은 집단사고라는 근본과 모순되는 것은 아닌가?
4. 집단사고가 철저하게 기층단위를 기반으로 작동하게 하려면 무엇을 전제로 해야하는가?
5. 이러한 모든 과정을 거쳐 집단사고가 긍정적으로 실현된다 하더라도 그것이 나의 가치에 부합한다는 보장을 할 수 있을까? 그렇다면 그 실현방법과 보장이유는?
5-1. 그렇지 않다면 나와 유리된 집단사고라는 것이 도대체 무슨 의미가 있는가?
6. 왜 그럴까? "나"를 제외한 집단사고가 "나"에게도 가치있을거라는 착각이 만연해있는 이유는?
7. 그렇다면 차라리 철저한 "나-중심"의 사고의 "집합-필터링"이 오히려 집단사고의 근본적인 의의에 가까운 것은 아닐까?
From : 옛날블로그 : Group Think, Group Intelligence

아직 더 때릴 것이 남았는데,
이른바 릴레이서플이라면서 프레임링크를 걸어버린다.
예:http://searchplus.nate.com/searchplus/relay.plus?ud=1&query=naver&coll=dir_site&s=1&forbid=&mid=dirSite1
이런 건 naver에서 소송안거나? :)
이는 엄연히 저작권을 침해하는 프레임링크라고.
하긴, 네이버 역시 비슷하게 프레임링크를 이용하는 서비스가 있으니 뭐라 할 말도 없겠지.
웃기는 것은, 죄다 이렇게 프레임링크를 걸었으면서, "웹뉴스"검색결과에는 빠져있다. 왜냐고? 온신협에서 프레임링크는 고소대상이니까.
즉, 뭔 말인가 하니, 저작권 침해로 고소당할까봐 신문사 검색결과에는 붙일 수 없는 프레임링크를 다른 곳에는 맘껏 쓰고 있다는 소리. 이참에 고소해버릴까? (아쉽게도 이 사이트는 검색결과에 나오지 않네... 마이너블로거의 서러움. 아쉽.)

웹 2.0이라면서 요즘 프레임링크를 맘껏(?) 사용하는 서비스들이 늘고 있다. 글쎄.. 물론 저작권법이 현실적으로 바뀌어야겠지만, 어쨌거나 현재 불법(?)인 프레임링크를 이렇게 막 써도 되는건가? 나름 저작권에 민감한 사용자들도 이 건에는 별 불만 없는 건가?

내친 김에 하나만 더 때리자.
"디렉토리/사이트 분류"의 "네이버"와 "웹페이지 분류"의 "네이버"는 별개의 항목으로, 플러즌이나 플러스도 따로 관리된다. 뭐, 개념상 다를 수도 있겠지만, 사용자들은 과연 두 가지를 서로 다른 것이라고 인식하고 있을까? 하나는 25플러즌, 또 하나는 2플러즌. "daum"으로 검색해보면 각각 20플러즌과 4플러즌이다. 나는 도대체 여기에 어떤 집단지성을 발견할 수 있는지 알 수가 없다. 집단바보놀이만 가득한 느낌이다.

2006년 9월 4일 월요일

CSS에서 selector 우선순위 계산하기

CSS를 사용하다보면 같은 엘리먼트에 대해 여러곳에서 선언하는 경우가 있다.
예를 들자면 다음과 같은 경우.

[html]
li {color:#A00;}
.list_item {color:#0A0;}
#item_1 {color:#00A;}
...

  • hello
  • ...
    [/html]

    이런 경우, 어떤 셀렉터가 우선될 것인가.

    이에 대해서는 다음과 같은 공식이 있다.

    * {} /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */
    li {} /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */
    li:first-line {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
    ul li {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
    ul ol+li {} /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */
    h1 + *[rel=up]{} /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */
    ul ol li.red {} /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */
    li.red.level {} /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */
    #x34y {} /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */
    style="" /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */

    1) inline 스타일 (style="")은 무조건 최상위이다. (a = 1, inline 스타일을 사용하지 않으면 a = 0)
    2) id selector 갯수를 b라 한다.
    3) class selector와 pseudo selector 갯수를 c라 한다.
    4) 엘리먼트의 갯수를 d라 한다.
    5) abcd의 조합이 큰 순서로 우선순위가 결정된다.

    예를 들어,
    li {...} : 0001
    ul li {...} : 0002
    ul li ul li {...} : 0004
    .list_item {...} : 0010
    li.list_item {...} : 0011
    .menu_list .list_item {...} : 0020
    ul.menu_list li.list_item {...} : 0022
    ul#main_menu li.list_item {...} : 0112
    ul#main_menu li.list_item div.item_label img : 0124

    간단히 말하자면, 좀더 상세화시킬 수록 높은 순위로 CSS가 적용된다는 뜻이다.

    이를 이용해서 모듈별 CSS관리가 가능한데,
    즉, 중간정도의 우선순위로 모듈별 CSS를 적고, 나중에 페이지에 적용할 때에는 그보다 높은 우선순위로 페이지별 CSS를 적어주게 되면 모듈별 CSS의 수정 없이 원하는 디자인 대로 페이지별 CSS에 따라 적용시킬 수 있다는 뜻이다.

    참조 : http://www.w3.org/TR/CSS21/cascade.html#specificity

    놓치기 쉬운 가상클래스의 selector 순서

    링크(a)에 대해 셀렉터를 적을 때 주의할 점.
    CSS의 선언은 나중에 선언한 것이 앞서 선언한 것을 덮어 쓰게 된다. 대개의 경우에는 문제가 없는데, 한가지 주의해야 할 부분은, a에 대한 가상클래스(pseudo-class) - 예를 들어, :hover 따위... - 를 적을 때이다.

    다음 순서를 지켜야 생각한 대로 동작하게 된다.

    a:link
    a:visited
    a:hover
    a:active
    a:focus

    이 부분에 대해서 정찬명씨는 명언을 남기셨다. "링크 방문시 지나치게 활동하면 주목받습니다."
    외우기 쉽다.

    2006년 8월 28일 월요일

    왜 RSS에 description을 사용해야 하는가.

    부분공개(?)가 왜 더 바람직한지는 몇가지 이유가 더 있습니다.
    일단, 그 전에 “부분공개”라는 용어는 잘못되었음을 지적하고 싶습니다. “TEXT요약(description)”과 “encoding된 전문(contents)”의 차이입니다.
    우선 RSS 2.0의 기본스펙은 description만 존재합니다. description은 HTML코드가 사용되지 않은 Plain Text만 대상으로 합니다. content:encoded는 마크 필그림이 추가로 확장제안(관련링크1, 관련링크2)한 것으로 “표준”은 아닙니다. 따라서 매우 많은 리더기가 content:encoded를 지원하기는 하지만 아닐 수도 있습니다. content:encoded만 사용해서는 안되는 이유입니다.
    또한, description에 HTML코드를 담아 보내는 경우도 있는데(일부 국내 블로그들), 이건 RSS 규격 자체를 제대로 이해하지 못한 것입니다. description안에는 반드시, HTML이나 XML이 빠진 Plain Text만 전달해야 합니다. (따라서 description안에 img나 a 태그들이 포함되어 있으면 안됩니다.) - 물론 필요에 따라 CDATA나 Entity처리된 HTML을 보낼 수는 있습니다. 이것을 해석하는 방식은 리더기에 따라 다를 수도 있습니다.

    가장 바람직한 것은 description에 해당 컨텐트에 대한 Plain Text로 된 설명을 싣고, content:encoded에 HTML이 들어있는 본문을 싣는 방법입니다. 국내 블로그 서비스들 대부분이 이를 지원하지 않고 있습니다. 몰라서 그럴 가능성이 제일 큽니다.
    이게 안된다면 차선책은 Plain Text로 된 description만 사용하는 것입니다.

    문제가 되는 것은, description에 Plain Text만 담아서 보내는 건 좋은데, 그것이 “본문의 일부만, 특히 앞부분만 잘라서 보내는 경우”입니다. (소위 말하는 “일부공개”라겠죠. 개념은 틀렸지만.)
    저는 이게 문제가 되지 않는다고 생각은 합니다만, 어떤 이들에게는 불만일 수 있습니다.
    “요약”도 아니고, “인코딩된 전문”도 아닌 어정쩡한 포지션이라는 생각이 들 수도 있기 때문이겠지요.

    사실, 제대로 RSS를 지원하는 블로깅 툴이라면(예:MovableType, WordPress등) 이 description에 사용하기 위한 별도의 excerpt입력항목을 두고 있기 마련입니다.
    사용자가 이 항목에 별도의 요약을 입력하면 그 내용을 RSS의 description으로 이용하는 것이 올바른 방식입니다만…
    국내에는 제가 알기로는 엔비블로그외에는 이런 시스템이 없습니다.
    만약 사용자가 excerpt를 따로 입력하지 않았다면 앞서말한 MT나 WP등은 사용자가 입력한 본문중의 몇자를 따와서 excerpt대신 씁니다. 이게 와전(?)된 것이 국내의 RSS들의 일부공개형식입니다. 그런고로, 사실 국내 블로그툴들이 이렇게 무조건 앞대가리만 떼어서 RSS를 만드는 건 반쪽자리 UX인 셈입니다.

    그렇다고는 해도, 비록 앞부분 몇자만 떼어와 만드는 TEXT description이라 하더라도 HTML이 포함된 content:encoded보다는 우선되어야 합니다. content:encoded는 어디까지나 RSS제공자의 선택사항일 뿐입니다.

    왜 그런고 하니,

    1) 모든 RSS리더기가 content:encoded를 처리할 수 있는 것은 아닙니다.

    2) HTML이 포함된 content:encoded는 제공자의 리소스/트래픽뿐만 아니라 구독자의 리소스/트래픽까지 잡아먹기 때문입니다. 비근한 예로 홈페이지에 강제로 음악을 임베딩해놓는 것이 주인장 맘에는 흡족하다 하더라도 방문자의 쾌적한 웹서핑을 방해하는 것과 마찬가지입니다.

    3) HTML이 포함된 RSS는 대개 웹접근성을 저해하기 때문입니다. 예를 들어 장애인들이나 기타 다른 장치(PDA등)에서 이용할 때 문제가 되기도 합니다.

    4) 이미 RSS에는 그러한 것들을 위한 별도의 엘리먼트들이 있기 때문입니다. 예를 들면 관련링크들을 기술하는 곳, 관련 이미지 리소스들을 적어두는 곳… 딱히 본문을 HTML형태로 다 보여주지 않더라도 본문과 동등한 내용을 전달할 수 있기 때문입니다. (역시 문제는 국내 블로깅 툴들이 만드는 RSS는 그런 것들을 지키고 있지 않아서 문제이긴 합니다.)

    5) 펌질/저작권은 오히려 부수적인 문제입니다. 비록 일부만 긁는다고 저작권이 더 잘지켜지거나 하는 건 아닙니다. 따라서 이 부분으로 논점을 옮기는 건 무의미하다고 보구요. 대신 RSS는 공개하는 순간 그것의 사용책임은 전적으로 구독자(수집자)가 져야 합니다. 가져가는 것이 문제가 아니라, 어떻게 사용하는가가 문제일 뿐이지요. 이부분에 대한 논쟁은 다른 주제이므로 여기에서는 그치겠습니다.

    개인적으로 description을 지지하는 이유는 1)~3)입니다. 그리고 이에 대해 모든이를 만족시키는 방법은 description과 content:encoded를 같이 제공하는 방법이며, WP나 MT등의 블로깅 툴에서는 모두 이런 방식을 쓰고 있습니다. 따라서 만약 “전문공개”(?)를 주장하고 싶으시다면 TT나 네이버등에 description(별도의 excerpt를 입력받는)과 content:encoded를 모두 지원하라고 요구하는 게 맞습니다. 둘 중의 어느 하나를 선택해야 한다면 저는 단연 description입니다. (둘 중의 하나만 선택해야할 이유따위는 물론 전혀 없습니다.)

    이 모든 건 RSS 제공자의 마음이지, 구독자가 뭐라 할 성질은 아닙니다. 아, 물론 자신의 유명세를 빌어 content:encoded만 이용할 것을 요구한 개념없는 외국인 블로거가 있기는 하지요. 정정:그 역시 content:encoded를 이용하려는 이유는 개선된 "광고"를 위해서가 아니었나요?

    2006년 8월 26일 토요일

    올바른 타이틀(title) 작성법

    웹페이지를 제작할 때 타이틀은 매우 중요하다. 소설을 쓸 때에도 제목을 잘 지어야 하는 것 처럼.

    나쁜 예부터 보자.


    Bad Case 1. "무제(無題)"
    요즘 청소년들도 혼자만의 감상에 못이겨 시를 쓰는지 모르겠는데, 아무튼 한때 문학소년소녀들의 자작시집에는 "무제"가 왜이리 많았는지. 머리통이 좀 굵어지고 난 후에 보기라도 할라치면 어쩌자고 저런 이름을 붙였나 낯뜨겁기까지 하다.

    웹 페이지 작성시에도 타이틀을 안붙여주는 경우들이 많은데, 매우 안좋은 습관이다.
    타이틀은 웹접근성을 위해서도 매우 중요하다. 시각장애인의 경우, 열려있는 문서와 프로그램들을 타이틀을 통해 구별한다. 타이틀이 없다면 구별이 아주 어렵다. 장애인뿐만 아니라 기계친화적인 문서를 필요로 할 때에도 문제가 된다. 예컨데, 검색엔진에라도 잘 걸리게 하고 싶다면 타이틀은 문서간의 구별과 문서내용을 짐작하게 해주는 아주 중요한 도구가 된다. 습관적으로 무성의 하게 타이틀을 비워두는 버릇은 버려야 한다.


    Bad Case 2. "XXX 사이트"
    아예 타이틀이 없는 것보다 낫긴 하지만, 그래봤자 오십보 백보. 사이트를 통털어서 모든 페이지가 같은 타이틀을 가지고 있는 것은 비워두는 것과 마찬가지이다.
    왜 이런 경우가 생기는가 하면 개발자들이나 코더들이 조금 편해보겠다고 모든 페이지에 고정된 HTML 헤더를 인클루드시켜버리기 때문이다.
    모든 페이지마다 독립된 타이틀을 가져야 한다. 이유는 앞 항목에서 이야기 한 것과 같은 이유. 모든 페이지의 타이틀이 같다면 색인을 만드는 기계들도 곤욕이고, 시각장애인들의 경우 자신이 보고 있는 페이지가 무엇인지 알기가 어렵다. 더군다나 팝업이나 새창이라도 몇 개 뜨고 나면 어려움은 몇 배 더 가중된다.


    Bad Case 3. "~에 오신 것을 환영합니다."
    일단 두번째 케이스의 단점에 준하면서, 거기에다 시각장애인에게 짜증을 더해주는 케이스이다.딴에는 저렇게 공손히 써놓으니 스스로 친절함을 발휘한 것 같아 흐믓할지는 몰라도.
    시각장애인들이 사용하는 TTS는 "모든 것"을 읽어준다. 듣기 좋은 소리도 한두번이지, 페이지 이동할 때마다 "~에 오신것을 환영합니다."를 반복해서 듣는 것은 멀쩡한 사람도 노이로제걸리게 하기 딱 알맞다.
    꼭 친절함을 표시하고 싶다면, 대문에나 한번 쓰고 말아라.

    그럼 어떻게 작성하는게 올바른 방법일까?


    Good Case 1. "문서 제목만 쓰기"
    예를 들자면, "올바른 타이틀 작성법"처럼 현재 보이고 있는 문서의 제목만 표시해주는 것도 괜찮다. 중언부언 늘어놓는 것보다는 깔끔하게 문서 제목만 보여주자.
    게시판 목록 페이지라면 "자유게시판 목록"이라거나, 게시물 읽기 페이지라면 "게시물 제목"을 써주는 식으로.


    Good Case 2. "사이트 이름 - 문서 제목"
    그러나 문서 제목만 가지고는 창을 여럿 띄웠을 때는 헷갈릴 수도 있다. 그러므로 사이트 이름을 같이 적어주는 것도 괜찮은 방법이다. "DNZIN - 올바른 타이틀 작성법" 이런 정도.


    Good Case 3. "Path"
    간단한 블로그라면 위의 두가지 정도로도 충분하겠지만, 덩치가 큰 사이트 내에서 단계가 깊은 페이지일 경우에는 경로를 보여주는 것도 좋다.
    예를 들자면,
    "DNZIN : 블로그 : WebStandard Archive : 올바른 타이틀 작성법" 이런 식이어도 좋을 테고, 대개 타이틀을 착실하게 써주는 사람들은 이런 형식을 선호하는 편이다.
    선형 혹은 트리형태의 사이트맵을 가지고 있는 사이트에서 하위 페이지로의 접근이 단계별로 진행되는 경우에는 크게 상관은 없지만, 만약 그렇지 못한 사이트라면 이러한 타이틀은 사용자에게 혼동을 줄 수도 있다. 스파게티처럼 링크들이 얽혀있는 사이트 네비게이션이라면 주의해서 사용해야 한다. 사용자의 UX는 경험상 뒤로가기 버튼을 눌렀을 때 상위 단계로 이동하길 기대하기 때문에 개구리 뜀뛰듯 링크가 얽혀있을 때 이러한 방법은 그다지 좋다고 할 수는 없다. 물론 시각장애인들에게는 그 어려움이 두배가 된다. 이럴 때에는 <head>안의 <link>의 rel과 rev 속성을 통해 prev, next, index등을 지정해줌으로써 혼동을 막는데 도움이 된다.
    게다가 이 형식에는 애초부터 시각장애인을 위한 배려가 2%쯤 부족한 아쉬움이 있다.


    Good Case 4. "Reverse Path"
    그 아쉬움이 뭐냐 하면...
    눈을 통해 2차원적으로 동시에 정보를 수용하는 정상인들과 달리, 시각장애인들은 음성이나 점자를 통해 선형적으로 구성된 정보를 시간순으로만 접할 수 있다. 이런 경우 인간의 집중력은 최초에는 매우 강하지만 시간이 흐르면서 계속 정보가 쏟아져 들어올 경우 집중력이 점차 떨어지게 된다.
    학교다닐 때 듣기 평가시간을 기억해보면 이해가 될 것이다. 대개 들려주는 지문의 처음부분은 잘 들리지만 뒤로 갈 수록 제대로 듣지 못한다. 비록 시각장애인들의 청각 집중력이 높고, TTS들도 빠르지 않게 읽어주지 않더라도 title이 길어지면 그것을 듣는데 피로해진다.
    타이틀에서 중요한 것은 문서의 제목인데, 정작 중요한 제목은 한참뒤에 나온다면 얼마나 불편하겠는가.

    따라서 기존의 경로형식 대신 역경로형식을 쓰는 것도 좋은 방법이다.
    "올바른 타이틀 작성법 : WebStandard Archive : 블로그 : DNZIN" 이런 식으로 거꾸로 놓으면 가장 중요한 문서제목이 먼저 들리므로 시각장애인들의 어려움을 조금 덜어줄 수 있다.

    그러나 좌에서 우로 읽기가 익숙한 사람들에게 저런 형태는 왠지 불편할 수도 있다. 그런 경우에는 두 방식을 혼용해서
    "올바른 타이틀 작성법 : DNZIN : 블로그 : WebStandard Archive" 처럼 써주는 방법도 있겠다.


    Bonus.
    위의 예에서는 언어를 혼용해서 타이틀을 썼는데 실은 언어를 혼용해서 쓰는 건 그다지 좋은 방법이 아니다. 특히 국내용으로 만드는 사이트라면 되도록이면 한글을 써주자. 국내의 TTS들은 외국어 처리가 그다지 매끄럽지 않기 때문에 외국어가 포함되어있을 경우 틀린 발음으로 읽거나 혹은 아예 철자만 불러주곤 한다. 그러니 되도록이면 다른 나라 언어는 사용을 자제하고, 꼭 써야겠다면 한글발음을 병기해주는 것이 좋다. HTML 제작시에 lang 옵션을 일일이 지켜주지 않을 바에야 말이다. (실상 본인도 일일이 lang옵션 주기는 불가능. 게다가 lang옵션을 준다 한들 TTS가 제대로 읽어준다는 보장도 없고.)