|
|
IT 2009/02/05 13:35
참고 : 이 글은 http://blog.gloridea.net/1165540616#comment3445356 에 대한 답변성 글입니다. : )
arguments가 deprecated 되었다고 하셔서 깜짝 놀랐네요 -ㅅ-; 그럴리가! 라고 ㅋㅋ;
찾아보니, Function.prototype.arguments 라는 프로퍼티가 deprecated 된 것이더군요. (함수 내부 스코프 체인에 추가되는 arguments 객체 자체는 계속 사용할 수 있습니다.) 이런 형태는 다음과 같이 사용합니다.
function plus(x, y) {
console.log(plus.arguments)
return x + y;
}
plus(1, 2);
위 코드를 돌려보시면
function plus(x, y) {
console.log(arguments)
return x + y;
}이 코드와 동일하게 동작합니다.
Function.prototype.arguments를 사용할 경우, function literal 표현에서는 자신의 arguments를 구하기가 매우 난감해지겠죠. 위와 같이 named function이야 자기 이름 적어주면 되지만... 그렇지 않다면 다음과 같이 해야 할겁니다. 외부에 반드시 자신의 레퍼런스가 있어야 하죠. 그것도 lexical scope에...
var plus = function(x, y) {
console.log(plus.arguments);
return x + y;
}
또 하나의 문제. 그런데 이걸 객체의 프로퍼티로 등록할 때는 어떻게 할 수 있을까요?
var MyNumber = $Class({
$init: function(x) {
this.value = x;
}
plus: function(y) {
console.log(this.plus.arguments);
return this.value + y;
}
})
이렇게 하면 됩니다만...
call/apply 등과 엮이면 꽤 귀찮아집니다.
var MyOtherNumber = $Class({
$init: function(x) {
this.value = x;
}
});
var num2 = new MyOtherNumber(1);
MyNumber.prototype.plus.call(num2, 2);
// "TypeError: this.plus is undefined" will be raised
function이 독립적인 객체로서 call/apply 등을 통해 다른 객체의 스코프에서 사용될 수 있음을 감안하면
Function.prototype.arguments 때문에 코드의 자유도가 현저히 떨어집니다.
이러한 이유로 아마 Function.prototype.arguments 에서는 제거되고 arguments가 function 내부에서 자동으로
scope chain 내에 포함되는 형태로 바뀐 것으로 보여집니다. 아마 꽤 옛날 일일듯...
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540617
IT 2009/01/28 15:11
arguments나 array-like object 를 Array 로 변환하기 위해서는 보통 아래의 방법을 사용한다.
그러나 이전에 언급한 IE에서 다른 프레임의 Array를 받지 못하는 문제는 여기서도 동일하게 발생한다.
Array.prototype.slice.call(results) 역시 'JScript 객체가 필요합니다.' 라는 에러를 낸다. 분명히 results 객체에 length property가 있음에도 불구하고. ECMA-262 Specification을 뒤져봐도 call이 받아야 하는 객체의 유형 제한에 대한 얘기는 없다.
위 방법은 아래와 같은 arguments 객체나 기타 array-like object 에는 잘 통한다.
Array.prototype.slice.call(arguments);
Array.prototype.slice.call({0:123, 1:456, length:2});
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540616
IT 2009/01/27 16:47
IE에서 apply는 Array 의 인스턴스, 혹은 Arguments 객체만을 받는다. array-like object 등을 받지 못한다. 여기서 말하는 Array는 window.Array만을 말한다. 다른 window의 Array 인스턴스 또한 받지 못한다는 의미이다.
ECMA-262 Specification에는 다음과 같이 되어 있다.
15.3.4.3 Function.prototype.apply (thisArg, argArray)
(전략) if argArray is neither an array nor an arguments object (see 10.1.8), a TypeError exception is thrown.
출처 : ECMAScript Language Specification (pdf)
위에서 언급된 arguments object (10.1.8)은 function에 진입했을 때 자동으로 생성되는 arguments 객체를 말한다. 그러므로 엄격히 해석하자면, 명세상으로는 exception이 던져지는 것이 맞다. 그러나 다른 모든 브라우저는 apply가 array-like object 를 인자로 받아도 정상적으로 처리한다.
아래와 같은 구조일 때 IE에서는 'JScript 객체가 필요합니다.' 라는 에러를 낸다. iframe인 경우도 마찬가지다.
parent.html
window.open("search.html");
var dummy = {
callback: function(results) {
this.foo.apply(this, results);
},
foo: function(arg1, arg2, arg3) {
alert(arg1 + " : " + arg2 + " : " + arg3);
}
}
search.html
function applyResult() {
var results = [1, 2, 3];
opener.dummy.callback(results);
}
결국 search.html에서 받은 Array를 현재 창의 Array로 바꿔줘야 하는데, 일반적으로는 Array.prototype.slice 를 사용한다. 그러나 IE에서는 다른 창에서 받은 Array에 대해 이마저도 사용할 수 없다.
그나마도 다른 창에서 받은 객체를 사용할 때는 이런저런 추가적인 문제가 있다. 당시 너무 정황이 없어서 잘 기억은 안 나지만. 해결책은,
- 객체를 deep copy 하는 메서드를 만들어서 객체를 복사해서 쓰거나,
- JSON 문자열로 만들어서 받거나. (객체에 함수 등이 달려있는 경우만 아니라면, 이쪽을 더 추천.)
뭐, 그렇다능.
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540603
IT 2009/01/24 17:11
티스토리에서 소스코드 문법 하이라이팅을 위해서 보통 Syntax Highlighter를 많이 사용한다. 그러나 입력할 때 HTML 소스에 직접 손을 대야 하기 때문에, 상당히 괴롭다. 그래서 일전에 티스토리에 SyntaxHighlighter 마크업 자동 적용 북마클릿이라는 걸 만들었는데, 발로 만들다보니 여러 문제가 있었다.
- 티스토리의 새 에디터에서는 사용할 수 없었다.
- 소스 수정 후에는 저장하기 전에 [소스코드의 BR 제거] 를 반드시 한 번 실행시켜줘야 했다.
깜빡 잊고 그냥 저장하면 개떼같이 둘러 싼 HTML 태그를 볼 수 있었다. (한 건망증 하는 나는 항상 잊었다.)
- 미리보기/임시저장 등에는 적용되지 않았다.
그래서 전면적으로 손을 좀 봤다. 티스토리의 새 에디터용이다. 물론 아직까지 Firefox만 지원(-_-;;)한다.
사용방법
- Syntax Highlighter 를 적용할 소스코드를 입력하고 SyntaxHighlight Helper 북마클릿을 클릭한다.
- Syntax Highlight Helper가 로딩되면 소스코드를 블럭 지정하고 새로 생긴 적용 아이콘을 클릭한다.
- 저장하면 보기 화면에서 Syntax Highlighter가 적용된 소스코드를 볼 수 있다.
- 수정 모드로 진입하면 처음에는 SyntaxHighlight Helper가 적용되어 있지 않다. 이 때는 소스코드 영역의 배경색이 회색으로 보인다. 이는 Syntax Hightlight Helper를 로딩해야 한다는 것을 상기시켜주기 위함이다. (이 상태로도 소스코드 수정이 불가능하지는 않으나, 엔터 등을 입력하고 저장하면 소스코드 영역에서 태그가 달라붙는다.)
- 다시 북마클릿을 클릭해서 Syntax Highlight Helper를 로딩하면 소스코드 영역의 배경색이 원래대로 돌아온다.
설치
- 첨부한 syntax_highlight_finder.js 와 syntax_highlight_helper.js 를 다운로드 받는다. (아래 아이콘 클릭)
- Syntax Highlighter 설치와 동일하게 스킨 파일 업로드 하는 곳에 업로드한다.
(스킨 > HTML/CSS 편집 > 파일 업로드 에서 업로드할 수 있다.)
- 스킨 > HTML/CSS 편집 > HTML/CSS 편집에서 SyntaxHighlighter 스크립트 태그를 추가한 바로 밑에
<script class="javascript" src="./images/syntax_highlight_finder.js"></script>
한 줄을 더 추가하고 저장한다.
- 아래 북마클릿을 우클릭하여 즐겨찾기로 지정한다.
시간 나면 조금 더 해보고 싶은 것들.
- 소스코드 영역 내에서 엔터 입력시 <p>등의 마크업이 추가되는데, 이것을 원천적으로 차단하기.
- 현재는 저장 시점에 걸러내고 있음.
- 시도는 해봤는데, 편집모드에서는 keypress 등의 이벤트 핸들러가 잘 안 먹는다. 뭐가 문젤까...
- 다른 브라우저에서도 쓸 수 있게 고치기.
- 하지만 수많은 예외상황과 맞짱 뜨기 귀찮다. orz
- 현재 언어 기본값이 무조건 javascript로 되어 있는 부분을 cookie 기반으로 마지막에 사용한 언어를 표시하도록 수정.
- 더 좋은 걸 바란다면... 현재는 소스코드 영역 입력 시 highlight 할 언어 종류를 prompt에 입력하게 되어있는데, 레이어라던가 좀 더 깔끔한 방법으로 처리해보기.
... 그러나 저 위의 일들... 별로 할 것 같지는 않다. 이미 내가 사용하는데는 충분히 편리한 상태가 되었으므로. ;; 그래도 열화와 같은 성원(... 같은게 있을리가.)이 있다면 고려를 해볼수도...
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540615
IT 2008/08/18 15:03
티스토리에 Syntax Highlighter 를 적용하는 방법은 꽤 많이 찾아볼 수 있다. 다만 문제는 편집할 때 이를 적용하는 게 정말 끔찍할 정도로 힘이 든다는 것이다. 두어번 해보고 나면 다신 해보고 싶지 않을 정도로... 텍스트 편집 모드로 전환해서 하이라이팅 적용할 곳에 pre나 textarea를 적용하고... class 적어주고, name 적어주고... 아무리 읽는 사람의 편의를 고려한다고 해도 이건 쓰는 사람이 너무 고통스럽다. 그래서 북마클릿 형태로 만들었다. -,.- 1. SyntaxHighlighter (javascript) 적용: 이 링크를 우클릭하여 북마크에 추가한다. 2. 글쓰기 모드로 진입한다. 3. 코드를 써넣거나 붙여넣는다. 4. SyntaxHighligher를 적용할 블럭을 드래그하여 선택한다. 5. 저장해둔 북마크를 클릭한다. 이렇게 하면 선택한 텍스트의 태그가 모두 없어지고, 텍스트가 파란 박스 안에 들어간다. 이 파란 박스는 <pre>태그로, 에디터상에서 소스 영역을 구분하기 위해 색을 넣었다. 읽기 화면에서 SyntaxHighligher가 적용되어 보여질 때는 이 선이 보이지 않는다. 이제 좀 코드 입력할 맛 난다. 기본적으로 위 북마클릿은 자바스크립트용이다. 다른 버전은 다음과 같다.
1. C++2. C#3. CSS4. Delphi5. Java6. Javascript7. PHP8. Python9. Ruby10. SQL11. VB12. XML/HTML이걸 모두 다 북마크하는 게 답답하다면, prompt 창으로 언어를 입력 받는 버전을 사용해도 된다. 대신 매번 언어를 적어주는 수고를 감수해야 -,.-; 중요한 건! 이 모든 기능이 Firefox 용이라는 점이다. -,.- IE용은 차차 만들어볼 예정.... (믿거나 말거나) 소스코드 : javascript:(function() {
var _ed = document.getElementById('tatterVisualEditor');
var _cw = document.createElement('pre');
_cw.style.border = '1px dotted red';
_cw.setAttribute('name', 'code');
_cw.className = 'javascript';
_ed.contentWindow.getSelection().getRangeAt(0).surroundContents(_cw);
_cw.innerHTML = _cw.innerHTML.replace(/(<\/?p>|<br.*?>)/g, '\n').replace(/<.*?>/g, '');
})();추가 : <pre> 태그 내에 글을 작성해도 엔터를 치면 자동으로 <br \>이 삽입되어 원하는 개행문자 대신 태그가 출력되는 문제가 있다. 이를 해결하기 위해서 북마클릿을 하나 더 만들었다. <pre name="code"> </pre> 안에 있는 <br />들을 모두 찾아 개행문자로 바꿔주는 북마클릿이다. 소스상의 <br />은 건들지 않는다. 꼭 소스를 고치지 않았더라도 HTML 편집모드를 한 번이라도 들어갔다가 나왔을 경우 (나오지 않고 바로 저장하면 상관없지만) BR이 자동으로 붙으므로, 제거해주고 저장해야 한다. 한 번 클릭하면 편집 영역에 있는 모든 소스코드의 BR을 개행문자로 바꿔준다. 추가하는 방법은 위와 동일하다. 소스코드의 BR 제거소스코드 : javascript:(function(){
var _ed = document.getElementById('tatterVisualEditor');
var _pres = _ed.contentWindow.document.getElementsByTagName('pre');
for (var i = 0; i < _pres.length; i++) {
if (_pres[i].getAttribute('name') != 'code') continue;
var _brs = _pres[i].getElementsByTagName('br');
for (var j = _brs.length - 1; j >= 0; j--) {
_brs[j].parentNode.replaceChild(document.createTextNode('\n'), _brs[j]);
}
}
})();
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540575
IT 2007/12/28 11:43
어떤 새로운 것을 배우는 건 많은 시행착오를 필요로 한다. 그 시점에는 모든 관심이 문제 해결에 맞춰져 있어서, 다른 작업을 등한시 하기 쉽다. 종종 내가 새로 배운 것들을 블로깅 하려고 해도 처음부터 모든 내용을 다시 정리해서 올려야 한다는 부담감에 미루게 되는 경우가 제법 많다. 가령, 어떤 프로그램을 설치하고 사용하는 방법에 대해 블로깅한다고 가정할 때, 한 번에 되는 경우보다는 여러 시행착오를 겪어야 할 경우가 많은데, 이 경우, - 열심히 한 단계씩 정리해가며 진행하다가 문제에 부딪혀서 수정을 해야 하거나
- 한 번 성공한 뒤 설치한 걸 다 지우고 다시 설치하면서 글을 정리하거나
해야 하는데, 이게 말처럼 쉬운 일은 아니다. 특히 화면이라도 캡쳐해서 넣고 했다가 다시 수정해야 하는 날에는 "돈 떨어지는 것도 없는데 왜 내가 이런 짓을 하고 있지?" 하는 회의감이 들기도 한다. 갑자기 원노트에 어떤 주제에 대해 정리하다가 이러한 문제를 좀 더 쉬운 일로 만들 방법이 떠올랐다. 원노트 2007에서는 바로 블로깅이 가능하다. 게다가 편집도 쉽다. 캡쳐를 뜨는 것도 화면 캡쳐 후 바로 붙여넣으면 된다. 학습 과정과 정리 과정 사이의 갭을 줄여 동시 진행이 가능하도록 해준다. 그리고나서 최종적으로 성공하면 글을 손봐서 바로 블로깅을 하면 된다. 한 번 시도해봐야겠다. :-) 요 근래의 관심사는 aptana + scriptdoc 과 mylyn 이다.
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540468
IT 2007/11/09 04:41
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="/a/a.js"></script> <script type="text/javascript" src="/a/b/b.js"></script> <script type="text/javascript" src="/c/d.js"></script> </head> <body> </body> </html>위와 같은 코드가 있을 때, 두번째로 로딩된 /a/b/b.js 는 과연 자신의 위치를 어떻게 알 수 있을까? location 객체를 아무리 찍어봐도 절대로 html의 위치만 나오지 b.js 자신의 위치는 나오지 않는다. 앞서 글에서 언급했듯, HTML이 파싱될 때 태그는 하나씩 파싱되어 DOM 리스트에 추가된다. 그러므로 document.getElementsByTagName("script") 의 결과로 반환되는 콜렉션에는 항상 현재 스크립트가 가장 마지막 요소일 수밖에 없다. 이를 활용한 다음 코드를 통해 js 내에서 자신의 위치를 알아내는 코드를 작성할 수 있다.
function getJsBasePath() { var scriptList = document.getElementsByTagName("script"); var fileName = scriptList[scriptList.length - 1].src; var isAbsolute = fileName.charAt(0) == "/"; var loc = window.location; var url = loc.protocol + "//" + loc.host; if (!isAbsolute) { url += loc.pathname; if (loc.protocol == "file:") { url = url.replace(/\\/g, "/") } url = url.substring(0, url.lastIndexOf("/") + 1) }
return url; } 이렇게 하면 비로소 파일간의 include 가 가능해진다. 이 js 를 부른 곳이 어느 경로이건간에 현재의 js의 위치를 기준으로 다른 js를 부를 수 있기 때문이다. IE6, FF2에서 테스트하였다.
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540451
IT 2007/11/09 03:45
이 내용은 오래전부터 관심을 가지고 간간히 생각해오다가 어제 갑자기 생각난 부분인데, 예전에 dojo툴킷을 쓸 때 비슷한 활용을 본 것 같아서 방금 dojo 툴킷 소스를 받아 열어보니, 역시나.... 기본적인 구현 아이디어가 같다. 이걸 좋아해야 하나.. 말아야 하나. 여하튼 유사한 구조를 따름을 미리 밝혀둔다. 여튼 이해의 차원에서 글을 적어본다.
대부분의 언어에서는 자신이 사용할 기능이 선언된 다른 파일을 부르는 명령이 존재한다. php에는 include / require 가 있고, java 에는 import가 있다. (둘이 성격이 같다는 이야기는 아니다.)
그러나 javascript 에는 include 문이 없다. 그래서 한 js 파일(a.js)에서 다른 js 파일(b.js)에 구현된 스크립트를 가져다 쓰기 위해서는 해당 js 파일을 호출한 html 페이지에서 a.js 와 b.js 모두를 호출해주어야 한다. 이는 실제로 사용할 대상에만 관심을 두는 원칙에 위배된다.
따라서 여타의 js를 include 하는 방법이 필요하다. dojo의 경우 이러한 문제를 해결하기 위해 다음과 같은 선언의 형태로 활용할 수 있도록 만들어졌다. 아래의 예제는 dojo 툴킷 중 TabContainer의 로딩 예제이다.
<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js" djConfig="parseOnLoad: true"></script> <script type="text/javascript"> dojo.require("dojo.parser"); dojo.require("dijit.layout.ContentPane"); dojo.require("dijit.layout.TabContainer"); dojo.require("dijit.form.Button"); </script>
특정 js 파일에서 다른 js 파일을 참조하기 위해서는 필요한 js를 먼저 로딩할 수 있어야 한다. 이러한 방법에는 몇 가지가 알려져 있다.
- script 엘리먼트를 만들어서 현 문서에 추가한다. (A)
var scr = document.createElement("script"); scr.src = "a.js"; document.getElementsByTagName("head")[0].appendChild(scr);
- document.write / innerHTML을 이용한 직접 태그를 추가한다. (B)
document.write("<script type='text/javascript' src='b.js'><"+"/script>");
- 기타 등등.. (현재 기억 안남)
그러나 위의 방법 중 어떠한 것을 사용해도 수행의 순서를 원하는대로 제어할 수는 없다. 파싱은 기본적으로 다음과 같은 순서로 진행된다. 설명에 사용될 call.js 에는 위에서 설명한 스크립트를 로딩하는 루틴이 모두 포함되어 있다고 가정한다.
- html 페이지를 순차적으로 파싱한다.
- html 페이지에서 <script src="call.js">태그를 만나면 call.js 파일을 읽어들인다.
- call.js 에서 위에 설명한 방법으로 스크립트를 로딩하는 루틴 A를 만나면 call.js 파싱이 모두 끝난 후 A에서 지정한 파일을 읽어들인다.
- call.js 내에서 루틴 B를 만나면 html 페이지를 모두 파싱한 후에야 B에서 지정한 js 파일을 읽어들인다.
call.js : (A 루틴) (B 루틴) window.alert("call.js");
a.js : window.alert("a.js");
b.js : window.alert("b.js");
라고 각각 쓰여져 있으면, alert이 나타나는 순서는 call.js, a.js, b.js 순서이다. 아무리 A루틴과 B루틴이 call.js 를 표시하는 루틴보다 앞에 있지만, 파싱 순서상 절대 앞에 나오지 않는다.
즉, 위의 방법으로는 어떤 방법을 써도 브라우저는 먼저 현 페이지의 스크립트를 파싱하고 진행한다.
수행제어를 위한 유일한 돌파구는 SJAX 이다 (비동기가 AJAX니까... ;; 동기식은 S(ynchronous)JAX ;;;) 아래 코드는 IE6, FF2.0에서 테스트되었다. (참고로, dojo 소스를 보아하니 ipv6관련 지원 문제로 uri 파싱도 수정이 가해져야 하는 듯하다. 오마이갓.)
활용은 다음과 같은 형태로 한다. eval(require_once("/some_path/some.js", true));
해결해야 할 과제.
- 어떻게 하면 eval을 쓰지 않게 할 수 있는지.
해결된 과제
- require 대상 js 파일의 경로를 이 js 파일로부터 어떻게 하면 상대경로로 잡을 수 있는지.
function require(jsFile, alwaysReload) { var url = "http://" + location.host + jsFile; var xhr = null; var jsSource = ""; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
if( xhr ){ xhr.open('get', jsFile, false); xhr.send(null); jsSource = xhr.responseText; } return jsSource; }
function require_once(jsFile, alwaysReload) { if (typeof(document.required_list) == "undefined") { document.required_list = new Array(); } var isExist = false; for (var i = 0; i < document.required_list.length; i++) { if (document.required_list[i] == jsFile) { isExist = true; break; } } if (!isExist) { document.required_list.push(jsFile); var param = (alwaysReload) ? "?hash=" + Math.random() : ""; return require(jsFile + param, require_once); } else { return ""; } }
XMLHttpRequest를 사용한다고 해서 특별히 성능상의 문제가 발생하지는 않는다. 동기식 통신의 부하는 어차피 <script src="..."> 태그를 썼을때와 동일하다. HTML파서는 서버로부터 HTML을 수신받고 파싱하다가 이 태그를 만나면 해당 src에 선언된 주소에서 파일을 가져오는데, 이 파일을 다 가지고 와서 파싱해야지만 다음 엘리먼트를 파싱한다. 외부 js 호출과 소스 파싱은 절대 비동기가 아니다. 즉, 거의 동일한 성능상의 부하를 가진다.
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540450
IT 2007/11/01 10:29
JDK 1.5 이상에서 컴파일 시 다음과 같은 에러가 발생하는 경우가 있다. warning: non-varargs call of varargs method with inexact argument type for last parameter; [javac] cast to java.lang.Object for a varargs call [javac] cast to java.lang.Object[] for a non-varargs call and to suppress this warning [javac] sb = (StringBuffer) method.invoke(obj, new SomeObject[] { someObject }); [javac] ^ [javac] Note: Some input files use unchecked or unsafe operations. [javac] Note: Recompile with -Xlint:unchecked for details. [javac] 1 warning
에러 메시지에 써있듯, Object[] 가 아닌 SomeObject[] 형 인자를 넘겨서 발생한 문제이다. 해당 라인을 아래와 같이 수정한다. sb = (StringBuffer) method.invoke(obj, new Object[] { someObject });
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540437
IT 2007/10/12 02:26
요근래, SMTP/POP3가 지원되는 대형 포털의 메일 계정을 필요로 하고 있었다. 기본적으로 Google Apps 에다가 개인 도메인을 설정해서 메일을 사용하고 있지만, gmail은 느리다! 이건 꽤 심각한 문제였다. 업무상 첨부파일을 주고받을 일이 꽤 많기 때문이다. 그런데 다음은 프리미엄 메일에서만 SMTP/POP3 제공이 되고, 네이버에서는 으뜸사용자가 되어야만 제공이 되었다. 그래서 열심히 포인트를 모았다. 이달 초부터 지금까지. 끙끙. 그래서 오늘에서야 비로소 으뜸사용자가 되었다. 오늘 아침에 열심히 아웃룩을 설정했다. (네이버 으뜸사용자에 관한 설명은 로그인을 해야만 링크를 볼 수 있어 연결하지 않았음.) 그런데, 오늘 RSS를 구독하다가 한메일을 만드는 사람들의 이야기에서 한메일이 SMTP/POP3지원을 개시했다는 쇼킹한 뉴스를 접했다. 쿠궁.... 대략, OTL ....
Trackback 0
:
Trackback Address :: http://blog.gloridea.net/trackback/1165540423
|