'Information' 카테고리의 다른 글
CSS-Based Navigation Menus: Modern Solutions (0) | 2007.03.15 |
---|---|
HTML 특수문자코드 (0) | 2007.03.04 |
HTTP 에러 코드 및 내용 (0) | 2007.03.04 |
CSS-Based Navigation Menus: Modern Solutions (0) | 2007.03.15 |
---|---|
HTML 특수문자코드 (0) | 2007.03.04 |
HTTP 에러 코드 및 내용 (0) | 2007.03.04 |
|
|
비스타 하드웨어 ‘체크포인트’ (0) | 2007.03.13 |
---|---|
HTTP 에러 코드 및 내용 (0) | 2007.03.04 |
주민번호 체크 검사 (0) | 2007.03.04 |
HTTP 에러 코드표
100: Continue
101: Switching Protocols
200: OK, 에러없이 전송 성공
202: Accepted, 서버가 클라이언트의 명령을 받음.
203: Non-authoritavive Information, 서버가 클라이언트 요구중 일부만 정송
204: Non Content, 클라이언트 요구를 처리했으나 전송할 데이터가 없음.
205: Reset Content
206: Partial Content
300: Multiple Choisces, 최근에 옮겨진 데이터를 요청
301: Moved Permanently, 요구한 데이터를 변경된 임시 URL에서 찾았음.
302: Moved Permanently, 요구한 데이터가 변경된 URL에 있음을 명시.
303: See Other, 요구한 데이터를 변경하지 않았기 때문에 문제가 있음.
304: Not modified
305: Use Proxy
400: Bad Request, 요청실패
문법상 오류가 있어, 서버가 요청사항을 이해하지 못함, 클라이언트는 수정없이 요청사항을 반복하지 않을 것이다.
401.1: Unauthorized, 권한 없음 (접속실패)
이 에러는 서버에 로그온 하려는 요청사항이 서버에 들어있는 권한과 비교했을 때 맞지 않을 경우 발생한다. 이 경우, 여러분이 요청한 자원에 접근할 수 있는 권한을 부여받기 위해 서버 운영자에게 요청해야 할 것이다.
401.2: Unauthorized, 권한 없음(서버설정으로 인한 접속 실패)
이 에러는 서버에 로그온 하려는 요청사항이 서버에 들어있는 권한과 비교했을 때 맞지않을 경우 발생한다. 이것은 일반적을 으로 적절한 www-authenticate head field를 전송하지 않아서 발생한다.
401.3: Unauthorized, 권한 없음(자원에 대한 ACL에 기인한 권한 없음)
이
에러는 클라이언트가 특정 자원에 접근할 수 없을 때 발생한다. 이 자원은 페이지가 될 수도 있고 , 클라이언트의 주소 입력란에
명기된 파일일 수도 있다. 아니면 클라이언트가 행당 주소로 들어갈 때 이용되는 또 다른 파일일 수도 있다. 여러분이 접근할 전체
주소를 다시 확인해 보고 웹 서버 운영자에게 여러분이 자원에 접근할 권한이 있는지를 확인해 본다.
401.4: Unauthorized, 권한 없음(필터에 의한 권한 부여 실패)
이 에러는 웹 서버가 서버에 접속하는 사용자들을 확인하기 위해 설치한 필터 프로그램이 있음을 의미한다. 서버에 접속한는 데 이용되는 인증 과정이 이런 필터 프로그램에 의해 거부되었다.
401.5: Unauthorized, 권한 없음(ISA PI/CGI 애플리케이션에 의한 권한부여 실패)
이 에러는 여러분이 이용하려는 웹 서버의 어드레스에 ISA PI나 CGI프로그램이 설치되어 있어 사용자의 권한을 검증하고 있음을 의미한다. 서버에 접속하는 데 이용되는 인증 과정이 이 프로그램에 의해 거부되었다.
402: Payment Required, 예약됨.
403.1: Forbidden, 금지(수행접근 금지)
이 오류는 CGI나 ISAPI,혹은 수행시키지 못하도록 되어있는 디렉토리 내의 실행 파일을 수행시키려고 했을 때 발생한다.
403.2: Forbidden, 금지(읽기 접근 금지)
이 에러는 브라우저가 접근한 디렉토리에 가용한 디폴트 페이지가 없을 경우에 발생한다. 아니면 Eecute나 Script로 분한이 부여된 디렉토리에 들어있는 HTML페이지를 보려했을 때 발생한다.
403.4: Forbidden, 금지(SSL 필요함)
이 에러는 여러분이 접근하려는 페이지가 SSL로 보안유지 되고 있는 것일 때 발생한다. 이것을 보기 위해서 여러분은 주소를 입력하기 전에 먼저 SSL을 이용할 수 있어야 한다.
403.5: Forbidden, 금지 (SSL 128필요함)
이 에러는 접근하려는 페이지가 SSL로 보안유지 되고 있는 것일 때 발생한다. 이 자원을 보기 위해서는 여러분의 브라우저가 SSL의 행당 레벌을 지원해야 한다. 여러분의 브라우저가 128비트의 SSL을 지원하는 지를 확인해 본다.
403.6: Forbidden, 금지(IP 주소 거부됨)
이 에러는 서버가 사이트에 접근이 허용되지 않은 IP주소를 갖고 있는데, 사용자가 이 주소로 접근하려 했을 때 발생한다.
403.7: Forbidden, 금지(클라이언트 확인 필요)
이 에러는 여러분이 접근하려는 자원이 서버가 인식하기 위해 여러분의 브라우저에게 클라이언트 SSL을 요청하는 경우 발생한다. 이것은 여러분이 자원을 이용할 수 있는 상용자임을 입증하는데 사용된다.
403.8: Forbidden, 금지 (사이트 접근 거부됨)
이 에러는 웹 서버가 요청사항을 수행하고 있지 않거나, 해당 사이트에 접근하는 것이 허락되지 않았을 경우 발생한다.
403.9: Forbidden, 접근 금지(연결된 사용자수 과다)
이 에러는 웹서버 BUSY 상태에 있어서 여러분의 요청을 수행할수 없을 경우에 발생한다. 잠시 후에 다시 접근해 보도록 한다.
403.10: Forbidden, 접근금지(설정이 확실 하지 않음)
이 순간 웹 서버의 설정쪽에 문제가 있다.
403.11: Forbidden, 접근금지(패스워드 변경됨)
이 에러는 사용자 확인단계에서 잘못된 패스워드를 입력했을 경우 발생한다. 페이지를 갱신한 후 다시 시도해 본다.
403.12: Forbidden, 접근금지(Mapper 접근 금지됨)
여러분의 클이언트 인증용 맵이 해당 웹 사이트에 접근하는 것이 거부되었다. 사이트 운영자에게 클라이언트 인증 허가를 요청한다. 또한 여러분은 여러분의 클라이언트 인증을 바꿀 수도 있다.
404: Not Found, 문서를 찾을 수 없음.
웹 서버가 요청한 파일이나 스크립트를 찾지 못했다. URL을 다시 잘 보고 주소가 올바로 입력되었는지 확인해본다.
- 해결방법: a.도구 ▶ 인터넷옵션 ▶ 일반 ▶ 쿠키삭제, 파일삭제, 목록지우기
b.도구 ▶ 인터넷옵션 ▶ 고급 ▶ [URL을 항상 UTF-8FH로 보냄] 체크 해제.
405: Method not allowed, 메쏘드 허용안됨
Request 라인에 명시된 메쏘드를 수행하기 위해 해당 자원의 이용이 허용되지 않았다. 여러분이 요청한 자원에 적절한 MIME 타입을 갖고 있는지 확인해 본다.
406: Not Acceptable, 받아들일 수 없음
요청 사항에 필요한 자원은 요청 사항으로 전달된 Acceptheader에 따라 "Not Acceptable"인 내용을 가진 Response 개체만을 만들 수 있다.
407: Proxy Authentication Required, 대리(Proxy) 인증이 필요함
해당 요청이 수행되도록 proxy 서버에게 인증을 받아야 한다. proxy서버로 로그온 한 후에 다기 시도해 본다.
408: Request timeout, 요청시간이 지남
409: Conflict
410: Gone, 영구적으로 사용할 수 없음.
411: Length Required
412: Precondition Failed, 선결조건 실패
Request-header
field에 하나 이상에 선결조건에 대한 값이 서버에서 테스트 결과 FALSE로 나왔을 경우에 발생한다. 현재 자원의
메타-정보가 하나 이상의 자원에 적용되는 것을 막기 위한 클라이언트 선결조건이 의도되어졌다.
413: Request entity too large
414: Request-URI too long, 요청한 URI가 너무 길다
요
청한 URI가 너무 길어서 서버가 요청 사항의 이행을 거부했다. 이렇게 희귀한 상황은 아래와 같은 경우에만 발생한다.
클라이언트가 긴 탐색용 정보를 가지고 POST 요청을 GET으로 부적절하게 전환했다. 클라이언트가 Redirection문제를
접하게 되었다. 서버가, 몇몇 서버가 사용하고 있는 요청한 URI 를 읽고 처리하는 고정된 길이의 메로리 버퍼를 이용해
보안체계에 들어가려는 , 클라이언트에 의한 공격을 받고 있다.
415: Unsupported media type
500: Internal Server Error, 서버 내부 오류
웹 서버가 요청사항을 수행할 수 없다. 다시 한 번 요청해 본다.
501: Not Implemented, 적용안됨
웹 서버가 요청사항을 수행하는 데 필요한 기능을 지원하지 않는다. 에러가 발생한 URL을 확인한 후에, 문제가 지속될 경우에는 웹 서버 운영자에게 연락한다.
502: Bad gateway, 게이트웨이 상태 나쁨/서버의 과부하 상태
Gateway나 proxy로 활동하고 있는 서버가 요구 사항을 접수한 upstream 서버로부터 불명확한 답변을 접수 했을 때 발생한다. 만약 문제가 지속된다면 웹 서버 운영자와 상의해 본다.
503: Service Unavailable, 외부 서비스가 죽었거나 현재 멈춘 상태 또는 이용할 수 없는 서비스
서버는 현재 일시적인 과부하 또는 관리(유지,보수) 때문에 요청을 처리할 수 없다.
이것은 약간의 지연후 덜게될 일시적인 상태를 말한다.
Retry-After 헤더에 지연의 길이가 표시하게 될지도 모른다.
만
약 Retry-After를 받지 못했다면 클라이언트는 500 응답을 위해 하고자 했는것처럼 응답을 처리해야 한다. 상태코드의
존재는 서버가 과부하가 걸릴때 그것을 사용해야한다는 것을 말하는 것이 아니다. 몇몇 서버는 접속을 거부하는 것을 바랄지도 모른다.
504: Gateway timeout
505: HTTP Version Not SupportedHTML 특수문자코드 (0) | 2007.03.04 |
---|---|
주민번호 체크 검사 (0) | 2007.03.04 |
Window객체의 속성 (0) | 2007.03.04 |
[미리보기]
주민번호 검사는 회원가입시에 주로 많이 쓰인다.
하지만 100%검사는 되지 않고 다만 잘못된 형태의 주민번호는 검사할수 있다.
주민번호 생성기로 만들어진 주민번호는 체크가 되지 않는다.
그것까지 체크할려면 실명인증 서비스를 제공하는곳에 서비스를 신청하여야 한다. 그건 가격이 비싸다. -,-
<script language="javascript">
<!--
//주민등록번호 검사
function jumin_check() {
if (document.myform.jumin1.value.length != 6) { // 앞번호가 6개 아니라면
alert("앞번호의 개수가 모자랍니다. 더 적으세요.^^");
document.myform.jumin1.focus(); //커서를 주민번호 앞자리에 놓는다.
return false;
} else if (document.myform.jumin2.value.length != 7) { //뒷자리가 7개가 아니라면
alert("뒷번호의 개수가 모자랍니다. 더 적으세요.^^");
document.myform.jumin2.focus(); //커서를 주민번호 뒷자리에 놓는다.
return false;
} else {
var strjumin1 = document.myform.jumin1.value; //변수에 주민번호 앞자리 담음
var strjumin2 = document.myform.jumin2.value; //변수에 주민번호 뒷자리 담음
var digit=0
for (var i=0;i<strjumin1.length;i++) { //주민번호 앞자리의 길이만큼 for문을 돌린다.
var strdigit=strjumin1.substring(i,i+1); //앞자리중 i번째와 i+i번째 문자를 변수에 담는다.
if (strdigit<'0' || strdigit>'9') { //strdigit 의 값이 0보다 작거나 9보다 크면
digit=digit+1 //digit에 1을 더한다.
}
}
if ( digit != 0 ) { //digit가 0이 아니라면
alert('주민등록번호에는 0에서 9까지의 숫자만 적을 수 있습니다.\n\n다시 확인하고 입력해 주세
요.');
document.myform.jumin1.focus();
return false;
}
var digit1=0
for (var i=0;i<strjumin2.length;i++) { // 주민번호 뒷자리의 길이만큼 for문을 돌린다.
var strdigit1=strjumin2.substring(i,i+1);
if (strdigit1<'0' || strdigit1>'9') {
digit1=digit1+1
}
}
if ( digit1 != 0 ) {
alert('주민등록번호에는 0에서 9까지의 숫자만 적을 수 있습니다.\n\n다시 확인하고 입력해 주세
요.');
document.myform.jumin2.focus();
return false;
}
if (strjumin1.substring(2,3) > 1) { //주민번호 월 부분의 첫째 숫자가 1보다 클경우
alert('잘못될 \'월\'을 입력했습니다.\n\n다시 확인하고 입력해 주세요.');
document.myform.jumin1.focus();
return false;
}
if (strjumin1.substring(4,5) > 3) { //주민번호 일 부분의 첫째 숫자가 3보다 클경우
alert('잘못된 \'일\'을 입력했습니다.\n\n다시 확인하고 입력해 주세요.');
document.myform.jumin1.focus();
return false;
}
if (strjumin2.substring(0,1) > 4 || strjumin2.substring(0,1) == 0) { //주민번호 뒷자리의 첫째숫자가
4보다 클경우
alert('주민등록번호에서 성별을 나타내는 숫자는 1에서 4까지입니다.\n\n다시 확인하고 입력해 주
세요.');
document.myform.jumin2.focus();
return false;
}
var a1=strjumin1.substring(0,1) //주민번호 계산법
var a2=strjumin1.substring(1,2)
var a3=strjumin1.substring(2,3)
var a4=strjumin1.substring(3,4)
var a5=strjumin1.substring(4,5)
var a6=strjumin1.substring(5,6)
var checkdigit=a1*2+a2*3+a3*4+a4*5+a5*6+a6*7
var b1=strjumin2.substring(0,1)
var b2=strjumin2.substring(1,2)
var b3=strjumin2.substring(2,3)
var b4=strjumin2.substring(3,4)
var b5=strjumin2.substring(4,5)
var b6=strjumin2.substring(5,6)
var b7=strjumin2.substring(6,7)
var checkdigit=checkdigit+b1*8+b2*9+b3*2+b4*3+b5*4+b6*5
checkdigit = checkdigit%11
checkdigit = 11 - checkdigit
checkdigit = checkdigit%10
if (checkdigit != b7) {
alert('잘못된 주민등록번호입니다.\n\n다시 확인하고 입력해 주세요.');
document.myform.jumin1.value=" ";
document.myform.jumin2.value=" ";
document.myform.jumin1.focus();
return false;
}
}
return true;
}
//-->
</script>
<form name = "myform" action="aa.asp" onsubmit="return jumin_check()">
주민번호 :
<input name="jumin1" value="" type="text" size="6" maxlength="6">-<input name="jumin2" value=""
type="text" size="7" maxlength="7">
<input type="submit" name="button" value="확인">
</form>
HTTP 에러 코드 및 내용 (0) | 2007.03.04 |
---|---|
Window객체의 속성 (0) | 2007.03.04 |
하룻동안 창 띄우지 않기 (0) | 2007.03.04 |
브라우져 내장객체 - Window | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 Window객체의 속성 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1.1 예제[Status] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 Window객체의 메소드 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2.1 예제[alert()] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2.2 예제[open(), close()] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2.3 예제[setTimeout(), clearTimeout()] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2.4 예제[resizeBy(), resizeTo()] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2.5 예제[moveBy(), moveTo()] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2.6 예제[print()] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2.7 예제[scrollBy(), scrollTo()] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3 Window객체의 이벤트 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
브라우져 내장객체가 무었인지... 왜 이것을 알아야 하는지... 궁금하시죠...^^*
이제 이번장에서 배우게될 Window객체의 속성에 대하여 알아볼까요...^^* Window 객체의 속성
위 Window객체의 속성을 살펴보면 주로 브라우저화면 상태를 제어하는 기능과 화면의 특정부분에 표시될 내용을 지정하는 기능들로 구성되어 있는것을 보실 수 있습니다. 아직까지는 아니 앞으로도 언제가 되어질지는 모르겠지만 익스플로러와 넷스케이프등 동시에 호환되지 않는 속성및 메소드가 많이 존재하니 홈페이지 제작시 참조하여 사용하시기 바랍니다. 자!~~~ 그럼 예제를 한번 만들어 볼까요...^^* 상태바를 제어하는 예를 들어 보겠습니다. [ Window 객체의 속성 예제 ] - 실행화면 보기 ... [ TOP ] <html> <head> <title>자바스크립트 예제</title> <script> <!-- function statusTest(Num) { switch(Num) { case 1 : window.status="[1]번을 클릭하셨습니다...^^*"; break; case 2 : window.status="[2]번을 클릭하셨습니다...^^*"; break; case 3 : window.status="[3]번을 클릭하셨습니다...^^*"; break; } } //--> </script> </head> <body onLoad="window.defaultStatus='상태바를 테스트 합니다.'"> <center> <br><br><br> 하단의 상태바를 참조하세요...^^* <br><br> <input type="button" value="클릭1" onClick="statusTest(1)"><br><br> <input type="button" value="클릭2" onClick="statusTest(2)"><br><br> <input type="button" value="클릭3" onClick="statusTest(3)"> </center> </body> </html> 위의 예제는 브라우저가 실행되면서 onLoad이벤트에 의하여 상태바에 "상태바를 테스트 합니다."라는 메세시가 출력이 되며 버튼을 클릭할때마다 해당된 메세지가 출력되는 내용입니다. window.defaultStatus는 defaultStatus로도 사용이 가능하다는것도 참고로 알아두세요. 우리가 사용하는 모든 속성및 메소드는 window객체에서 파생되었기에 "window"는 생략해도 괜챦답니다.
음!~~~ 다음은 ... window객체의 메소드 부분을 살펴볼까요!~~~^^* Window 객체의 메소드
window객체의 메소드를 보았으니...^^* 예제로 들기 쉬운 몇몇가지를 직접 작성해 보도록 하겠습니다. [ Window 객체의 메소드 - alert() ] - 실행화면 보기 ... [ TOP ] <html> <head> <meta http-equiv="CONTENT-TYPE" content="text/html;charset=euc-kr"> <title>인포카페 - 자바스크립트 예제</title> <script> <!-- function alertTest() { alert("음!~~~ 경고창이 뜨죠... 줄을 바꾸워 볼까요...\n줄이 바뀌었죠...^^*"); } //--> </script> </head> <body> <center> <br><br><br><br><br> <input type='button' value='클릭' onClick='alertTest()'> </center> </body> </html>
이번에는 새로운창을 열수 있는 open()메소드에 대해서 알아보도록 하겠습니다. 새로운 창이라 함은 예를들어 웹서핑을 다니다 보면 주로 공지사항 또는 이벤트를 알리기 위하여 몇몇개의 창이 뜨는 경우가 있죠...^^* 바로 그것을 말합니다. 물론 버튼으로도 제어가 가능하며, 이 메소드에는 여러가지의 속성들이 있는데 먼저 예제를 한번 살펴보고 그 속성에 대한 설명을 살펴보기로 하겠습니다. [ Window 객체의 메소드 - open(), close(); ] - 실행화면 보기 ... [ TOP ] <html> <head> <meta http-equiv="CONTENT-TYPE" content="text/html;charset=euc-kr"> <title>인포카페 - 자바스크립트 예제</title> <script> <!-- function newOpen(Num) { var myText=""; if(Num==1) { window.open("","newWin1","menubar=no, scrollbars=no, status=no, toolbar=no, resizable=no, width=200, height=200, top=10, left=10"); } else if(Num==2) { window.open("","newWin2","menubar=yes, scrollbars=yes, status=yes, toolbar=yes, resizable=yes, width=200, height=200, top=10, left=250"); } else if(Num==3) { newObj=window.open("","newWin3","menubar=no, scrollbars=no, status=no, toolbar=no, resizable=no, width=200, height=200, top=210, left=10"); if(newObj != null) { myText += "<html><head><title>새로운창</title></head><body>"; myText += "<center><br><br>"; myText += "새로운 창입니다.<br><br>"; myText += "<input type='button' value='새창닫기' onClick='window.self.close();'>"; myText += "</body></html>"; newObj.document.write(myText); } } } //--> </script> </head> <body> <center> <br><br><br><br><br> 첫번째 버튼은 새창을 열지만 툴바 상태바등의 속성지정을 "No"로 한 상태입니다.<br> <input type='button' value='새로운창열기[1]' onClick="newOpen('1')"><br><br> 두번째 버튼은 새창을 열지만 툴바 상태바등의 속성지정을 "Yes"로 한 상태입니다.<br> <input type='button' value='새로운창열기[2]' onClick='newOpen(2)'><br><br> 세번째 버튼은 새창을 열면서 객체를 이용하여 텍스트를 출력하는 예제입니다.<br> 또한 창닫기 버튼도 만들어 보았습니다.<br> <input type='button' value='새로운창열기[3]' onClick='newOpen(3)'><br><br> </center> </body> </html> 예제가 조금 길었나요...^^* window.open("문서주소(location)","창이름","open()메소드의 속성")와 같은 방법으로 새로운창을 띄울때 설정하는 예를 보았습니다. (단, 위 예제에서는 주소를 사용하지 않고 예를 들었답니다.) 자!~~~ 그러면 그 속성들에 대한 설명들을 하나하나 살펴볼까요. (참조 : 새로 띄운창(자식창)은 Window객체의 속성인 opener속성을 이용하여 새로운창을 띄우게한(부모창) 창을 컨트롤 할 수 있답니다.) open()메소드의 속성
흔히들 재귀호출이라고 하죠...^^* setTimeout(), clearTimeout() 메소드는 일정한 간격으로 함수를 호출하고 중지하는 역활을 한답니다. 주로 윈도우창 또는 이미지등을 동적으로 움직이는데 많이들 사용하는것 같더군요...^^* 위에서 일정한 간격이라 함은 setTimeout()메소드에 호출한 함수와 파라미터값 그리고 1000 또는 10000등 정수를 이용하여 간격을 정의할 수 있는데 그 방법은 아래와 같습니다. 예) setTimeout("test('1')",1000) test('1')은 test란 함수에 인자값으로 1을 정의한 것이며, 1000은 1초를 의미합니다. 참고로 10000은 10초, 100은 0.1초를 의미한답니다...^^* 자 그럼 예제를 볼까요...^^* [ Window 객체의 메소드 - setTimeout(), clearTimeout(); ] - 실행화면 보기 ... [ TOP ]
이번에 배울 메소드는 말그대로 창(윈도우)의 크기를 변형하는 함수입니다. 위 두 메소드의 사용방법은... resizeBy()의 경우 상대적인 길이를 입력하게 되는데 예를 들어 현재의 창이 가로 100PX 세로 100PX이었을때 resizeBy(40,20);으로 설정하였을 경우 가로가 140PX가 되고 세로가 120PX가되는 결과가 나올 것입니다. 그러나... 가로 세로 100PX에서 resizeTo(40,20);설정하였을 경우에는 절대적인 값이 적용되어 가로 40PX와 세로 20PX 크기의 윈도우창이 된답니다. [참조] resizeBy()메소드는 인자값에 음수표기가 가능합니다...^^* 이해하시겠죠... 자 그럼 예제를 볼까요...^^* [ Window 객체의 메소드 - resizeBy(), resizeTo(); ] - 실행화면 보기 ... [ TOP ]
moveBy, moveTo메소드 역시 브라우저의 위치를 변경하는데 사용되는 메소드 입니다. 위에서 배운 resize메소드와 같이 moveBy메소드는 상대적인 위치를 정의하고 moveTo메소드는 절대적인 위치를 정의하게 되죠...^^* 사용방법역시 크게 틀릴바는 없구요... 아래와 같습니다. moveBy(상대적인x위치값, 상대적인y위치값); moveTo(절대적인x위치값, 절대적인y위치값); 어때요... 쉽죠... 아래 예제를 보시면 더욱 이해하시는데 도움이 될듯 하네요. [ Window 객체의 메소드 - moveBy(), moveTo(); ] - 실행화면 보기 ... [ TOP ] 상 하 좌 우
이번에는 print()메소드입니다...^^* 크게 설명드릴것이 없을것 같아 바로 예제로 넘어갑니다...^^* ㅋㅋㅋ [ Window 객체의 메소드 - print(); ] - 실행화면 보기 ... [ TOP ] 인쇄하기
상대적인 설정과 절대적인 설정방법에 대한 메소드들이 계속하여 강좌가 이루어지고 있는것 같네요...^^* 스크롤을 컨트롤하는 메소드인 scrollBy()메소드 역시 상대적인 위치값을 설정할 수 있으며 scrollTo()메소드는 절대적인 위치값을 설정할 수 있답니다. 그럼 사용방법을 볼까요^^* scrollBy(상대적인x위치값, 상대적인y위치값); scrollTo(절대적인x위치값, 절대적인y위치값); 사용방법을 보았으니 항상하는것 처럼 예제를 보도록하죠...^^* 예제가 너무 어렵지 않을까 모르겠네요...^^* ㅋㅋㅋ [ Window 객체의 메소드 - scrollTo(); scrollTo(); ] - 실행화면 보기 ... [ TOP ] 새로 테스트 하시려면 새로고침을 하세요...^^* scrollBy ==> y == 10 scrollTo ==> y == 500 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 자!~~~^^* 이것으로 window객체의 메소드 강좌는 마무리 하구요 다음시간에는 window객체의 이벤트에 대하여 알아보도록 하겠습니다...^^* 이번 window내장객체의 강좌는 너무 긴것 같네요...^^* 헉헉헉^^*
Window 객체의 이벤트
|
주민번호 체크 검사 (0) | 2007.03.04 |
---|---|
하룻동안 창 띄우지 않기 (0) | 2007.03.04 |
세로식 배열 테이블 메뉴 (0) | 2007.03.04 |
Window객체의 속성 (0) | 2007.03.04 |
---|---|
세로식 배열 테이블 메뉴 (0) | 2007.03.04 |
동적으로 테이블의 tr 생성 및 삭제 (0) | 2007.03.04 |
하룻동안 창 띄우지 않기 (0) | 2007.03.04 |
---|---|
동적으로 테이블의 tr 생성 및 삭제 (0) | 2007.03.04 |
접근할 수 있는 객체를 확인하는 스크립트 (0) | 2007.03.03 |
세로식 배열 테이블 메뉴 (0) | 2007.03.04 |
---|---|
접근할 수 있는 객체를 확인하는 스크립트 (0) | 2007.03.03 |
iframe 자동 크기지정 (1) | 2007.03.03 |
동적으로 테이블의 tr 생성 및 삭제 (0) | 2007.03.04 |
---|---|
iframe 자동 크기지정 (1) | 2007.03.03 |
CSS Cuser Property (0) | 2007.03.03 |
iframe 으로 불려질 문서의 크기에 따라 자동으로 크기를 설정 해 주는 스크립트 입니다
많은 분들이 필요하신 소스일것 같네요
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> J@sko Sample Script </title>
<meta name="Generator" content="EditPlus">
<!-- [1단계] 아래의 코드를 <head> 와 </head> 사이에 붙여 넣으세요 -->
<script type="text/javascript">
var iframeids=["myframe"] // iframe 에 사용할 ID 를 지정 해 주세요
var iframehide="yes"
function resizeCaller() {
var dyniframe=new Array()
for (i=0; i<iframeids.length; i++){
if (document.getElementById)
resizeIframe(iframeids[i])
if ((document.all || document.getElementById) && iframehide=="no"){
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i])
tempobj.style.display="block"
}
}
}
function resizeIframe(frameid){
var currentfr=document.getElementById(frameid)
if (currentfr && !window.opera){
currentfr.style.display="block"
if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) //ns6 syntax
currentfr.height = currentfr.contentDocument.body.offsetHeight;
else if (currentfr.Document && currentfr.Document.body.scrollHeight) //ie5+ syntax
currentfr.height = currentfr.Document.body.scrollHeight;
if (currentfr.addEventListener)
currentfr.addEventListener("load", readjustIframe, false)
else if (currentfr.attachEvent)
currentfr.attachEvent("onload", readjustIframe)
}
}
function readjustIframe(loadevt) {
var crossevt=(window.event)? event : loadevt
var iframeroot=(crossevt.currentTarget)? crossevt.currentTarget : crossevt.srcElement
if (iframeroot)
resizeIframe(iframeroot.id);
}
function loadintoIframe(iframeid, url){
if (document.getElementById)
document.getElementById(iframeid).src=url
}
if (window.addEventListener)
window.addEventListener("load", resizeCaller, false)
else if (window.attachEvent)
window.attachEvent("onload", resizeCaller)
else
window.onload=resizeCaller
</script>
<!----------------- 여기까지 ----------------->
</head>
<body>
<!-- [2단계] 아래의 방법으로 iframe 태그를 넣으세요 -->
<iframe id="myframe" src="http://www.jasko.co.kr/homepage/main.html" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" vspace="0" hspace="0" style="overflow:visible; width:100%; display:none"></iframe>
<!-- 여기에서 주의할 점은 스크립트의 맨 처음에 지정한 iframe 의 아이디를 반드시 사용해야 한다는 점입니다 --->
<!----------------- 여기까지 ----------------->
<p>
위의 페이지는 iframe 태그에 의해 불려진 페이지의 전체 입니다<br>
이처럼 이 스크립트를 사용하면 불려질 문서의 길이가 자동으로 체크되어 그 길이만큼 iframe 이 보여집니다
</body>
</html>
출처 : 자스코
접근할 수 있는 객체를 확인하는 스크립트 (0) | 2007.03.03 |
---|---|
CSS Cuser Property (0) | 2007.03.03 |
Javascript 에서 Querystring 뽑아내기 (0) | 2007.03.03 |
all-scroll |
[IE6+] 좌, 우측 스크롤이 가능할때 나타나는 커서 |
auto |
브라우저의 기본 설정을 따름 |
col-resize |
[IE6+] 테이블의 세로폭을 리사이즈 할때 나타나는 커서 |
row-resize |
[IE6+] 테이블의 가로폭을 리사이즈 할때 나타나는 커서 |
crosshair |
+ 모양의 커서 |
default |
OS에서 설정한 마우스의 기본 커서 |
hand |
링크나 개체를 이동할때 나타나는 손 모양의 커서 |
help |
도움말 등을 나타 낼때 사용하는 커서 |
move |
이동 가능함을 나타내는 + 자 모양의 화살표 |
no-drop |
[IE6+] 접근 불가나 Drop 불가를 나타내는 커서 |
not-allowed |
접근 불가, 허용불가를 나타내는 커서 |
pointer |
[IE6+] Head 와 모양과 기능이 같음 |
progress |
[IE6+] 화살표 + 모래시계 커서 |
wait |
동작중임을 나타내는 모래시계 커서 |
text |
가로 텍스트를 표시하는 I 자 모양의 커서 |
text |
[IE6+] 세로 텍스트를 표시하는 ㅡ 자 모양의 커서 |
url(uri) |
[IE6+] 다른서버의 커서를 사용할 수 있음 |
*-resize |
다양한 리사이즈 지원의 커서 (아래쪽 표참고) |
[표 - 리사이즈 별 커서]
n-resize | s-resize | ne-resize | sw-resize |
nw-resize | se-resize | e-resize | w-resize |
iframe 자동 크기지정 (1) | 2007.03.03 |
---|---|
Javascript 에서 Querystring 뽑아내기 (0) | 2007.03.03 |
web editor 소스 (0) | 2007.03.03 |
<SCRIPT Language="JavaScript"> <!-- /* * This function parses comma separated name=value * argument pairs from the query string of the URL. * It stores the name=value pairs in * properties of an object and then returns that object * * Jim K - From Orielly JSB pp 244 */ function getArgs() { var args = new Object(); // Get Query String var query = location.search.substring(1); // Split query at the comma var pairs = query.split("&"); // Begin loop through the querystring for(var i = 0; i < pairs.length; i++) { // Look for "name=value" var pos = pairs[i].indexOf('='); // if not found, skip to next if (pos == -1) continue; // Extract the name var argname = pairs[i].substring(0,pos); // Extract the value var value = pairs[i].substring(pos+1); // Store as a property args[argname] = unescape(value); } return args; // Return the Object } // Set Defaults var StyleSheet = "StyleSheet" var OuterTableWidth = "640" // Get the values back var args = getArgs(); //Get the arguments if (args.CSSPATH) StyleSheet = (args.CSSPATH); if (args.OTBL) OuterTableWidth = (args.OTBL); // write the path for the style sheet now document.write("<link rel='stylesheet' href='http://www.jamesrking.com/_scriptLib/Includes/StyleSheet" + args.CSSPATH + ".css'>"); //--> </SCRIPT>
CSS Cuser Property (0) | 2007.03.03 |
---|---|
web editor 소스 (0) | 2007.03.03 |
개발자 등급 기준 -출처 Codeway- (0) | 2007.03.03 |
웹에디터, web editor 소스 (학습용)
기본 원리는 IFAME의을 편집 할 수 있도록 하고 자바스크립트에서 DHTML편집 할 수 있는 형태이며 저장은 자바스크립트에서 값을 변환 하고 넘기는 방식 입니다.
1. 편집창 만들기
편집창은 iframe태그를 사용 합니다.
<iframe></iframe>
속성으로는 다음과 같은 것들이 있습니다.
src="" iframe에서 연결 시킬 경로 width="" 너비 height="" 높이 name="" 이름으로 FRAME의 이름과 동일 하며 taget의 대상이 될 수 있습니다.
예) <iframe src="http://www.yahoo.co.kr" width="700" height="400" name="html"></ifame>
ifrme은 반드시 종료태그가 있어야 합니다.
IFRAME은 FRAME을 이미지 형식으로 만드는 태그 입니다. 하지만 일반형식은 브라우저의 내용을 그냥 읽어오는 형식 입니다. 그래서 편집 가능 하도록 자바스크립트에서 만들어 줍니다.
<HTML>
<HEAD>
<TITLE>웹에디터 예제1</TITLE>
</HEAD>
<BODY>
<IFRAME NAME=dhtmlframe></IFRAME>
<SCRIPT LANGUAGE="JavaScript">
<!-- JavaScript
dhtmlframe.document.designMode = "On"
// - JavaScript - -->
</SCRIPT>
</BODY>
</HTML>
여기서 자바스크립트는 iframe이후에 넣어 줘야 합니다.
그럼 위의 파일을 html로 만들고 브라우저에서 읽어오면 편집 가능 하도록 되어 있을 것 입니다.
2. 편집툴바 만들기
<HEAD>와 </HEAD>사이에 자바 스크립트 만듭니다.
<SCRIPT langauge="javascript">
function htmledit(excute){
dhtmlframe.document.execCommand(excute);
}
</SCRIPT>
그리고 툴바에는 볼드,이탤릭,언더라인 만들고 다음 과 링크를 연결 합니다.
<A href="javascript:htmledit('BOLD');">볼드</A>
<A href="javascript:htmledit('italic');">이탤릭</A>
<A href="javascript:htmledit('underline');">언더라인</A>
다음 예제를 저장 하고 브라우저를 통해 실행 합니다.
<HTML>
<HEAD>
<TITLE>웹에디터 예제2</TITLE>
<SCRIPT langauge="javascript">
function htmledit(excute){
dhtmlframe.document.execCommand(excute);
}
</SCRIPT>
</HEAD>
<BODY>
<A href="javascript:htmledit('bold');">볼드</A>
<A href="javascript:htmledit('italic');">이탤릭</A>
<A href="javascript:htmledit('underline');">언더라인</A>
<p>
<IFRAME NAME=dhtmlframe></IFRAME>
<SCRIPT LANGUAGE="JavaScript">
<!-- JavaScript
dhtmlframe.document.designMode = "On"
// - JavaScript - -->
</SCRIPT>
</BODY>
</HTML>
브라우저에서 편집 가능 한것을 볼수 있습니다.
볼드,이탤릭,언더라인 이외 무엇이 있을까요.
cut - 자르기
copy - 복사
paste - 붙여넣기
justifyleft - 좌측정렬
justifycenter - 중심정렬
justifyright - 우측정렬
insertorderedlist - 점표시목록
insertunorderedlist - 숫자목록
outdent - 들여쓰기 줄이기
indent- 들여쓰기 늘이기
createlink - 링크
fontname - 글꼴
fontSize - 글사이즈
<A href="javascript:htmledit('cut');">자르기</a>
형식등로 사용 할 수 있습니다.
그러나 글꼴 이나 글크기등은 값이 필요 합니다. 이경우 htmledit(excute)에서 excute이외 하나더 인자가 필요 합니다. values 라고 하나 더 추가 합니다.
<SCRIPT langauge="javascript">
function htmledit(excute,values){
if(values==null){
dhtmlframe.document.execCommand(excute);
}
else
dhtmlframe.document.execCommand(excute,"",values);
}
}
</SCRIPT>
글꼴을 궁서체로 만들고 싶으면
htmledit('fontname','궁서체') 가 됩니다. 다음 예제를 테스트 해보세요
<HTML>
<HEAD>
<TITLE>웹에디터 예제3</TITLE>
<SCRIPT langauge="javascript">
function htmledit(excute,values)
{
if(values==null)
{
dhtmlframe.document.execCommand(excute);
}
else
{
dhtmlframe.document.execCommand(excute,"",values);
}
}
</SCRIPT>
</HEAD>
<BODY>
<A href="javascript:htmledit('cut');">자르기</a>
<A href="javascript:htmledit('copy');">복사</a>
<A href="javascript:htmledit('paste');">붙여넣기</a>
<A href="javascript:htmledit('justifyleft');">좌측정렬</a>
<A href="javascript:htmledit('justifycenter');">중심정렬</a>
<A href="javascript:htmledit('justifyright');">우측정렬</a>
<A href="javascript:htmledit('insertorderedlist');">점표시목록</a>
<A href="javascript:htmledit('insertunorderedlist');">숫자목록</a>
<A href="javascript:htmledit('outdent');">들여쓰기줄이기</a>
<A href="javascript:htmledit('indent');">들여쓰기늘이기</a>
<A href="javascript:htmledit('createlink');">링크</a><BR>
글꼴 >
<A href="javascript:htmledit('fontname','굴림');">굴림</a>
<A href="javascript:htmledit('fontname','궁서');">궁서</a>
글크기 >
<A href="javascript:htmledit('fontSize',2);">2</a>
<A href="javascript:htmledit('fontSize',3);">3</a>
<A href="javascript:htmledit('fontSize',4);">4</a>
<A href="javascript:htmledit('bold');">볼드</A>
<A href="javascript:htmledit('italic');">이탤릭</A>
<A href="javascript:htmledit('underline');">언더라인</A>
<P><IFRAME NAME=dhtmlframe></IFRAME>
<SCRIPT LANGUAGE="JavaScript">
<!-- JavaScript
dhtmlframe.document.designMode = "On"
// - JavaScript - -->
</SCRIPT>
</BODY>
</HTML>
3. 값넘기기
이제까지 HTML과 자바스크립트로만 이용 해서 만들었습니다. 이렇게 만든 값을 CGI(PHP,ASP..)등으로 보내고야 합니다. 아시다 싶이 값을 전송 하는것은 form태그를 시용 합니다.
form을 만듭니다. 그리고 form의 속성중 name을 form으로 만들고(아무거나 만들어도 상관 없겠죠)
<IFRAME>밑에 <TEXTAREA></TEXTAREA>을 만듭니다. 이름은 아무거나.. 저는 comment라 지었습니다.
그리고 HEAD자바 스크립트에 다음과 같이 추가 합니다.
function datasubmit()
{
form.comment.value = dhtmlframe.document.body.innerHTML;
}
아래의 예제를 실행 하고 HTML보기를 클릭 하면 HTML소스가 <TEXTAREA>에 복사 되는 것을 볼 수 있습니다.
그상태에서 다른 CGI에서 comment로 변수로 읽어 저장 되는 것 입니다.
<HTML>
<HEAD>
<TITLE>웹에디터 예제4</TITLE>
<SCRIPT langauge="javascript">
function htmledit(excute,values)
{
if(values==null)
{
dhtmlframe.document.execCommand(excute);
}
else
{
dhtmlframe.document.execCommand(excute,"",values);
}
}
function datasubmit()
{
form.comment.value = dhtmlframe.document.body.innerHTML;
}
</SCRIPT>
</HEAD>
<BODY>
<form name=form>
<A href="javascript:htmledit('cut');">자르기</a>
<A href="javascript:htmledit('copy');">복사</a>
<A href="javascript:htmledit('paste');">붙여넣기</a>
<A href="javascript:htmledit('justifyleft');">좌측정렬</a>
<A href="javascript:htmledit('justifycenter');">중심정렬</a>
<A href="javascript:htmledit('justifyright');">우측정렬</a>
<A href="javascript:htmledit('insertorderedlist');">점표시목록</a>
<A href="javascript:htmledit('insertunorderedlist');">숫자목록</a>
<A href="javascript:htmledit('outdent');">들여쓰기줄이기</a>
<A href="javascript:htmledit('indent');">들여쓰기늘이기</a>
<A href="javascript:htmledit('createlink');">링크</a><BR>
글꼴 >
<A href="javascript:htmledit('fontname','굴림');">굴림</a>
<A href="javascript:htmledit('fontname','궁서');">궁서</a>
글크기 >
<A href="javascript:htmledit('fontSize',2);">2</a>
<A href="javascript:htmledit('fontSize',3);">3</a>
<A href="javascript:htmledit('fontSize',4);">4</a>
<A href="javascript:htmledit('bold');">볼드</A>
<A href="javascript:htmledit('italic');">이탤릭</A>
<A href="javascript:htmledit('underline');">언더라인</A>
<A href="javascript:htmledit('fontname');">언더라인</A>
<P><IFRAME NAME=dhtmlframe></IFRAME>
<P><TEXTAREA NAME="comment" ROWS="3"></TEXTAREA></P>
<P><A href="javascript:datasubmit()">HTML보기</a>
<SCRIPT LANGUAGE="JavaScript">
<!-- JavaScript
dhtmlframe.document.designMode = "On"
// - JavaScript - -->
</SCRIPT>
</form>
</BODY>
</HTML>
그럼 다른 CGI(PHP,ASP..)을 보내기 위해 소스를 다듬어 보도록 하겠습니다.
먼저 <TEXTAREA>에 STYLE="display: none"을 추가 합니다.
그럼 <TEXTAREA STYLE="display: none">가 되며 브라우저에서 보이지 않게 됩니다.
그리고 <form>에는 제대로 보내고자 하는 CGI위치와 method를 지정 합니다.
<A href="javascript:datasubmit()">HTML보기</a>을
<input type="submit" value="확인" Onclick="datasubmit()"> 으로 바꿉니다.
<HTML>
<HEAD>
<TITLE>웹에디터 예제5</TITLE>
<SCRIPT langauge="javascript">
function htmledit(excute,values)
{
if(values==null)
{
dhtmlframe.document.execCommand(excute);
}
else
{
dhtmlframe.document.execCommand(excute,"",values);
}
}
function datasubmit()
{
form.comment.value = dhtmlframe.document.body.innerHTML;
}
</SCRIPT>
</HEAD>
<BODY>
<form name=form method=post action="test.php">
<A href="javascript:htmledit('cut');">자르기</a>
<A href="javascript:htmledit('copy');">복사</a>
<A href="javascript:htmledit('paste');">붙여넣기</a>
<A href="javascript:htmledit('justifyleft');">좌측정렬</a>
<A href="javascript:htmledit('justifycenter');">중심정렬</a>
<A href="javascript:htmledit('justifyright');">우측정렬</a>
<A href="javascript:htmledit('insertorderedlist');">점표시목록</a>
<A href="javascript:htmledit('insertunorderedlist');">숫자목록</a>
<A href="javascript:htmledit('outdent');">들여쓰기줄이기</a>
<A href="javascript:htmledit('indent');">들여쓰기늘이기</a>
<A href="javascript:htmledit('createlink');">링크</a><BR>
글꼴 >
<A href="javascript:htmledit('fontname','굴림');">굴림</a>
<A href="javascript:htmledit('fontname','궁서');">궁서</a>
글크기 >
<A href="javascript:htmledit('fontSize',2);">2</a>
<A href="javascript:htmledit('fontSize',3);">3</a>
<A href="javascript:htmledit('fontSize',4);">4</a>
<A href="javascript:htmledit('bold');">볼드</A>
<A href="javascript:htmledit('italic');">이탤릭</A>
<A href="javascript:htmledit('underline');">언더라인</A>
<A href="javascript:htmledit('fontname');">언더라인</A>
<P><IFRAME NAME=dhtmlframe></IFRAME>
<P><TEXTAREA NAME="comment" ROWS="3"></TEXTAREA></P>
<P><input type="submit" value="확인" Onclick="datasubmit()">
<SCRIPT LANGUAGE="JavaScript">
<!-- JavaScript
dhtmlframe.document.designMode = "On"
// - JavaScript - -->
</SCRIPT>
</form>
</BODY>
</HTML>
지금까지 공개 되었던 소스보다 간단하다는것을 알 수 있습니다. 하지만 중요한 요소는 다들어 가 있으며 여기서부터는 살을 붙이고 디자인도 바꾸면 됩니다. 그 몫은 여러분이 해야 할 일 입니다.
Javascript 에서 Querystring 뽑아내기 (0) | 2007.03.03 |
---|---|
개발자 등급 기준 -출처 Codeway- (0) | 2007.03.03 |
프로그래밍은 예술이다? (0) | 2007.03.03 |
web editor 소스 (0) | 2007.03.03 |
---|---|
프로그래밍은 예술이다? (0) | 2007.03.03 |
프로그래머를 위한「공부론」 (0) | 2007.03.03 |
임백준 ( 루슨트 테크놀로지스 )
2004/01/15
필자는 프로그래밍을 비교적 늦은 나이인 이십대 중반에 시작했다. 따라서 독학을 통해서 익힌 '초식'이 많았는데 그래서인지 10년이 지나도록 잘 고쳐지지 않는 습관이 하나 있다. 머리 속에 알고리즘의 윤곽이 떠오르면 일단 키보드를 붙잡고 코드를 두드려야만 직성이 풀리는 것이다. 그렇게 하지 않으면 다음 내용이 잘 떠오르지 않는다. 프로그래밍 방법론이나 소프트웨어 공학의 충고에 의하면 이것은 '코딩'이 '설계'에 앞서는 대단히 잘못된 방법에 속한다. 교과서에 적힌 기본을 무시하는 철저한 아마추어리즘의 소산인 것이다.
여러 명의 개발자가 함께 코딩을 하는 경우에는 물론 얘기가 다르다. 그런 경우에는 레쇼날 로즈 ( Rational Rose ) 같은 소프트웨어나 객체 설계용 언어인 UML 을 이용해서 어느 정도 설계를 마친 다음에 코딩을 시작할 수밖에 없다. 하지만 프로그래밍을 혼자서 할 때는 언제나 '코딩'이 '설계'를 앞선다. "진정한 '프로'는 설계를 마친 다음에 비로소 키보드를 잡는 거야"라고 아무리 말해도 소용이 없다. 커피를 마실 때 크림을 넣지 않으면 맛이 느껴지지 않는 것처럼 손끝에 전달되는 키보드의 감촉이 없으면 프로그래밍의 '맛'이 느껴지지 않는다.
이런 습관은 회사에서 수행하는 공식적인 프로그래밍에도 종종 연결된다. 외부의 API 가 모두 결정된 상태에서 독립적인 컴포넌트의 내부를 구현하는 경우에는 예외 없이 코딩에서 부터 설계가 시작된다. 화면에 뜬 편집기 ( 필자의 경우에는 주로 vi ) 라는 캔버스 위에 키보드 커서라는 연필을 조금씩 움직여 나가면 머리 속에 감추어져 있던 알고리즘이 서서히 눈앞에 모습을 드러낸다. 때로는 종이 위에 동그라미, 네모, 선 등을 그리면서 설계를 하는 경우도 있지만 그것은 어디까지나 키보드를 통해서 하는 붓질을 돕는 보조적인 조치일 뿐이다.
프로그래밍에 '조예'가 있는 개발자라면 이런 습관은 그다지 자랑할 바가 아니라고 생각할 것이다. 당연하다. 필자도 아주 최근까지 그렇게 생각했다. 그렇지만 프로그래머 중에서 이와 같은 습관을 가지고 있는 사람이 적지 않으리라는 점은 분명하다. 손끝에 키보드의 감촉이 전달될 때 비로소 프로그래밍의 맛을 느끼는 사람은 결코 필자에 국한되는 얘기가 아닐 것이다.
하지만 그런 사람들조차 대부분 '설계'에 앞서는 '코딩'은 자랑할 바가 아니라고 생각한다. 특히 프로그래밍 실력이 뛰어난 고수일수록 설계를 마치기 전에는 키보드를 넘실거리지 않을 것이라고 믿는다. 뒤집어 말하면 설계를 끝내기 전에 키보드를 만지작거리는 사람은 일종의 '하수'로 간주되는 셈이다.
필자가 이와 같은 '설계'와 '코딩'의 관계를 포함하여 흔히 알려진 프로그래밍의 방법론이나 소프트웨어 공학의 '교리'를 의심하기 시작한 것은 ( 지난 해에 두 권의 책을 쓰면서 ) 프로그래밍의 본질이 '공학'에 있는가 아니면, '예술'에 있는가 하는 문제를 고민하면서부터였다.
프로그래밍이 도대체 예술일 수 있는가에 대한 답을 구하려면 우선 예술이 무엇을 의미하는지 이해해야 하는데 그것은 간단하지 않은 주제이므로 여기서 다루기 어렵다. 하지만 한 가지 분명한 것은 필자의 관점에서 볼 때 프로그래밍은 공학적 요소를 포함하고 있긴 하지만 분명히 예술에 더 가깝다는 점이다.
프로그래밍을 예술로 파악하는 것은 물론 새로운 관점이 아니다. 「프로그래밍의 예술 ( The Art of Computer Programming )」로 유명한 스탠포드 대학의 도날드 카누스 교수는 일찍이 「문학적 프로그래밍 ( Literate Programming )」이라는 책에서 '프로그래밍은 예술'이라고 선언한 바 있다. 그는 이러한 선언을 한 걸음 더 밀고 나아가 프로그램 소스 코드도 다른 예술 작품들과 마찬가지로 미학적 요소와 독창성을 고려해서 '값'이 매겨지는 시대가 도래할 것이라고 예언하기까지 했다.
카누스 교수가 말한 '문학적 프로그래밍'이란 사실 단순한 비유에서 그치는 것이 아니라 코드의 예술성을 담보하기 위한 일종의 구체적인 프로그래밍 방법론이었다. 우리나라에서는 「생각하는 프로그래밍」이라는 책으로 번역된 '프로그래밍 펄 ( Programming Pearl )'로 유명한 존 벤틀리는 카누스 교수가 '문학적 프로그래밍'을 설명한 글을 읽고 감명을 받은 나머지 자신의 컬럼 몇 개를 카누스 교수의 새로운 방법론을 소개하는데 바치기도 했다.
'프로그래밍은 예술'이라는 명제는 사실 수학 명제처럼 명쾌하게 증명될 수 있는 것이 아니다. 그러나 프로그래밍을 하는 사람이라면, 그 '맛'을 조금이라도 아는 사람이라면, 이 명제를 간단하게 거부하지 못할 것이다. 오픈소스 프로젝트에 참여하여 자신의 여가시간마저 프로그래밍에 바치는 해커든, 아니면 회사에 출퇴근하면서 정해진 틀에 따라 코딩을 하는 '월급쟁이'이든 상관이 없다.
프로그래밍이 단순히 기술이나 공학의 수준에 머무르지 않는다는 사실은 누구에게나 분명하다. 프로그래밍이라는 행위 안에는 꼭 집어서 설명할 수 없지만 가슴이 떨리고 흥분이 밀려오는 '창조적 긴장'의 순간이 담겨 있기 때문이다.
카누스 교수는 스스로 수학적 논리와 알고리즘에 대해서 실로 심오한 내공을 갖추고 있었다. 그런 맥락에서 그는 프로그래밍이 가지고 있는 '과학적 미학'의 측면을 강조했다. 이에 비해서 폴 그래이엄은 프로그래밍에 담겨 있는 '창조적 미학'의 측면을 날카롭게 부각시켰다. 그래이엄은 하버드에서 컴퓨터 공학 박사 학위를 받고 인공지능 언어인 LISP에 대한 교과서를 쓸 정도로 내공이 중후한 프로그래머였다. 뿐만 아니라 인터넷 붐이 한창이던 1998년에 ViaWeb 이라는 회사를 야후에 팔아서 '비즈니스맨'으로서도 이름을 얻었다.
그래이엄은 프로그래밍에 담긴 예술의 측면을 설명하기 위해서 프로그래밍을 그림 그리는 행위에 비유했다. 앞에서 그를 소개하면서 내공이 중후한 '프로그래머였다고' 말한 이유는 그가 지금은 그림 ( painting ) 을 공부하여 화가의 길을 걷고 있기 때문이다.
그가 보기에 프로그래밍은 순수한 논리나 학문의 대상이라기보다는 '실천적 행위'를 통해서 몸에 익혀 가는 구체적인 '행동'에 가까웠다. 그것은 마치 텅빈 백지 위에 붓을 한 번 크게 긋는 행위와 다를 바 없었다. 그래서 그는 컴퓨터 과학이라는 표현이 프로그래밍의 진정한 속성을 정확하게 담지 못한다고 비판했다.
프로그래밍이 '컴퓨터 과학' 혹은 '컴퓨터 공학'과 같지 않은 이유는 그림을 그리는 예술적 실천이 물감의 화학적 배합을 연구하는 '학문'과 같지 않은 이유와 동일하다. 다시 말해서 그림을 그리는 화가는 물감의 화학적 성분이나 여러 화학 이론에 대해서 굳이 알 필요가 없다.
이와 마찬가지로 프로그래밍이라는 창조적 활동을 하는 사람 ( 즉, 프로그래머 ) 들은 컴퓨터 과학과 공학의 수많은 이론을 굳이 자세하게 알 필요가 없다. 예를 들어서 튜링 기계나 오토마타의 개념 정도는 알 필요가 있을지 몰라도 복잡성 이론 ( complexity theory ) 에 등장하는 명제를 모두 읽어야만 좋은 프로그램을 만들 수 있는 것은 아니다.
그래이엄을 알기 전까지 필자는 '코딩'이 '설계'를 앞서는 습관을 '아마추어리즘'의 표현이라고 생각해 왔다. 진정한 프로라면 교과서에서 가르치는 대로 정확하게 설계를 마친 다음 비로소 코딩을 시작해야 하는 것이라고 생각했다. 이런 강박관념은 일종의 열등감마저 수반했는데 그래이엄의 통찰은 필자를 '예술'이라는 아름다운 이름과 함께 구원해 주었다.
프로그래밍을 예술로 바라보는 관점에서 생각해 보면 '판에 박힌 듯한' 소프트웨어 개발 방법론은 프로그래머 개개인의 감성을 존중하기보다는 정해진 틀에 맞는 상품을 생산하기 원하는 기업의 욕망을 반영하고 있다. '획일적인 틀'은 상품 생산을 위해서 필요할 뿐 진정한 창조와 아무런 상관이 없기 때문이다.
뛰어난 프로그래머였던 그래이엄은 자기 자신도 프로그래밍을 할 때 키보드를 붙잡고 코딩부터 시작한다고 고백했다. 그가 밝힌 방법은 우선 가볍게 키보드를 두드리면서 코드의 전체 윤곽을 잡고, 다시 처음으로 돌아가서 조금씩 각 부분의 디테일을 살려 나가는 방식으로 프로그램을 작성하는 것이었다. 그는 코딩이 설계에 앞서는 이와 같은 방식을 조금도 이상하게 여기지 않았다. 오히려 그는 모든 예술적 창조가 대개 이와 비슷한 과정을 거치면서 이루어지며 그림을 그리는 과정도 이와 다르지 않다고 말했다. 그리고 미술에서는 그것을 '스케치'라는 자연스러운 이름으로 부른다고 지적했다.
혹시 필자가 이 글을 통해서 '코딩은 설계에 앞서야 한다'는 명제를 주장하고 있다고 잘못 이해하지 않기 바란다. 그것은 손으로 달을 가리켰더니 손가락만 바라보더라는 이야기와 다를 바 없는 오해가 될 것이다. 여러 명이 함께 복잡한 소프트웨어를 만들 때 '설계'의 과정이 결정적으로 중요하다는 사실에는 이견이 있을 수 없다. 다만 필자는 소프트웨어의 '생산성'을 높이기 위한 방법론이 반드시 프로그래밍의 '예술성'을 강화시키는 쪽으로 작용하지 않는다는, 아니 정확하게 말하자면 그 반대의 방향으로 작용한다는 사실을 지적하고 싶었을 뿐이다.
그럼 프로그래밍의 '예술성'을 강조하는 프로그래머는 그렇지 않은 프로그래머에 비해서 소프트웨어 '생산성'이 떨어지는 것일까? 놀랍게도 전혀 그렇지 않다. 오히려 그 반대의 경우가 더 많다. 창조의 기쁨을 아는 사람과 그렇지 않은 사람이 발휘하는 능력에는 본질적인 차이가 존재하기 때문이다. 필자가 이 글을 통해서 말하고 싶은 것이 바로 그 차이이다. '기쁨'이 있는 사람과 없는 사람 사이에 존재하는 차이는 프로그래밍의 예술적 속성을 이해하는데 있어서 핵심적인 열쇠가 된다
개발자 등급 기준 -출처 Codeway- (0) | 2007.03.03 |
---|---|
프로그래머를 위한「공부론」 (0) | 2007.03.03 |
각종 확장자 파일 모음 (0) | 2007.03.03 |
| ||
이 글은 공부하는 방법과 과정에 관한 글입니다. 이 글은 제가 공부한 성공/실패 경험을 기본 토대로 했고, 지난 몇 년간 주변에서 저보다 먼저 공부한 사람들의 경험을 관찰, 분석한 것에 제가 다시 직접 실험한 것과 그밖에 오랫동안 꾸준히 모아온 자료들을 더했습니다. '만약 다시 공부한다면' 저는 이렇게 공부할 것입니다. 부디 독자 제현께서 이 글을 씨앗으로 삼아 자신만의 나무를 키우고 거기서 열매를 얻고, 또 그 열매의 씨앗이 다시 누군가에게 전해질 수 있다면 더 이상 바랄 것이 없겠습니다. 이 글은 특정 주제들의 학습/교수법에 대한 문제점과 제가 경험한 좋은 공부법을 소개하는 식으로 구성됐습니다. 여기에 선택된 과목은 리팩토링, 알고리즘·자료구조, 디자인패턴, 익스트림 프로그래밍(Extreme Programming 혹은 XP) 네 가지입니다. 이 네 가지가 선택된 이유는 필자가 관심있게 공부했던 것이기 때문만은 아니고, 모든 프로그래머에게 어떻게든 널리 도움이 될만한 교양과목이라 생각하여 선택한 것입니다. 그런데 이 네 가지의 순서가 겉보기와는 달리 어떤 단계적 발전을 함의하는 것은 아닙니다. 수신(修身)이 끝나면 더 이상 수신은 하지 않고 제가(齊家)를 한다는 것이 어불성설인 것과 같습니다. 원래는 글 후미에 일반론으로서의 공부 패턴들을 쓰려고 했습니다. 하지만 지면의 제약도 있고, 독자 스스로 이 글에서 그런 패턴을 추출하는 것도 의미가 있을 것이기에 생략했습니다. 그런 일반론이 여기 저기 숨어있기 때문에 알고리즘 공부에 나온 방법 대부분이 리팩토링 공부에도 적용할 수 있고, 적용되어야 한다는 점을 꼭 기억해 주셨으면 합니다. 다음에 기회가 닿는다면 제가 평소 사용하는 (컴퓨터) 공부패턴들을 소개하겠습니다. 알고리즘·자료구조 학습에서의 문제 우리는 알고리즘 카탈로그를 배웁니다. 이미 그러한 해법이 존재하고, 그것이 최고이며, 따라서 그것을 달달 외우고 이해해야 합니다. 좀 똑똑한 친구들은 종종 "이야 이거 정말 기가 막힌 해법이군!"하고 감탄할지도 모릅니다. 대부분의 나머지 학생들은 그 해법을 이해하려고 머리를 쥐어짜고 한참을 씨름한 후에야 어렴풋이 왜 이 해법이 그 문제를 해결하는지 납득하게 됩니다. 그리고는 그 '증명'은 책 속에 덮어두고 까맣게 사라져버립니다. 앞으로는 그냥 '사용'하면 되는 것입니다. 더 많은 대다수의 학생은 이 과정이 무의미하다는 것을 알기 때문에 왜 이 해법이 이 문제를 문제없이 해결하는지의 증명은 간단히 건너뜁니다. 이런 학생들은 이미 주어진 알고리즘을 사용하는 일종의 객관식 혹은 문제 출제자가 존재하는 시험장 상황에서는 뛰어난 성적을 보일 것임은 자명합니다. 하지만 스스로가 문제와 해답을 모두 만들어내야 하는 상황이라면, 또는 해답이 존재하지 않을 가능성이 있는 상황이라면, 혹은 최적해를 구하는 것이 불가능에 가깝다면, 혹은 알고리즘을 완전히 새로 고안해내야 하거나 기존 알고리즘을 변형해야 하는 상황이라면 어떨까요? 교육은 물고기를 잡는 방법을 가르쳐야 합니다. 어떤 알고리즘을 배운다면 그 알고리즘을 고안해낸 사람이 어떤 사고 과정을 거쳐 그 해법에 도달했는지를 구경할 수 있어야 하고, 학생은 각자 스스로만의 해법을 차근차근 '구성'(construct)할 수 있어야 합니다(이를 교육철학에서 구성주의라고 합니다. 교육철학자 삐아제(Jean Piaget)의 제자이자, 마빈 민스키와 함께 MIT 미디어랩의 선구자인 세이머 페퍼트 박사가 주창했습니다). 전문가가 하는 것을 배우지 말고, 그들이 어떻게 전문가가 되었는지를 배우고 흉내 내야 합니다. 결국은 소크라테스적인 대화법입니다. 해답을 가르쳐 주지 않으면서도 초등학교 학생이 자신이 가진 지식만으로 스스로 퀵소트를 유도할 수 있도록 옆에서 도와줄 수 있습니까? 이것이 우리 스스로와 교사들에게 물어야 할 질문입니다. 왜 우리는 학교에서 '프로그래밍을 하는 과정'이나 '디자인 과정'(소프트웨어 공학에서 말하는 개발 프로세스가 아니라 몇 시간이나 몇 십 분 단위의, 개인적인 차원의 사고 과정 등을 일컫습니다)을 명시적으로 배운 적이 없을까요? 왜 해답에 이르는 과정을 가르쳐주는 사람이 없나요? 우리가 보는 것은 모조리 이미 훌륭히 완성된, 종적 상태의 결과물로서의 프로그램뿐입니다. 어느 날 문득 하늘에서 완성된 프로그램이 뚝 떨어지는 경우는 없는데 말입니다. 교수가 어떤 알고리즘 문제의 해답을 가르칠 때, "교수님, 교수님께서는 어떤 사고 과정을 거쳐, 그리고 어떤 디자인 과정과 프로그래밍 과정을 거쳐서 그 프로그램을 만드셨습니까?"하고 물어봅시다. 만약 여기에 어떤 체계적인 답변도 할 수 없는 분이라면 그 분은 자신의 사고에 대해 '사고'해 본 적이 없거나 문제 해결에 어떤 효율적 체계를 갖추지 못한 분이며, 따라서 아직 남을 가르칠 준비가 되어있지 않은 분일 것입니다. 만약 정말 그렇다면 우리는 어떻게 해야 할까요? 자료구조와 알고리즘 공부 제가 생각건대, 교육적인 목적에서는 자료구조나 알고리즘을 처음 공부할 때 우선은 특정 언어로 구현된 것을 보지 않는 것이 좋을 때가 많습니다. 대신 말로 된 설명이나 의사코드(pseudo-code) 등으로 그 개념까지만 이해하는 것이죠. 그 아이디어를 절차형(C, 어셈블리어)이나 함수형(LISP, Scheme, Haskell), 객체지향(자바, 스몰토크) 언어 등으로 직접 구현해 보는 겁니다. 그 다음에는 다른 사람이나 다른 책의 코드와 비교합니다. 이 경험을 애초에 박탈당한 사람은 귀중한 배움과 깨달음의 기회를 잃은 셈입니다. 만약 여러 사람이 함께 공부한다면 각자 동일한 아이디어를 같은 언어로 혹은 다른 언어로 어떻게 다르게 표현했는지를 서로 비교해 보면 배우는 것이 무척 많습니다. 우리가 자료구조나 알고리즘을 공부하는 이유는, 특정 '실세계의 문제'를 어떠한 '수학적 아이디어'로 매핑시켜 해결할 수 있는지, 그것이 효율적인지, 또 이를 컴퓨터에 어떻게 효율적으로 구현할 수 있는지 따지고, 그것을 실제로 구현하기 위해서입니다. 따라서 이 과정에 있어 실세계의 문제를 수학 문제로, 그리고 수학적 개념을 프로그래밍 언어로 효율적으로 표현해내는 것은 아주 중요한 능력이 됩니다. 알고리즘 공부에서 중요한 것 개별 알고리즘의 목록을 이해, 암기하며 익히는 것도 중요하지만 더 중요한 것은 다음 네 가지입니다. ①알고리즘을 스스로 생각해낼 수 있는 능력 ②다른 알고리즘과 효율을 비교할 수 있는 능력 ③알고리즘을 컴퓨터와 다른 사람이 이해할 수 있는 언어로 표현해낼 수 있는 능력 ④이것의 정상작동(correctness) 여부를 검증해 내는 능력 첫 번째가 제대로 훈련되지 못한 사람은 알고리즘 목록의 스테레오 타입에만 길들여져 있어서 모든 문제를 자신이 아는 알고리즘 목록에 끼워 맞추려고 합니다. 디자인패턴을 잘못 공부한 사람과 비슷합니다. 이런 사람들은 마치 과거에 수학 정석만 수십 번 공부해 문제를 하나 던져주기만 하면, 생각해보지도 않고 자신이 풀었던 문제들의 패턴 중 가장 비슷한 것 하나를 기계적·무의식적으로 풀어제끼는 문제풀이기계와 비슷합니다. 그들에게 도중에 물어보십시오. "너 지금 무슨 문제 풀고 있는 거니?" 열심히 연습장에 뭔가 풀어나가고는 있지만 그들은 자신이 뭘 풀고 있는지도 제대로 인식하지 못 하는 경우가 많습니다. 머리가 푸는 게 아니고 손이 푸는 것이죠. 이렇게 되면 도구에 종속되는 '망치의 오류'에 빠지기 쉽습니다. 새로운 알고리즘을 고안해야 하는 상황에서도 기존 알고리즘에 계속 매달릴 뿐입니다. 알고리즘을 새로 고안해 내건 혹은 기존의 것을 조합하건 스스로 생각해 내는 훈련이 필요합니다. 두 번째가 제대로 훈련되지 못한 사람은 일일이 구현해 보고 실험해 봐야만 알고리즘 간의 효율을 비교할 수 있습니다. 특히 자신이 가진 카탈로그를 벗어난 알고리즘을 만나면 이 문제가 생깁니다. 이건 상당한 대가를 치르게 합니다. 세 번째가 제대로 훈련되지 못한 사람은, 문제를 보면 "아, 이건 이렇게 저렇게 해결하면 됩니다"하는 말은 곧잘 할 수 있지만 막상 컴퓨터 앞에 앉혀 놓으면 아무 것도 하지 못합니다. 심지어 자신이 생각해낸 그 구체적 알고리즘을 남에게 설명해 줄 수는 있지만, 그걸 '컴퓨터에게' 설명하는 데는 실패합니다. 뭔가 생각해낼 수 있다는 것과 그걸 컴퓨터가 이해할 수 있게 설명할 수 있다는 것은 다른 차원의 능력을 필요로 합니다. 네 번째가 제대로 훈련되지 못한 사람은, 알고리즘을 특정 언어로 구현해도, 그것이 옳다는 확신을 할 수 없습니다. 임시변통(ad hoc)의 아슬아슬한 코드가 되거나 이것저것 덧붙인 누더기 코드가 되기 쉽습니다. 이걸 피하려면 두 가지 훈련이 필요합니다. 하나는 수학적·논리학적 증명의 훈련이고, 다른 하나는 테스트 훈련입니다. 전자가 이론적이라면 후자는 실용적인 면이 강합니다. 양자는 상보적인 관계입니다. 특수한 경우들을 개별적으로 테스트해서는 검증해야 할 것이 너무 많고, 또 모든 경우에 대해 확신할 수 없습니다. 테스트가 버그의 부재를 보장할 수는 없습니다. 하지만 수학적 증명을 통하면 그것이 가능합니다. 또, 어떤 경우에는 수학적 증명을 굳이 할 필요 없이 단순히 테스트 케이스 몇 개만으로도 충분히 안정성이 보장되는 경우가 있습니다. 이럴 때는 그냥 테스트만으로 만족할 수 있습니다. 실질적이고 구체적인 문제를 함께 다루라 자료구조와 알고리즘 공부를 할 때에는 가능하면 실질적이고 구체적인 실세계의 문제를 함께 다루는 것이 큰 도움이 됩니다. 모든 학습에 있어 이는 똑같이 적용됩니다. 인류의 지성사를 봐도, 구상(concrete) 다음에 추상(abstract)이 옵니다. 인간 개체 하나의 성장을 봐도 그러합니다. 'be-동사 더하기 to-부정사'가 예정으로 해석될 수 있다는 룰만 외우는 것보다 다양한 예문을 실제 문맥 속에서 여러 번 보는 것이 훨씬 나을 것은 자명합니다. 알고리즘과 자료구조를 공부할 때 여러 친구들과 함께 연습문제(특히 우리가 경험하는 실세계의 대상들과 관련이 있는 것)를 풀어보기도 하고, ACM의 ICPC(International Collegiate Programming Contest: 세계 대학생 프로그래밍 경진 대회) 등의 프로그래밍 경진 대회 문제 중 해당 알고리즘·자료구조가 사용될 수 있는 문제를 같이 풀어보는 것도 아주 좋습니다. 이게 가능하려면 "이 알고리즘이 쓰이는 문제는 이거다"하고 가이드를 해줄 사람이 있으면 좋겠죠. 이것은 그 구체적 알고리즘·자료구조를 훈련하는 것이고, 이와 동시에 어떤 알고리즘을 써야할지 선택, 조합하는 것과 새로운 알고리즘을 만들어내는 훈련도 무척 중요합니다. 알고리즘 디자인 과정의 중요성 알고리즘을 좀더 수월하게, 또 잘 만들려면 알고리즘 디자인 과정에 대해 생각해 봐야 합니다. 그냥 밑도 끝도 없이 문제를 쳐다본다고 해서 알고리즘이 튀어나오진 않습니다. 체계적이고 효율적인 접근법을 사용해야 합니다. 대표적인 것으로 다익스트라(E. W. Dijkstra)와 워스(N. Wirth)의 '조금씩 개선하기'(Stepwise Refinement)가 있습니다. 워스의 「Program Development by Stepwise Refinement」(1971, CACM 14.4, http://www.acm.org/classics/dec95)를 꼭 읽어보길 바랍니다. 여기 소개된 조금씩 개선하기는 구조적 프로그래밍에서 핵심적 역할을 했습니다(구조적 프로그래밍을 'goto 문 제거' 정도로 생각하면 안 됩니다). 다익스트라의 「Stepwise Program Construction」(Selected Writings on Computing: A Personal Perspective, Springer-Verlag, 1982, http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD227.PDF)도 추천합니다. 알고리즘 검증은 알고리즘 디자인과 함께 갑니다. 새로운 알고리즘을 고안할 때 검증해 가면서 디자인하기 때문입니다. 물론 가장 큰 역할은 고안이 끝났을 때의 검증입니다. 알고리즘 검증에는 루프 불변식(loop invariant) 같은 것이 아주 유용합니다. 아주 막강한 무기입니다. 익혀 두면 두고두고 가치를 발휘할 것입니다. 맨버(Udi Manber)의 알고리즘 서적(『Introduction to Algorithms: A Creative Approach』)이 알고리즘 검증과 디자인이 함께 진행해 가는 예로 자주 추천됩니다. 많은 계발을 얻을 것입니다. 고전으로는 다익스트라의 『A Discipline of Programming』과 그라이스(Gries)의 『The Science of Programming』이 있습니다. 특히 전자를 추천합니다. 프로그래밍에 대한 관을 뒤흔들어 놓을 것입니다. 알고리즘과 패러다임 알고리즘을 공부하면 큰 줄기들을 알아야 합니다. 개별 테크닉도 중요하지만 '패러다임'이라고 할만한 것들을 알아야 합니다. 이것에 대해서는 튜링상을 수상한 로버트 플로이드(Robert Floyd)의 튜링상 수상 강연(The Paradigms of Programming, 1978)을 추천합니다. 패러다임을 알아야 알고리즘을 상황에 맞게 마음대로 변통할 수 있습니다. 그리고 자신만의 분류법을 만들어야 합니다. 구체적인 문제들을 케이스 바이 케이스로 여럿 접하는 동안 그냥 지나쳐 버리면 개별자는 영원히 개별자로 남을 뿐입니다. 비슷한 문제들을 서로 묶어서 일반화해야 합니다. 이런 패러다임을 발견하려면 '다시 하기'가 아주 좋습니다. 다른 것들과 마찬가지로, 이 다시 하기는 알고리즘에서만이 아니고 모든 공부에 적용할 수 있습니다. 같은 것을 다시 해보는 것에서 우리는 얼마나 많은 것을 배울 수 있을까요. 대단히 많습니다. 왜 동일한 문제를 여러 번 풀고, 왜 같은 내용의 세미나에 또 다시 참석하고, 같은 프로그램을 거듭 작성할까요? 훨씬 더 많이 배울 수 있기 때문입니다. 화술 교육에서는 같은 주제에 대해 한 번 말해본 연사와 두 번 말해본 연사는 천지 차이가 있다고 말합니다. 같은 일에 대해 두 번의 기회가 주어지면 두 번째에는 첫 번째보다 잘 할 기회가 있습니다. 게다가 첫 번째 경험했던 것을 '터널을 벗어나서' 다소 객관적으로 볼 수 있게 됩니다. 왜 자신이 저번에 이걸 잘 못 했고, 저걸 잘 했는지 알게 되고, 어떻게 하면 그걸 더 잘할 수 있을는지 깨닫게 됩니다. 저는 똑같은 문제를 여러 번 풀더라도 매번 조금씩 다른 해답을 얻습니다. 그러면서 정말 엄청나게 많은 것을 배웁니다. '비슷한 문제'를 모두 풀 능력이 생깁니다. 제가 개인적으로 존경하는 전산학자 로버트 플로이드(Robert W. Floyd)는 1978년도 튜링상 강연에서 다음과 같은 말을 합니다. 제가 어려운 알고리즘을 디자인하는 경험을 생각해 볼 때, 제 능력을 넓히는 데 가장 도움이 되는 특정한 테크닉이 있습니다. 어려운 문제를 푼 후에, 저는 그것을 처음부터 완전히 새로 풉니다. 좀 전에 얻은 해법의 통찰(insight)만을 유지하면서 말이죠. 해법이 제가 희망하는 만큼 명료하고 직접적인 것이 될 때까지 반복합니다. 그런 다음, 비슷한 문제들을 공략할 어떤 일반적인 룰을 찾습니다. 아까 주어진 문제를 아예 처음부터 최고로 효율적인 방향에서 접근하도록 이끌어줬을 그런 룰을 찾는 거죠. 많은 경우에 그런 룰은 불변의 가치가 있습니다. … 포트란의 룰은 몇 시간 내에 배울 수 있습니다. 하지만 관련 패러다임은 훨씬 더 많은 시간이 걸립니다. 배우거나(learn) 배운 것을 잊거나(unlearn) 하는 데 모두. 수학자와 프로그래머를 포함한 모든 문제 해결자들의 고전이 된 죠지 폴리야(George Polya)의 『How to Solve it』에는 이런 말이 있습니다: 심지어는 꽤나 훌륭한 학생들도, 문제의 해법을 얻고 논증을 깨끗하게 적은 다음에는 책을 덮어버리고 뭔가 다른 것을 찾는다. 그렇게 하는 동안 그들은 그 노력의 중요하고도 교육적인 측면을 잃어버리게 된다. … 훌륭한 선생은 어떠한 문제이건 간에 완전히 바닥이 드러나는 경우는 없다는 관점을 스스로 이해하고 또 학생들에게 명심시켜야 한다. 저는 ACM의 ICPC 문제 중에 어떤 문제를 이제까지 열 번도 넘게 풀었습니다. 대부분 짝 프로그래밍이나 세미나를 통해 프로그래밍 시연을 했던 것인데, 제 세미나에 여러 번 참석한 분이 농담조로 웃으며 물었습니다. "신기해요. 창준 씨는 그 문제를 풀 때마다 다른 프로그램을 짜는 것 같아요. 설마 준비를 안 해 와서 그냥 내키는 대로 하는 건 아니죠?" 저는 카오스 시스템과 비슷하게 초기치 민감도가 프로그래밍에도 작용하는 것 같다고 대답했습니다. 저 스스로 다른 해법을 시도하고 싶은 마음이 있으면 출발이 조금 다르고, 또 거기서 나오는 진행 방향도 다르게 됩니다. 그런데 중요한 것은 이렇게 같은 문제를 매번 다르게 풀면서 배우는 것이 엄청나게 많다는 점입니다. 저는 매번, 전보다 개선할 것을 찾아내게 되고, 또 새로운 것을 배웁니다. 마치 마르지 않는 샘물처럼 계속 생각할 거리를 준다는 점이 참 놀랍습니다. 알고리즘 개론 교재로는 CLR(Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, and Ronald L. Rivest)을 추천합니다. 이와 함께 혹은 이 책을 읽기 전에 존 벤틀리(Jon Bentley)의 『Programming Pearls』도 강력 추천합니다. 세계적인 짱짱한 프로그래머와 전산학자들이 함께 꼽은 위대한 책 목록에서 몇 손가락 안에 드는 책입니다. 아직 이 책을 본 적이 없는 사람은 축하합니다. 아마 몇 주간은 감동 속에 하루하루를 보내게 될 겁니다. 리팩토링 학습에서의 문제 먼저, 본지 2001년 11월호에 제가 썼던 마틴 파울러의 책을 추천하는 글을 인용하겠습니다. OOP를 하건 안 하건 프로그래밍이란 업을 하는 사람이라면 이 책은 자신의 공력을 서너 단계 레벨업시켜줄 수 있다. 자질구레한 술기를 익히는 것이 아니고 기감과 내공을 증강하는 것이다. 혹자는 DP 이전에 RF를 봐야 한다고도 한다. 이 말이 어느 정도 일리가 있는 것이, 효과적인 학습은 문제의식이 선행해야 하기 때문이다. DP는 거시적 차원에서 해결안을 모아놓은 것이다. RF를 보고 나쁜 냄새(Bad Smell)를 맡을 수 있는 후각을 발달시켜야 한다. RF의 목록을 모두 외우는 것은 큰 의미가 없다. 그것보다 냄새나는 코드를 느낄 수 있는 감수성을 키우는 것이 더 중요하다. 필자는 일주일에 한 가지씩 나쁜 냄새를 정해놓고 그 기간 동안에는 자신이 접하는 모든 코드에서 그 냄새만이라도 확실히 맡도록 집중하는 방법을 권한다. 일명 일취집중후각법. 패턴 개념을 만든 건축가 크리스토퍼 알렉산더나 GoF의 랄프 존슨은 좋은 디자인이란 나쁜 것이 없는 상태라고 한다. 무색 무미 무취의 무위(無爲)적 자연(自然) 코드가 되는 그 날을 위해 오늘도 우리는 리팩토링이라는 유위(有爲)를 익힌다. 주변에서 리팩토링을 잘못 공부하는 경우를 종종 접합니다. 어떤 의미에서 잘못 공부한다고 할까요? '실체화'가 문제입니다. 리팩토링은 도구이고 방편일 뿐인데, 그것에 매달리는 것은 달은 보지 않고 손을 보는 것과 같습니다. 저는 리팩토링 책이 또 하나의 (이미 그 병폐가 많이 드러난) GoF 책이 되는 현상이 매우 걱정됩니다. 리팩토링 공부 사람들이 일반적으로 생각하는 바와는 달리 리팩토링 학습에 있어 어떤 리팩토링이 있는지, 구체적으로 무엇인지 등의 리팩토링 목록에 대한 지식과 각각에 대한 메카닉스(Mechanics: 해당 리팩토링을 해나가는 구체적 단계)는 오히려 덜 중요할 수 있습니다. 더 기본적이고 유용한 것은 코드 냄새(Code Smell)와 짧은 테스트-코드 싸이클입니다. 이것만 제대로 되면 리팩토링 책의 모든 리팩토링을 스스로 구성해낼 수 있으며, 다른 종류의 리팩토링까지 직접 발견해낼 수 있습니다. 그 책에서는 테스트의 중요성이 충분히 강조되지 않았습니다. 하지만 테스트 코드 없는 리팩토링은 안전벨트 없는 자동차 경주와 같습니다. 그리고 테스트 코드가 리팩토링의 방향을 결정하기도 합니다. 양자는 음과 양처럼 서로 엮여 있습니다. 이런 의미에서 리팩토링은 TDD(Test Driven Development)와 함께 수련하는 것이 좋습니다. 훨씬 더 빨리, 훨씬 더 많은 것을 배울 수 있을 겁니다. 리팩토링을 공부할 때는 우선 코드 냄새의 종류를 알고, 왜 그것이 나쁜 냄새가 될 수 있는지 이해하고(그게 불가하다면 리팩토링 공부를 미뤄야 합니다) 거기에 동의할 수 있어야 합니다. 그런 다음, 대충 어떤 종류의 리팩토링이 가능한지 죽 훑어봅니다. 그 중 몇 개는 메카닉스를 따라가면서 실험해 봅니다. 이제는 책을 덮습니다. 그리고 실제 코드를 접하고, 만약 거기에서 냄새를 맡는다면 이 냄새를 없애기 위해 어떻게 해야 할지 스스로 고민합니다. 리팩토링 책의 목록은 일단 무시하십시오. 그 냄새를 없애는 것이 목표이지, 어떤 리팩토링을 여기에 '써먹는 것'이 목표가 되어선 안 됩니다. 이 때, 반드시 테스트 코드가 있어야 합니다. 그래야 '좋은' 리팩토링을 할 수 있습니다. 책을 떠나 있으면서도 책에서 떠나지 않는 방법입니다. 리팩토링을 하기 전에 초록색 불(테스트가 모두 통과)이 들어온 시점에서 코드를 일부 고치면 빨간 불(테스트가 하나라도 실패)로 바뀔 겁니다. 이게 다시 초록색 불이 될 때까지 최소한도의 시간이 걸리도록 하십시오. 현 초록색에서 다음 초록색까지 최소한의 시간을 소비하도록 하면서 코드와 테스팅을 오가게 되면 자기도 모르는 사이에 훌륭한 리팩토링이 자발공으로 터져 나옵니다. 여기서 목적지는 우선은 OAOO(Once And Only Once: 모든 것은 오로지 한 번만 말해야 한다)를 지키는 쪽으로 합니다. 그러면 OAOO와 짧은 테스트-코드 싸이클을 지키는 사이 어느새 탁월한 디자인이 튀어나옵니다. 참고로 저는 '모래시계 프로그래밍'이란 걸 가끔 합니다. 모래시계나 알람 프로그램으로 테스트-코드 사이클의 시간을 재는 것입니다. 그래서 가급적이면 한 사이클이 3분 이내(대부분의 모래시계는 단위가 3분입니다)에 끝나도록 노력합니다. 여기서 성공을 하건 실패를 하건 많은 걸 얻습니다. 리팩토링 수련법 제가 고안, 사용한 몇 가지 리팩토링 수련법을 알려드립니다. ①일취집중후각법: 앞에 소개한 본지 2001년 11월호에서 인용된 글 참조 ②주석 최소화: 주석을 최소화하되 코드의 가독성이 떨어지지 않도록(혹은 오히려 올라가도록) 노력합니다. 이렇게 하면 자동으로 리팩토링이 이뤄지는 경우가 많습니다. ③OAOO 따르기: OAOO 법칙을 가능하면 최대한, 엄격하게 따르려고 합니다. 역시 자동으로 좋은 리팩토링이 이뤄집니다. 여기서 디자인패턴이 창발하기도 합니다. GoF 책을 한번도 보지 못한 사람이 디자인패턴을 자유자재로 부리는 경우를 보게 됩니다. ④디미터 법칙(Law of Demeter) 따르기: 디미터 법칙을 가능하면 지키려고 합니다. 어떤 리팩토링이 저절로 이뤄지거나 혹은 필요 없어지는가요? ⑤짝(Pair) 리팩토링: 함께 리팩토링합니다. 혼자 하는 것보다 더 빨리, 더 많은 걸 배우게 됩니다. 특히, 각자 작성했던 코드를 함께 리팩토링하고, 제3자의 코드를 함께 리팩토링해 봅니다. 사람이 많다면 다른 짝이 리팩토링한 것과 서로 비교하고 토론합니다. ⑥'무엇'과 '어떻게'를 분리: 어떻게에서 무엇을 분리해 내도록 합니다. 어떤 리팩토링이 창발합니까? 여기서 번, 짝 리팩토링은 아주 효과적인 방법입니다. 저는 이것을 협동적 학습(Collaborative Learning)이라고 부릅니다. 상대가 나보다 더 많이 아는 경우만이 아니고, 서로 아는 것이 비슷해도 많은 양의 학습이 발생합니다. 특히, 전문가와 함께 짝 프로그래밍을 하면 무서울 만큼 빠른 학습을 경험할 수 있습니다. 저와 짝 프로그래밍을 한 사람이 학습하는 속도에서 경이감을 느낀 적이 한두 번이 아닙니다. 문화는 사회적으로 학습되는 것입니다. 우리가 지식이라고 하는 것의 상당 부분은 문화처럼 암묵적인 지식(Tacit Knowledge)입니다. 전문가가 문제가 생겼을 때 어떻게 사고하고, 어떤 과정을 거쳐 접근하며, 어떻게 디버깅하고, 키보드를 어떤 식으로 누르는지, 사고 도구로 무엇을 사용하는지, 일 계획과 관리를 어떻게 하는지, 동료와 어떻게 대화하는지 등은 성문화되어 있지 않습니다. 그러나 이런 것들은 아주 중요합니다. 프로페셔널의 하루 일과의 대부분을 이루고 있기 때문입니다. 이런 것들은 전문가 바로 옆에서 조금씩 일을 도와주면서 배워야 합니다. 도제 살이(Apprenticeship)입니다. 진정한 전문가는 모든 동작이 우아합니다. 마치 춤을 추는 것 같습니다. 이 모습을 바로 곁에서 지켜보게 되면, 주니어는 한마디로 엄청난 충격을 받습니다. 그리고 스펀지처럼 빨아들이게 됩니다. 도대체 이 경험을 책이나 공장화한 학교가 어떻게 대신하겠습니까. 이와 관련해서는 레이브와 웽거(Jean Lave, Etienne Wenger)의 『Situated Learning : Legitimate Peripheral Participation』을 강력 추천합니다. 이 글을 보는 모든 교육 종사자들이 꼭 읽어봤으면 합니다. 이 협동적 학습은 두 사람만이 아니고 그룹 단위로도 가능합니다. 스터디에 이용하면 재미와 유익함 일석이조를 얻습니다. 이 외에, 특히(어쩌면 가장) 중요한 것은 일취집중후각법 등을 이용해 자신의 코드 후각의 민감도를 높이는 것입니다. 코드 후각의 메타포 말고도 유사한 메타포가 몇 가지 더 있습니다. 켄트 벡은 코드의 소리를 들으라고 하고, 저는 코드를 향해 대화하라고 합니다. 코드의 소리를 듣는 것은 코드가 원하는 것에 귀를 기울이는 것을 말합니다. 코드는 단순해지려는 욕망이 있습니다. 그걸 이뤄주는 것이 프로그래머입니다. 그리고 짝 프로그래밍을 할 때 두 사람의 대화를 코드에 남기도록 합니다. 주석이 아닙니다. 왜 이것이 중요한가는 본지 2001년 12월호 「허실문답 XP 강화」를 참고하기 바랍니다. 기학으로 우리 사상사에 큰 획을 그은 철학자요, '서울서 책만 사다 망한 사람'으로 이름을 날릴 정도로 엄청난 지식욕을 과시하던 조선시대 사상가 혜강 최한기는 그의 저술 『신기통』(神氣通)에서 '눈에 통하는 법(目通), 귀에 통하는 법(耳通), 코에 통하는 법(鼻通)' 등을 이야기하고 있습니다. 어떻게 하면 우리는 코드에 도통할 수 있을까요? 리팩토링을 공부하거나 혹은 했던 사람들에게 많은 영감과 메타포를 주는 책으로 일독을 권합니다. 필자가 기회가 닿는다면 프로그래밍을 혜강의 사상적 측면에서 조망한 글을 써보고 싶습니다. 앞서의 것들이 어느 정도 이뤄지고, 리팩토링에 대한 감이 오게 되면 그 때 비로소 리팩토링 책을 하나 하나 파헤치고 또 거기서 제대로 된 비판을 할 수 있게 됩니다. 디자인패턴 학습에서의 문제 잡지에 연재되거나 서적으로 출간된 혹은 세미나에서 진행되었던 디자인패턴 '강의'를 몇 가지 접했습니다. 훌륭한 강의도 많았지만 그렇지 못한 것도 있었습니다. 몇 가지 문제점을 지적하겠습니다. ◆패턴을 지나치게 실체화, 정형화해 설명한다. ◆컨텍스트와 문제 상황에 대한 설명이 없거나 부족하다. 결과적으로 문제를 해결하기 위해 패턴이 도입된 것이 아니라 패턴을 써먹기 위해 패턴이 도입된 느낌을 준다. ◆문제의식을 먼저 형성하게 하지 않고 답을 먼저 보여준 뒤 그걸 어디에 써먹을지 가르친다. 왜 이걸 쓰는 게 좋은지는 일언반구 언급이 없다. 독자는 '어린아이가 망치를 들고 있는 오류'에 빠질 것이다. ◆패턴이 어떻게 생성되었는지 그 과정을 보여주지 못한다. 즉, 스스로 패턴을 만들어내는 데 도움이 전혀 되지 않는다. ◆해당 패턴이 현실적으로 가장 자주 쓰이는 맥락을 보여주지 못한다. 대부분 장난감 문제(Toy Problem)에서 끝난다. 그런 패턴 강의를 하는 분들이 알렉산더(Christopher Alexander, 패턴언어 창시자)의 저작을 충실히 읽어봤다면 이런 병폐는 없을 것이라 생각합니다. 알렉산더의 저작을 접해보지 못 하고서 패턴을 가르치는 사람은 성경을 읽어보지 않은 전도사와 같을 것입니다. 알렉산더가 『The Timeless Way of Building』의 마지막에서 무슨 말을 하는가요? 이 마지막 단계에는 더 이상 패턴은 중요하지 않다. … 패턴은 당신이 현실적인 것에 대해 수용적이 되는 것을 가르쳐줬다. 패턴 역시 도구요, 방편일 뿐입니다. 패턴은 현실적인 것에 대해 수용적이 되도록 가르친다는 말은 결국 우리가 궁극적으로 추구하는 것은 패턴이 아니라 현실이어야 한다는 이야기입니다. 물론 처음 단계에는 교육적인 목적에서, 어느 정도 패턴에 얽매여도 괜찮다고는 해도, 나중에 패턴을 잊고 패턴에서 자유로워지려면 처음부터 패턴에 대해 도구적·방편적인 인식을 가져야 합니다. 미국 캘리포니아 주립대학의 교수 베티 에드워즈(Betty Edwards)가 쓴 책 중에 『Drawing on the Right Side of the Brain』이라는 유명한 베스트셀러가 있습니다. 사람의 뇌와 그림 그리기의 관계에 대한 탁월한 책입니다. 에드워즈는 자신의 그리기 실력을 향상시키기 위해 우뇌를 적극적으로 사용하는 구체적인 방법들을 가르쳐줍니다. 그 중 대표적인 것 하나가 대상을 뒤집어 놓고 그리는 것입니다. 지금 실험해 보길 바랍니다. 1000원권 지폐를 바로 놓고 그걸 비슷하게 그려보고, 이번에는 그걸 위아래가 거꾸로 되게 놓고 따라 그려보십시오. 아마 무척 놀랐을 겁니다. "아니 내가 이렇게 그림을 잘 그리다니! 그것도 거꾸로!" 그렇습니다. 우리는 자신의 머리 속 패턴에 얽매여 세상을 제대로 보지 못 할 때가 많습니다. 실체가 코에 약간이라도 비슷하게 보이면 우리는 그것을 이미 우리 머리 속에 추상적으로 갖고 있던 기하학적 '코'의 패턴으로 대체해버리는 것입니다. 디자인 패턴 공부 우선은 제 교육철학과 언어교습론, 그리고 공부론 이야기를 잠깐 하겠습니다. 기본적으로 교육은 교육자가 피교육자가에게 지식을 그대로 전달하는 행위가 아닙니다. 진정한 교육은 피교육자의 개인적 체험에 기반한 전폭적 동의에서 출발합니다. 저는 이를 동의에 의한 교육이라고 합니다. 제가 "주석문을 가능하면 쓰지 않는 것이 더 좋다"는 이야기를 했을 때 이 문장을 하나의 사실로 받아들이고 기억하면 당장 그 시점에는 학습이 일어나지 않는다고 봅니다. 대신 여러분이 차후에 여러 가지 경험을 하면서도 이 화두를 놓치지 않고 있다가 어느 순간엔가, "아! 그래, 주석문을 쓰지 않는 게 좋겠구나!"하고 자각하는 순간, 바로 그 시점에 학습과 교육이 이뤄지는 것입니다. 이는 기본적으로 삐아제와 비갓스키(Lev Vygotsky)의 구성주의를 따르는 것이죠. 지식이란 외부에서 입력받는 것이 아니고, 그것에 대한 모델을 학습자 스스로가 내부에서 구축할 때 획득할 수 있는 것이라는 사상이죠. 권법에서 주먹에 대해 달통한 도사가 '권을 내지르는 법'에 대한 규칙들을 정리해서 애제자의 머리 속에 아무리 쑤셔 넣는 데 성공한들 그 제자가 도사만큼 주먹이 나갈리는 만무합니다. 권을 내지르는 법을 유추해 내기까지 그 스승이 겪은 과정을 제자는 완전히 쏙 빼먹고 있기 때문입니다. 소위 '몸'이 만들어지지 않은 것이지요. 제자는 마당 쓸기부터, 물 긷기 등의 수련 과정을 겪어야만 하고 스승이 정리한 그 일련의 규칙에 손뼉을 치고 춤을 추며 기쁨의 동의를 할 수 있을 정도로 수련 과정이 축적된 이후에야 비로소 진정한 '가르침'이 이뤄지는 것이며, 청출어람의 가능성도 생각해 볼 수 있는 것입니다. 이런 동의라는 것은 학습자 자신만의 컨텍스트와 문제의식을 바탕으로 한 것입니다. 우리는 많은 경우, 어떤 지식과 동시에 그 지식의 필요성까지도 지식화해서 외부에서 주입을 받습니다. 하지만 진정 체화된 지식을 위해서는 스스로가 이미 문제의식을 갖고 있어야 합니다. 패턴도 마찬가지인데, 대부분 그 패턴의 필요성을 체감하지 못한 채 그냥 도식적 구조를 외우기에만 주력하는 사람이 많습니다만, 사실 그렇게 되면 어떤 경우에 이 패턴이 필요하고 어떤 경우에는 사용하면 안 되는지(GoF는 패턴을 정말 안다는 것은 그 패턴을 쓰면 안 될 때를 아는 것이라 했습니다) 등을 알기 힘듭니다. 설령 책에 나온 가이드를 암기했더라도요. 자신의 삶 속에서 문제의식이 구체적으로 실제 경험으로 형성되지 않았기 때문입니다. GoF 중 한 명인 랄프 존슨(Ralph Johnson)은 다음과 같이 말합니다. 우리[GoF]는 책에서, 정말 그 패턴들이 필요하다는 것을 알만큼 충분한 경험을 갖기 전에는 그것을 [시스템 속에] 집어넣는 것을 피해야 한다고 말할 만큼 대담하진 못했다. 하지만 우리 모두는 그 사실을 믿었다. 패턴은 프로그램의 초기 버전이 아니고 프로그램 생애의 훨씬 나중에 가서야 비로소 등장해야 한다고 나는 늘 생각해 왔다. 결국은 어떤 패턴의 필요성을 자신의 경험 속에서 절감하지 못한다면 그 패턴을 제대로 아는 것이 아니라고 말할 수 있을 겁니다. 따라서 패턴 하나를 공부할 때는 가능한 한 실제 예를 많이 접해야 합니다. 그리고 패턴을 적용하지 않은 경우에서 그 필요를 느끼고 설명할 수 있게끔 다양한 코드를 접해야 합니다. 소프트웨어 개발에 푹 빠지기 패턴 중에 보면 서로 비슷비슷한 것이 상당히 많습니다. 그 구조로는 완전히 동일한 것도 있죠. 초보자를 괴롭히는 것 중 하나입니다. 이것은 외국어를 공부할 때 문법 중심적인 학습을 하면서 부딪치는 문제와 비슷합니다. '주어+동사+목적어'라는 구조로는 동일한 두 개의 문장, 즉 'I love you'와 'I hate you'가 구조적으로는 동일할지라도 의미론적으로는 완전히 반대가 될 수 있는 겁니다. 패턴을 공부할 때는 그 구조보다 의미와 의도를 우선해야 하며, 이는 다양한 실례를 케이스 바이 케이스로 접하면서 추론화 및 자신만의 모델화라는 작업을 통해 하는 것이 최선입니다. 스스로 문법을 발견하고 체득하는 것이라고 할까요. DP는 사전과 같습니다. 이 책은 순서대로 소설 읽듯이 읽어나가라고 집필된 것이 아니고, 일종의 패턴 레퍼런스로 쓰인 것입니다. 역시 GoF의 한 명인 존 블리스사이즈(John Vlissides)는 다음과 같이 말합니다. 여기서 내가 강조하고 싶은 것은 디자인패턴, 즉 GoF 책을 어떻게 읽느냐는 것이다. 많은 사람들은 그 내용을 온전히 이해하기 위해서는 순서대로 읽어야 한다고 느낀다. 하지만 GoF는 소설이 아니라 레퍼런스 북이다. 독일어를 배우기 위해 독영 사전의 처음부터 끝까지 하나하나 읽으려고 하는 경우를 생각해 보라. 그렇게는 결코 배울 수 없을 것이다! 독일어를 마스터하기 위해서는 독일어 문화에 자기 자신을 푹 담궈야(immerse) 한다. 독일어로 살아야 하는 것이다. 디자인패턴도 똑같다. 그걸 마스터하기 이전에 소프트웨어 개발에 자신을 푹 담궈야 한다. 패턴으로 살아야 하는 것이다. 만약 꼭 그래야 한다면 소설 읽듯이 디자인패턴 책을 읽어라. 하지만 거의 아무도 그 방식으로 유창해지지 못한다. 소프트웨어 개발 프로젝트의 열기 속에서 패턴이 동작하게 하라. 실제 디자인 문제를 직면했을 때 그 패턴들의 통찰을 이용하라. 이것이 GoF 패턴들을 자신의 것으로 만드는 가장 효율적인 방법이다. 어떤 지식을 체화하기 위해선 그 지식으로 살아야 한다는 말을 확인할 수 있습니다. 영어를 배우려면 영어로 살고, DP를 배우려면 DP로 살라는 단순하면서도 아주 강력한 말입니다. 어떤 특정 문장 구조를 학습하는 데 최선은 그 문장 구조를 이용한 실제 문장을 나에게 의미 있는 실제 컨텍스트 속에서 많이 접하고 스스로 나름의 모델을 구축하여 교과서의 법칙에 '기쁨에 찬 동의'를 하는 것입니다. 주변에서 특정 패턴이 구현된 코드를 구하기가 힘들다면 이 패턴을 자신이 만지고 있는 코드에 적용해 보려고 노력해 볼 수 있습니다. 이렇게 해보고 저렇게도 해보고, 그러다가 오히려 복잡도만 증가하면 "아 이 경우에는 이 패턴을 쓰면 안 되겠구나"하는 걸 학습할 수도 있죠. GoF는 패턴을 배울 때는 한결 같이 "이 패턴이 적합한 상황과 동시에 이 패턴이 악용, 오용될 수 있는 상황"을 함께 공부하라고 합니다. 이런 식의 '사례 중심'의 공부를 위해서는 스터디 그룹을 조직하는 것이 좋습니다. 혼자 공부를 하건, 그룹으로 하건 커리프스키(Joshua Kerievsky)의 「A Learning Guide To Design Patterns」(http://www.industriallogic.com/papers/learning.html)를 참고하세요. 그리고 스터디 그룹을 효과적으로 꾸려 나가는 데는 스터디 그룹의 패턴 언어를 서술한 「Knowledge Hydrant」(http://www.industriallogic.com/papers/khdraft.pdf)를 참고하면 많은 도움이 될 겁니다. 이 문서는 뭐든지 간에 그룹 스터디를 한다면 적용할 수 있습니다. LG2DP(「A Learning Guide To Design Patterns」) 뒷부분에 보면 DP를 공부하는 순서와 각 패턴에서 던질만한 질문이 같이 정리되어 있습니다. DP는 순차적으로 공부해야만 하는 것은 아닙니다. 효과적인 공부의 순서가 있습니다. sorry라는 단어를 모르면서 remorseful이라는 단어를 공부하는 학생을 연상해 보세요. 외국어 공부에서는 자기 몸에 가까운 쉬운 단어부터 공략하는 것이 필수적입니다. 이런 걸 근접 학습(Proximal Learning)이라고도 하죠. 등급별 어휘 목록 같은 게 있으면 좋죠. LG2DP에서 제안하는 순서가 그런 것 중 하나입니다. 랄프 존슨은 이런 순서의 중요성에 관해 다음과 같은 말을 했습니다. … 하지만 나는 언제나 싱글톤 패턴을 가르치기 전에 콤포짓, 스트래터지, 템플릿 메쏘드, 팩토리 메쏘드 패턴을 가르친다. 이것이 훨씬 더 일반적인 것들이며, 대다수의 사람들은 아마도 이것들 중 마지막 두 가지를 이미 사용하고 있을 것이다. 마이크로패턴 그런데 사실 GoF의 DP에 나온 패턴들보다 더 핵심적인 어휘군이 있습니다. 마이크로패턴이라고도 불리는 것들입니다. DP에도 조금 언급되어 있긴 합니다. 이런 마이크로패턴은 우리가 알게 모르게 매일 사용하는 것들이고 그 활용도가 아주 높습니다. 실제로 써보면 알겠지만, DP의 패턴 하나 쓰는 일이 그리 흔한 게 아닙니다. 마이크로패턴은 켄트 벡의 『Smalltalk Best Practice Patterns』에 잘 나와 있습니다. 영어로 치자면 관사나 조동사 같은 것들입니다. 그리고 이런 마이크로패턴과 함께 리팩토링을 공부하는 게 좋습니다. 리팩토링은 패턴의 필요를 느끼게 해줍니다. 제가 리팩토링 공부에서도 언급했지만 OAOO를 지키면서 리팩토링을 하다보면 자연스레 디자인패턴에 도달하는 경우가 많습니다. 이 때는 지나친 엔지니어링(Overengineering)이 발생하지 않고, 오로지 필요한 만큼만 생깁니다. 이에 관해서는 커리프스키의 「Stop Over-Engineering!」(Software Development Magazine, Apr 2002, http://www.sdmagazine.com/documents/s=7032/sdm0204b/0204b.htm)의 일독을 권합니다. 리팩토링이 디자인패턴을 어떻게 생성해낼 수 있는지 보여주고 있습니다. 1980년대 이후 최근 알렉산더의 향방도 이런 쪽으로 가고 있습니다. 그는 자신이 발표한 기존 패턴들이 너무 크다고 생각해 그런 패턴들을 구성하고, 자동으로 만들어 내며, 또 관통하는 더 작은 원칙들을 발견하는 데 노력해 오고 있습니다. 코플리엔(James Coplien)은 컴퓨터계가 알렉산더의 최근 발전을 쫓아가지 못한다고 늘 이야기합니다. 제대로 된 패턴 구현을 위한 다양한 접근 시도하기 우리의 지식이라는 것은 한 가지 표현양상(representation)으로만 이뤄져 있지 않습니다. 사과라는 대상을 음식으로도, 그림의 대상으로도 이해할 수 있어야 합니다. 실제 패턴이 적용된 '다양한 경우'를 접하도록 하라는 것이 이런 겁니다. 동일 대상에 대한 다양한 접근을 시도하라는 것이죠. 자바로 구현된 코드도 보고, C++로 된 것도 보고, 스몰토크로 된 것도 봐야 합니다. 설령 '오로지 자바족'이라고 할지라도요(전 이런 사람들을 자바리안(Javarian)이라고 부릅니다. 자바와 바바리안(barbarian)을 합성해서 만든 조어지요). 이런 '오로지 하나만 공부하는 것'의 병폐에 대해서는 존 블리스사이즈가 쓴 「Diversify」(http://www.research.ibm.com/people/v/vlis/pubs/gurus-99.pdf)라는 글을 읽어보세요. 이렇게 다양화를 해야 비로소 자바로도 '상황에 맞는' 제대로 된 패턴을 구현할 수 있습니다. 패턴은 그 구현(implementation)보다 의도(intent)가 더 중요하다는 사실을 꼭 잊지 말고, 설명을 위한 방편으로 채용된 한 가지 도식에 자신의 사고를 구속하는 우를 범하지 않기를 빕니다. 이런 맥락에서 저는 DP를 공부할 때 GoF와 동시에 『Design Patterns Smalltalk Companion』을 필수적으로 읽기를 권합니다. 두 권은 말하자면 양날개입니다. 하나는 정적언어로 구현되었고(간간이 스몰토크 구현이 있긴 합니다), 다른 하나는 동적언어로 구현되어 있습니다. 언어와 패턴의 고리를 느슨하게 하고, 패턴을 여러 관점에서 신선하게 볼 수 있는 계기가 될 것입니다. 또, 한 쪽을 보고 이해가 잘 되지 않을 때 다른 쪽을 보면 쉽게 이해됩니다. 서로 상보적인 것이죠. 패턴도 결국 '문제해결'을 위한 한 가지 방편에 지나지 않습니다. 주변에서 "이 경우에는 무조건 이 패턴을 써야 합니다"하고 생떼를 쓰는 사람을 보면 씁쓸한 기분을 감출 수 없습니다. 디자인패턴 추천서 디자인패턴 책 중에 중요한 서적을 몇 권 소개하겠습니다. ◆『Design Patterns Explained』(Shalloway, Trott): 최근 DP 입문서로 급부상하고 있는 명저 ◆『Design Patterns Java Workbook』(Steven John Metsker): DPE 다음으로 볼만한 책으로 쏟아져 나오는 시중의 조악한 자바 패턴 책들과는 엄연히 다르다. 워크북 형식을 채용해서 연습문제를 풀고 뒷부분의 답과 대조해 볼 수 있는 등 독학자가 공부하기에 좋다. ◆『Refactoring』(Martin Fowler): DP 공부 이전에 봐서 문제의식 형성하기(망치를 들면 모든 것이 못으로 보이는 오류 탈피) ◆『Design Patterns』: 바이블. ◆『Design Patterns Smalltalk Companion』: GoF가 오른쪽 날개라면 DPSC는 왼쪽 날개 ◆『Pattern Hatching』(John Vlissides): DP 심화학습. 얇지만 밀도 높은 책. ◆『Smalltalk Best Practice Patterns』(Kent Beck): 마이크로 패턴. 개발자의 탈무드. 감동의 연속. ◆『Pattern Languages of Program Design』 1,2,3,4: 패턴 컨퍼런스 논문 모음집으로 대부분은 인터넷에서 구할 수 있음 ◆『Pattern-Oriented Software Architecture』 1,2: 아키텍처 패턴 모음. 2권은 네트워크 애플리케이션의 아키텍처 모음. ◆『Concurrent Programming in Java』(Doug Lea): 컨커런트 프로그래밍에 대한 최고의 서적. ◆『Patterns of Software』(Richard Gabriel): 패턴에 관한 중요한 에세이 모음. ◆『Analysis Patterns』(Martin Fowler): 비즈니스 분석 패턴 목록. 비즈니스 애플리케이션 개발자에게 많은 도움이 됨. ◆『A Timeless Way of Building』(Christopher Alexander): 프로그래머들이 가장 많이 본 건축 서적. 패턴의 철학적·이론적 배경. '구약'('신약'은 올해 안에 출간 예정인 동저자의 『The Nature of Order』). ◆『A Pattern Language』(Christopher Alexander): 알렉산더의 건축 패턴 모음집. ◆『Problem Frames』(Michael Jackson): DP의 해결(solution) 지향식의 문제점과 극복 방안으로서의 문제 지향식 방법. 마이클 잭슨은 요구 사항 분석 쪽에서 동명의 가수만큼이나 유명. DP를 처음 공부한다면, DPE와 DPJW를 RF와 함께 보면서 앞서의 두 권을 RF적으로 독해해 나가기를 권합니다(하버드 대학의 뚜웨이밍 교수는 요즘 칸트를 유교적으로 독해하고 있다고 합니다. 하나의 책을 다른 각도에서 독해하는 것, 여기서 배우는 것이 많습니다). 이게 된 후에는 GoF와 DPSC를 함께 볼 수 있습니다. 양자는 상호 보완적인 면이 강합니다. 이쯤 되어 SBPP를 보면 상당히 충격을 받을 수 있습니다. 스스로가 생각하기에 코딩 경험이 많다면 다른 DP 책 이전에 SBPP를 먼저 봐도 좋습니다. 이 정도의 책을 봤다면 POSA와 PLOPD 등에서 자신이 관심이 가는 패턴들을 찾아 읽는 것이 좋습니다. 그리고 동시에 알렉산더의 원저들을 꼭 읽기를 권합니다. 가브리엘의 책이 알렉산더의 사상 이해에 많은 도움이 될 것입니다. 패턴 공부를 해나가면서 남을 가르치는 것이 공부에 많은 도움이 됩니다(사실 자바 패턴 책 중에 어떤 것은 "내가 패턴을 처음 공부하면서 같이 쓴 것이다"라고 저자가 고백한 것도 있습니다). 보이스카웃에서는 보통 다음 과정을 통해 뭔가를 '학습'하게 한다고 합니다. 처음은 어떻게 하는지를 보여주고, 다음은 스스로 그것을 해보게 하고, 다음으로 그걸 남에게 가르치게 합니다. 이 때 중요한 것은 상대가 이해하지 못 하면 그 이유를 자기 자신에게서 찾는 것이 나에게 더 이득이 된다는 것입니다. "내가 설명을 잘못 했군"하고 생각하는 것이죠. 그러면 다음번에는 설명을 좀더 잘 할 수 있게 되고, 동시에 자기의 이해도 더욱 명료해지게 됩니다. 저는 'OOP 개념을 한 시간 만에 가르치기'나 '특정 언어 문법을 한 시간 만에 가르치기' 등을 하나의 도전으로 생각하고 즐깁니다. 가르치면서 동시에 배운다는 것은 정말 놀라운 경험입니다. 익스트림 프로그래밍 학습에서의 문제 앞의 경우와 비슷합니다. 익스트림 프로그래밍을 공부하는 사람들은 실제로 행해보지 않고 책만 들여다보면 안 됩니다. 그렇다고 책이 중요하지 않다는 말은 아닙니다. 하지만 자전거 타기는 자기 몸으로 직접 굴려봐야 합니다. 게다가 켄트 벡 스스로가 『XP Explained』를 만약 다시 쓴다면 뜯어고치고 싶은 부분이 상당히 된다고 말하는 것을 봐도 알 수 있듯이 초기 XP 이후 바뀌고 보완된 점이 상당수 있습니다. 따라서 책만으로 XP를 공부하기는 힘듭니다. 지금은 책 속의 XP가 사람들의 머리 속 XP에 한참 뒤쳐져 있습니다. 어찌 되었든 XP에는 무술이나 춤, 혹은 악기 연주 등과 유사한 면이 많습니다. 따라서 글을 보고 그것을 익히기는 쉽지 않습니다. 그나마 메일링 리스트 같은 '대화'를 보면 훨씬 더 많은 것을 얻을 수 있기는 하지만, 태권도 정권 찌르기를 말로 설명하는 것이 불가능에 가깝듯이 XP를 언어를 통해 익히기는 정말 어렵습니다. 우리의 언어는 너무도 성글은 미디어입니다(XP는 매 초, 매 순간 벌어지는 '일상적' 장면의 연속이 매우 중요합니다). 익스트림 프로그래밍 공부 XP를 이해하려면 다음 기본 자료에 대한 이해가 우선해야 합니다(본지 2001년 12월호 「허실문답 XP 강화」 참조). ◆『XP Explained』(Kent Beck): XP 선언서 ◆『XP Installed』(Ron Jeffries et al): C3 프로젝트에 적용한 예, 얻은 교훈 등 ◆『Planning XP』(Kent Beck, Martin Fowler): 계획 부분 설명(관리자, 코치용) ◆『Refactoring』(Martin Fowler): 리팩토링에 대한 최고의 책 ◆『XP Applied』: 유즈넷과 메일링 리스트의 논의 등 최근 자료를 반영 ◆『XP Explored』: 가장 쉽고 구체적인 XP 안내서 이 중에서 XPI나 XPX를 먼저 권합니다. XPE는 좀 추상적인 서술이 많아서 봐도 느낌이 별로 없을 수 있습니다(2001년 본지 11월호에 제가 쓴 리뷰 참고). 여유가 되면 다음 자료를 더 참고합니다. ◆『The Timeless Way of Building』: 패턴 운동을 일으킨 알렉산더의 저작. 현장 고객(On-site Customer), 점진 성장(Piecemeal Growth), 소통(Communication) 등의 아이디어가 여기에서 왔음. ◆『XP in Practice』(Robert C. Martin 외): 두세 사람이 짧은 기간 동안 간단한 프로젝트를 XP로 진행한 것을 기록. 자바 사용(중요한 문헌은 아님). ◆『XP Examined』: XP 컨퍼런스에 발표된 논문 모음 ◆『Peopleware』(Tom DeMarco): 개발에 있어 인간 중심적 시각의 고전 ◆『Adaptive Software Development』(Jim Highsmith): 복잡계 이론을 개발에 적용. 졸트상 수상. ◆『Surviving Object-Oriented Projects』(Alistair Cockburn): 얇고 포괄적인 OO 프로젝트 가이드라인 ◆『Software Project Survival Guide』(Steve McConnell): 조금 더 전통적인 SE 시각. ◆『The Psychology of Computer Programming』(Gerald M. Weinberg): 프로그래밍에 심리학을 적용한 고전. 코드 공유와 짝 프로그래밍에 필수인 비자아적 프로그래밍(Egoless Programming)이 여기서 나왔다. ◆『Agile Software Development』(Alistair Cockburn): 전반적 애자일 방법론에 대한 개론서 ◆『Software Craftsmanship』(Pete McBreen): 장인으로서의 새로운 프로그래머 상 ◆『Agile Software Development with SCRUM』(Schwaber Ken): 최근 확장성(Scalability)을 위해 XP+SCRUM의 시도가 애자일 쪽의 큰 화두임. ◆『A Practical Guide to eXtreme Programming』(David Astels 외): 저자들이 직접 참여한 프로젝트를 따라가 보면서 배움. 자바로 구현. XPP보다는 스케일이 큼. ◆『Agile Modeling』(Scott Ambler): 애자일 쪽에서 모델링이 무시되는 느낌이 있을 수 있는데, 그쪽으로 깊게 천착한 사람이 앰블러임. ◆『Agile Software Development Ecosystems』(Jim Highsmith): 각각의 애자일 방법론에 대한 소개와 동시에 각 방법론의 대표자들 인터뷰가 백미. ◆『Test Driven Development』(Kent Beck): 곧(아마 올해 내에) 출간 예정인 최초의 TDD 서적. TDD를 모르면 XP도 모르는 것(TDD를 실제 적용하려면 적어도 반년 정도는 계속 훈련해야 함) ◆IEEE Software/Computer, CACM, Software Development Magazine 등에 실린 기사 ◆『XP Conference, XP Universe 등의 논문들(특히 최근 것들) ◆유즈넷, 메일링 리스트, 오리지널 위키(http://c2.com)의 논의들 특히 유즈넷, 메일링 리스트, 오리지널 위키는 늘 가까이 하고 있어야 합니다. 이 세 곳을 살필 때, 특히 다음 사람들의 글은 꼭 읽어보고 항상 레이더를 열어두면 좋습니다(이 외에도 개발 경력 10년, 20년이 넘는 짱짱한 사람이 많으므로 눈 여겨 관찰하세요. 모든 글을 읽는 것은 무리이므로 그들의 대화를 일차적으로 읽어야 합니다). 켄트 벡, 론 제프리즈(Ron Jeffries), 워드 커닝엄(Ward Cunningham), 앨리스테어 코번(Alistair Cockburn), 마틴 파울러, 로버트 마틴 혹은 엉클 밥(Robert C. Martin aka Uncle Bob), 마이클 페더즈(Michael Feathers), 켄 아우어(Ken Auer), 윌리엄 웨이크(William Wake), 로이 밀러(Roy Miller), 데이브 토마스(Dave Thomas), 앤디 헌트(Andy Hunt), 랄프 존슨, 스카트 앰블러(Scott Ambler), 짐 하이스미스(Jim Highsmith), 조슈아 커리프스키(Joshua Kerievsky), 로렌트 보사빗(Laurent Bossavit), 존 브루어(John Brewer) 등 이런 자료들 외에, 기회가 된다면 주변에서 XP를 직접 사용하는 곳을 방문해서 하루만 같이 생활해 보기를 권합니다. 반년 공부를 앞당길 수 있습니다. 제가 공부할 때는 주변에 XP를 아는 사람이 없어서 혼자 공부했는데, 그것에 비해 XP를 직접 사용하는 상황에 처한 사람은 (제가 억울하리만큼) 더 적은 노력으로 몇 배 이상 빨리 몸에 익히는 것 같았습니다. 이게 힘들면 같이 공부하는 방법이 있습니다(앞서 언급된 스터디 그룹에 관한 패턴 참고). 이 때 같이 책을 공부하거나 하는 것은 시간 낭비가 많습니다. 차라리 공부는 미리 다 해오고 만나서 토론을 하거나 아니면 직접 실험을 해보는 것이 훨씬 좋습니다. 두 사람 당 한 대의 컴퓨터와 커대란 화이트보드를 옆에 두고 말이죠. 제 경우 스터디 팀과 함께 저녁 시간마다 가상 XP 프로젝트를 많이 진행했고, 짤막짤막하게 프로그래밍 세션도 많이 가졌습니다. 나중에 회사에서 직접 XP를 사용할 때 많은 도움이 되었습니다. Refactor Me 제가 하고 싶은 말은 더 있지만 이 글은 일단 여기서 끝이 납니다. 서두에서 말씀드렸듯이 애초 쓰려던 '일반론'은 생략하고, 대신 독자들의 몫으로 남겨두려 합니다. 이 글 자체가 여러분의 리팩토링 수련의 연장(延長)이 되었으면 하는 바램입니다. 이 글과 함께 실생활에서 직접 실험을 해보면서 - 이 때 욕심 부리지 않고 한 가지씩 지긋이 해보는 느긋함과 음미의 정신이 필요할지도 모르겠습니다 - 자신의 경험을 축적해 나가고, 동시에 이 글을 적절히 리팩토링해서 자신만의 패턴을 차근히 만들어 나가길 바랍니다. 그렇습니다. 리팩토링은 대상에 대한 이해가 깊고 경험이 많을수록 더 잘할 수 있습니다. 이 글에 소개된 제 공부론은 어찌 보면 상당히 진부해 보이기도 할 것입니다. 하지만 저는 이런 상식적이고 일상적이며 심지어는 소소해 보이는 것들에서 많은 감동을 받아왔습니다. 이 글도 사실 제 감동의 개인사입니다. 저는 "만약 오늘 어떤 것에라도 감동한 것이 없었다면, 오늘은 뭔가 잘못 산 것이다"라는 신조를 갖고 있습니다. 그것이 컴퓨터이건 대화이건 상관없이 말이죠. 저는 날마다 감동하며 살려고 노력합니다. 그러나 이 감동에 뭔가 꼭 대단한 것이 필요한 것은 아닙니다. 저는 오히려 감동 받기 위해 스스로 대단해져야 할 필요를 느끼기도 합니다. '감동'이라는 것은 주어지는 것이 아닙니다. 나와 타자가 공조하여 만드는 대화입니다. 감동해야 체득할 수 있다고 생각합니다. 그리고 이 감동은 개인적 삶 속에서 자기가, 자신의 몸으로, 직접 얻는 것입니다. 工夫 열심히 합시다. |
프로그래밍은 예술이다? (0) | 2007.03.03 |
---|---|
각종 확장자 파일 모음 (0) | 2007.03.03 |
자바스크립트 강좌, 사용법, 객체, 이벤트 등 (0) | 2007.03.03 |
프로그래머를 위한「공부론」 (0) | 2007.03.03 |
---|---|
자바스크립트 강좌, 사용법, 객체, 이벤트 등 (0) | 2007.03.03 |
insertAdjacentElement Method (0) | 2007.03.03 |
<script language="javascript">
JavaScript Statements
</script>
<script language="javascipt" src="src.js">
</script>
arrayName = new Array(arrayLength)
arrayName = new Array()
arrayName = new Array(value0,value1, ..., valuen)
HTML 태그 | JavaScript 이벤트 | 설명 |
---|---|---|
다양 | mouseMove | 마우스 이동 |
<A>..</A> | Click | 마우스로 링크를 클릭 |
dbClick | 마우스를 링크위에서 더블클릭 | |
mouseDown | 마우스 버튼을 누름 | |
mouseUp | 마우스 버튼을 놓음 | |
mouseOver | 마우스를 링크위로 이동 | |
mouseOut | 링크 위에 있던 마우스를 링크 밖으로 이동 | |
keyDown | 사용자가 키를 누름 | |
keyUp | 사용자가 키를 놓음 | |
keyPress | 사용자가 키를 눌렀다가 놓음 | |
<IMG> | abort | 사용자 액션으로 인해 이미지 로딩 작업을 중단함 |
error | 이미지 로딩하는 동안 에러 발생 | |
load | 이미지가 로드되고 화면에 나타남 | |
keyDown | 사용자가 키를 누름 | |
keyUp | 사용자가 키를 놓음 | |
keyPress | 사용자가 키를 눌렀다가 놓음 | |
<AREA> | mouseOver | 마우스가 클라이언트측 이미지맵의 한 영역으로 이동함 |
mouseOut | 마우스가 이미지맵 영역 밖으로 이동 | |
dbClick | 사용자가 이미지맵의 한 영역을 더블클릭함 | |
<BODY>..</BODY> | Click | 사용자가 문서의 본문을 클릭 |
dbClick | 문서의 본문을 더블 클릭함 | |
keyDown | 키를 누름 | |
keyUp | 키를 놓음 | |
keyPress | 키를 눌렀다가 놓음 | |
mouseDown | 마우스 버튼을 누름 | |
mouseUp | 마우스 버튼을 놓음 | |
<BODY>..</BODY> <FRAMESET>..</FRAMESET> <FRAME>..</FRAME> |
blur | 윈도우에서 현재 입력 포커스가 사라짐 |
error | 윈도우가 로드되는 동안 에러 발생 | |
focus | 입력 포커스가 현재 윈도우로 이동 | |
load | 윈도우 로딩이 완료됨 | |
unload | 윈도우를 종료함 | |
move | 윈도우가 이동됨 | |
resize | 윈도우의 크기가 바뀜 | |
dragDrop | 윈도우에 객체를 드롭 | |
<FORM>..</FORM> | submit | 사용자가 폼을 제출 |
reset | 사용자가 폼을 재설정 | |
<INPUT TYPE="text"> | blur | 현재 입력 포커스가 텍스트 필드에서 사라짐 |
focus | 현재 입력 포커스가 텍스트 필드로 이동 | |
change | 텍스트 필드가 변경되어 현재 입력 포커스가 사라짐 | |
select | 텍스트 필드에 있는 텍스트가 선택됨 | |
<INPUT TYPE="password"> | blur | 패스워드 필드에서 입력 포커스가 사라짐 |
focus | 패스워드 필드에 입력 포커스 생김 | |
<TEXTAREA>..</TEXTAREA> | blur | 텍스트 영역이 현재 입력 포커스가 사람짐 |
focus | 텍스트 영역에 입력 포커스 생김 | |
change | 텍스트 영역이 변경되어 입력 포커스가 사라짐 | |
select | 텍스트 영역에서 텍스트가 선택됨 | |
keyDown | 키를 누름 | |
keyUp | 키를 놓음 | |
keyPress | 키를 눌렀다 놓음 | |
<INPUT TYPE="button"> | Click | 버튼이 클릭됨 |
blur | 입력할 수 없도록 버튼이 흐려짐 | |
focus | 입력할 수 있도록 포커스 생김 | |
mouseDown | 버튼 위에서 왼쪽 마우스 버튼 누름 | |
mouseUp | 버튼 위에서 왼쪽 마우스 버튼 놓음 | |
<INPUT TYPE="submit"> | Click | 제출 버튼이 클릭됨 |
blur | 제출 버튼에서 입력 포커스가 사라짐 | |
focus | 제출 버튼에 입력 포커스 생김 | |
<INPUT TYPE="reset"> | Click | 리셋 버튼이 클릭됨 |
blur | 리셋 버튼에서 포커스가 사라짐 | |
focus | 리셋 버튼에서 포터스가 놓임 | |
<INPUT TYPE="radio"> | Click | 라디오 버튼이 클릭 |
blur | 라디오 버튼에서 입력 포커스가 사라짐 | |
focus | 라디오 버튼에 입력 포커스 생김 | |
<INPUT TYPE="checkbox"> | Click | 체크 박스가 클릭 |
blur | 체크 박스에서 입력 포커스가 사라짐 | |
focus | 체크 박스에 입력 포커스 놓임 | |
<INPUT TYPE="file"> | blur | 파일 업로드 폼 요소에서 입력 포커스 사라짐 |
change | 사용자가 업로드될 파일을 선택 | |
focus | 파일 업로드 폼 요소에 입력 포커스 놓임 | |
<SELECT>..</SELECT> | blur | 선택 요소가 현재 입력 포커스 잃음 |
change | 선택 요소가 변경되어 입력 포커스가 사라짐 | |
focus | 선택 요소에 현재 입력 포커스가 놓임 |
이벤트핸들링속성 | 실행되는 상황 |
---|---|
onAbort | 이미지를 로딩하는 작업이 사용자의 한 행동으로 인해 취소되었음 |
onBlur | 문서나 윈도우, 프레임세트, 폼 요소에서 현재 입력 포커스가 사라짐 |
onChange | 텍스트 필드나 텍스트 영역, 파일 업로드 필드, 선택 항목이 변경되어 현재 입력 포커스가 사라짐 |
onClick | 링크나 클라이언트측 이미지맵 영역, 폼 요소가 클릭됨 |
onDbClick | 링크나 클라이언트측 이미지맵 영역, 문서가 더블 클릭됨 |
onDragDrop | 드래그된 객체가 윈도우나 프레임에 드롭됨 |
onError | 이미지나 윈도우, 프레임을 로딩하는 동안 에러가 발생함 |
onFocus | 문서나 윈도우, 프레임 세트, 폼 요소에 입력 포커스 놓임 |
onKeyDown | 키를 누름 |
onKeyPress | 키를 눌렀다 놓음 |
onKeyUp | 키를 놓음 |
onLoad | 이미지나 문서, 프레임이 로드됨 |
onMouseDown | 마우스 버튼 누름 |
onMouseMove | 마우스를 이동함 |
onMouseOut | 링크나 클라이언트측 이미지맵에서 마우스를 옮김 |
onMouseOver | 마우스를 링크나 클라이언트측 이미지맵으로 옮김 |
onMouseUp | 마우스 버튼을 놓음 |
onMove | 사용자가 윈도우나 프레임을 이동함 |
onReset | 폼의 리셋 버튼을 클릭하여 폼을 리셋시킴 |
onResize | 사용자가 윈도우나 프레임의 크기를 조절 |
onSelect | 텍스트는 텍스트 필드나 영역에서 선택됨 |
onSubmit | 폼이 제출됨 |
onUnload | 사용자가 문서나 프레임 세트를 종료함 |
객 체 | 용 도 |
---|---|
window 객체 | 브라우저 윈도우나 윈도우 안에 있는 프레임에 액세스할 때 사용한다. 프로퍼티와 메소드를 참조할 때, window 객체가 존재하는 경우에는 "window."접두사를 붙일 필요가 없다 |
document 객체 | 현재 윈도우에 로드되어 있는 문서에 액세스할 때 사용한다. document 객체는 컨텐트를 제공하는 HTML 문서, 즉 HEAD와 BODY 태그가 있는 문서를 의미한다. |
location 객체 | URL을 나타낼 때 사용한다. 이 객체는 URL객체를 만들거나 URL의 일부분에 액세스하거나 기존의 URL을 수정할 때 사용할 수 있다. |
history 객체 | 한 윈도우 안에서 액세스된 URL의 히스토리를 유지할 때 사용 |
frame 객체, frames 배열 | HTML 프레임에 액세스할 때 사용 frames 배열은 윈도우안에 있는 모든 프레임에 액세스할 때 사용 |
link 객체, links 배열 | 하이퍼텍스트 링크의 텍스트 기반이나 이미지 기반 소스 앵커(anchor)에 액세스할 때 사용 links배열은 문서 안에 있는 모든 link 객체에 액세스할 때 사용한다. I.E.는 link 객체의 anchor객체를 결합한다. |
anchor 객체, anchors 배열 | 하이퍼텍스트 링크의 타켓에 액세스할 때 사용 anchors 배열은 문서 안에 있는 모든 anchor 객체에 액세스할 때 사용 |
image객체, images 배열 | HTML 문서에 삽입되어 있는 이미지에 액세스할 때 사용 images 배열은 문서 안에 있는 모든 image 객체에 액세스할 때 사용 |
area 객체 | 클라이언트측 이미지맵 안에 있는 영역에 액세스할 때 사용 |
applet 객체, applets 배열 | Java 애플릿에 액세스할 때 사용 애플릿 배열은 문서 안에 있는 모든 애플릿에 액세스할 때 사용 |
event 객체, Event 객체 | 이벤트 발생에 대한 정보에 액세스할 때 사용 event 객체는 특정 이벤트에 대한 정보 제공 Event 객체는 이벤트를 식별하는 데 사용하는 상수 제공 |
form 객체, forms 배열 | HTML 폼에 액세스시 사용 forms 배열은 문서 안에 있는 모든 폼에 액세스시 사용 |
element 객체 | 폼 안에 들어있는 모든 폼 요소에 액세스시 사용 |
text 객체 | 폼의 텍스트 필드에 액세스시 사용 |
textarea 객체 | 폼의 텍스트 영역 필드에 액세스시 사용 |
radio 객체 | 폼의 라디오 버튼 세트에 액세스하거나 세트 안에 있는 각각의 버튼에 액세스할 때 사용 |
checkbox 객체 | 폼의 체크 박스에 액세스할 때 사용 |
button 객체 | Submit나 Reset 버튼이 아닌 폼 버튼에 액세스시 사용 |
reset 객체 | 폼의 Reset 버튼에 액세스시 사용 |
selet 객체 | 폼의 선택 리스트에 액세스시 사용 |
option 객체 | option 객체는 선택 리스트의 요소에 액세스시 사용 |
password 객체 | 폼의 패스워드 필드에 액세스시 사용 |
hidden 객체 | 폼의 숨겨진 필드에 액세스시 사용 |
FileUpload 객체 | 폼의 파일 업로드 요소에 액세스시 사용 |
navigator 객체 | 스크립트를 실행하고 있는 브라우저에 대한 정보에 액세스시 사용 |
screen 객체 | 사용자의 화면의 색상 깊이와 크기에 대한 정보에 액세스시 사용 |
embed 객체, embeds 배열 | 삽입된 객체에 액세스시 사용 embeds 배열은 문서 안에 삽입된 모든 객체에 대한 액세스 제공 |
mimeType 객체, mimeTypes 배열 | 브라우저가 제공하는 특징 MIME 유형에 대한 정보에 액세스시 사용 mimeTypes 배열은 제공하는 모든 mimeType 객체의 배열 I.E.는 빈 배열을 리턴하면서 mimeTypes에 대해서 임시적으로 지원 |
plugin 객체, plugins 배열 | 특정 브라우저 플러그인에 대한 정보에 액세스시 사용 plugins 배열은 브라우저가 지원하는 모든 플러그인의 배열 I.E.는 빈 배열을 리턴하면서 plugins에 대해서 임시적으로 지원 |
프로퍼티 | 설 명 |
---|---|
closed | 윈도우가 닫혀 있는지 식별 |
defaultStatus | 브라우저 윈도우의 하단의 상태바에 나타나는 디폴트 상대 메시지를 지정 |
document | 윈도우에 표시되어 있는 현재 문서를 지정하는 객체 |
frames | 윈도우 객체에 들어 있는 모든 프레임 객체로 구성된 배열 |
history | 마지막으로 윈도우로 로드된 URL의 리스트를 포함하는 윈도우의 히스토리 객체 |
length | window에 들어 있는 프레임의 수 식별 |
location | window 객체와 관련된 URL을 지정하는 객체 |
name | 윈도우의 이름 지정 |
offscreenBuffering | 윈도우 정보의 오프스크린 버퍼링이 사용될 것인지를 지정하는 부울값 오프스크린 버퍼링은 윈도우를 나타내기 전에 윈도우의 모든 요소를 로드할 때 사용 |
opener | 윈도우를 만들거나 열 수 있도록 해주는 window 객체 지정 |
parent | 특정 윈도우를 포함하는 윈도우를 지정하는 시너님 |
self | 참조될 현재 윈도우를 지정하는 시너님 |
status | 브라우저 윈도의 하단의 상태 표시줄에 나타날 임시 메시지를 지정 |
top | 중첩된 일련의 윈도우에서 맨 위에 있는 브라우저 윈도우를 의미하는 시너님 |
window | 참조될 현재 윈도우를 식별하는 시너님 |
메 소 드 | 설 명 |
---|---|
alert(text) | 경고 다이얼로그 박스를 표시 |
blur() | 포커스를 윈도우에서 옮긴다 |
setInterval(expression,milliseconds) | 지정된 타임아웃 인터벌이 지난 이후에 표현식을 반복해서 평가하거나 함수를 불러온다. |
clearInterval(interval) | 이전에 설정된 인터벌 타이머를 클리어 |
setTimeout(expression,milliseconds) | 타임아웃 기간이 지난 이후에 표현식을 평가하거나 함수를 호출한다. |
clearTimeout(timer) | 이전에 설정된 타임아웃을 클리어 |
close() | 지정된 윈도우를 닫는다. |
confirm(text) | 확인 다이얼로그 박스를 나타낸다. |
focus() | 윈도우로 포커스를 가져간다. |
open(url,name,[options]) | 새로운 윈도우를 열고 새로운 window 객체를 만듬 |
prompt(text,defaultInput) | 프롬프트 다이얼로그 박스를 나타낸다. |
scroll(x,y) | 윈도우를 특정 위치까지 스크롤한다. |
옵 션 | 값 | 설 명 |
---|---|---|
toolbar | yes no | 윈도우에 툴바 제공 |
location | yes no | 윈도우에 위치 필드 제공 |
directories | yes no | 디렉토리 버튼 제공 |
status | yes no | 상태 표시줄 제공 |
menubar | yes no | 메뉴바 제공 |
scrollbars | yes no | 스크롤 바 제공 |
resizable | yes no | 윈도우 크기 조절 가능 |
width | 정수 | 윈도우의 폭(픽셀) |
height | 정수 | 윈도우의 높이(픽셀) |
프로퍼티 | 설 명 |
---|---|
alinkColor | <BODY> 태그의 alink 속성의 값 지정 |
anchor | 문서에 들어 있는 배열을 참조하는 객체 |
anchors | 문서에 들어 있는 모든 앵커의 배열 |
applet | 문서에 들어 있는 애플릿을 참조하는 객체 |
applets | 문서에 들어 있는 모든 애플릿의 배열 |
area | 문서 안의 이미지맵 영역을 참조하는 객체 |
bgColor | <BODY> 태그의 bgColor 속성의 값 식별 |
cookie | 쿠키의 값 식별 |
domain | 문서가 로드되는 서버의 도메인 이름 식별 |
embeds | 문서안의 모든 플러그인의 배열 |
fgColor | <BODY> 태그의 text 속성값 지정 |
form | 문서 안의 폼을 참조하는 객체 |
Forms[] | 문서 안의 모든 폼의 배열 |
image | 문서 안의 이미지를 참조하는 객체 |
Images[] | 문서 안의 모든 이미지의 배열 |
lastModified | 문서가 마지막으로 수정된 날짜 |
link | 문서 안의 링크를 참조하는 객체 |
links | 문서 안의 모든 링크의 배열 |
linkColor | <BODY> 태그의 link 속성의 값 식별 |
plugin | 문서 안의 플러그인을 참조하는 객체 |
plugins[] | 브라우저가 지원하는 플러그인을 나타내는 객체의 배열 |
referrer | 문서에 대한 링크를 제공하는 문서의 URL |
title | 문서의 타이틀 |
URL | 문서의 URL |
vlinkColor | <BODY> 태그의 vlink 속성의 값 식별 |
메 소 드 | 설 명 |
---|---|
close() | 문서의 객체를 만드는 데 사용된 스트림 |
open([mimeType][,"replace"]) | 선택적인 MIME 유형으로 문서 객체를 만들 때 사용되는 흐름을 개시한다. "replace" 파라미터는 text/html MIME 유형과 함께 사용되어 히스토리 리스트에 있는 현재 문서를 대체 |
write(expr1[,expr2...,exprN]) | 문서에 표현식의 값을 기록 |
write(expr1[,expr2...,exprN]) | 개행 문자가 다음에 따라오는 문서에 표현식의 값 기록 |
프로퍼티 | 브라우저 지원 | 설 명 |
---|---|---|
appCodeName | N2, I.E3 | 브라우저 색상 이름 |
AppMinorVersion | I.E4 | 브라우저 버전 번호 |
appName | N2, I.E3 | 브라우저 이름 |
appVersion | N2, I.E3 | 브라우저의 버전 |
browserLanguage | I.E4 | 브라우저에 설정되어 있는 언어 |
connectionSpeed | I.E4 | 브라우저가 네트워크에 연결되는 속도 |
cookieEnabled | I.E4 | 브라우저가 쿠키를 허용하도록 설정되어 있는지의 여부 |
cpuClass | I.E4 | 브라우저 실행시 사용되는 마이크로프로세서의 유형 |
onLine | I.E4 | 브라우저가 현재 온라인 연결을 가지고 있는지 여부 |
Language | N4, I.E4 | 브라우저에 설정되어 있는 언어 |
mimeTypes | N3, I.E4 | 현재 브라우저가 지원하는 모든 MIME 유형의 배열 |
platform | N4, I.E4 | 브라우저가 실행되는 운영체제 플랫폼 |
plugins | N3, I.E4 | 현재 브라우저에 설치된 모든 플러그인의 배열 |
systemLanguage | I.E4 | 운영체제의 디폴트 언어 |
userAgent | N2, I.E3 | 브라우저에서 서버로 전송된 HTTP 프로토콜의 사용자 에이전트 헤더 |
userLanguage | I.E4 | 사용자가 사용하는 언어 |
userProfile | I.E4 | 사용자 프로파일 정보에 대한 액세스를 제공하는 객체 |
메 소 드 | 설 명 |
---|---|
javaEnabled() | 사용자가 브라우저의 Java 기능을 켜두었는지의 여부를 나타내는 부울값 리턴 |
taintEnabled() | 사용자가 data tainting(보안 메커니즘)을 활성화했는지 여부를 나타내는 부울값 리턴 |
preference | 서명이 되지 않은 스크립트가 보안 관련 프로퍼티를 얻고 설정할 때 사용 |
프로퍼티 | 브라우저 | 설 명 |
---|---|---|
data | N | DragDrop 이벤트로 인해 드롭된 객체의 URL이 들어있는 스트링 배열 |
height, width | N | 윈도우나 프레인의 길이와 너비(픽셀표시) |
pageX, pageY | N | 픽셀로 나타낸 커서의 수평/수직 위치(페이지에서의 상대적위치) |
screenX, screenY | N, I.E | 픽셀로 나타낸 커서의 수평/수직 위치(화면에서의 상대적 위치) |
layerX, layerY | N | 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 레이어에 대한 상대적 위치. Resize 이벤트와 함께 사용하면 layerX와 layerY가 이벤트가 타겟으로 하는 객체의 길이와 너비 지정 |
clientX와 clientY | I.E | 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 웹페이지에서의 상대적 위치 |
offsetX, offsetY | I.E | 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 컨테이너에 대한 상대적 위치 |
X, Y | I.E | 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 문서에 대한 상대적 위치 |
target | N | 이벤트가 전송된 원래 객체 |
srcElement | I.E | 이벤트가 전송된 원래 객체 |
type | N, I.E | 발생한 이벤트 유형 |
which | N | 눌려진 마우스 버튼(왼:1, 가:2, 오:3)이나 눌려진 키의 ASCII값 |
keyCode | I.E | 키 누름과 연관된 Unicode 키 코드를 식별 |
button | I.E | 이벤트가 발생했을 때 눌려진 마우스 버튼 식별(0:눌려진버튼없음, 1:왼, 2:오, 4:가) |
modifiers | N | 마우스나 키 이벤트와 연관된 수정자 키(ALT_MASK,CONTROL_MASK,SHIFT_MASK,META_MASK)를 식별 |
altkey,ctrlkey,shiftkey | I.E | true나 false로 설정하여 이벤트가 발생했을 때 Alt키와 Control키, Shift 키 중에 어떤 것이 눌려졌는지 알려준다. |
cancelBubble | I.E | true나 false로 설정하여 이벤트 버블링을 취소하거나 활성화한다. |
fromElement, toElement | I.E | 이동 중인 HTML 요소 지정 |
reason | I.E | 데이터 소스 객체에 대한 데이터 전송 상태를 나타내는데 사용 |
returnValue | I.E | true나 false로 설정하여 이벤트 핸들러의 리턴값을 나타낸다. 이벤트 핸들러에서 true나 false를 리턴하는 것과 같다. |
srcFilter | I.E | onfilterchange 이벤트를 시작하는 filter객체 지정 |
프로퍼티 | 설 명 |
---|---|
action | <FORM> 태그의 HTML action 속성에 대한 액세스 제공 |
button | GUI 컨트롤 버튼을 나타내는 객체 |
checkbox | 체크 박스 필드를 나타내는 객체 |
elements | 폼 안에 포함되어 있는 모든 필드와 GUI 컨트롤을 포함하는 배열 |
encoding | <FORM> 태그의 HTML enctype 속성에 대한 액세스 제공 |
FileUpload | 파일 업로드 폼 필드를 나타내는 객체 |
hidden | 숨겨진 폼 필드를 나타내는 객체 |
length | elements 배열의 길이에 대한 액세스 제공 |
method | <FORM> 태그의 HTML method 속성에 대한 액세스 제공 |
name | 폼의 이름 식별 |
password | 패스워드 필드를 나타내는 객체 |
radio | 라디오 버튼 필드를 나타내는 객체 |
reset | reset 버튼을 나타내는 객체 |
select | 선택 항목 리스트를 나타내는 객체 |
submit | submit 버튼을 나타내는 객체 |
target | <FORM> 태그의 HTML target 속성에 대한 액세스 제공 |
text | 텍스트 필드를 나타내는 객체 |
textarea | 텍스트 영역 필드를 나타내는 객체 |
메 소 드 | 설 명 |
---|---|
handleEvent() | 지정된 이벤트에 대한 폼의 이벤트 핸들러를 호출할 때 사용 |
submit() | 폼을 제출시 사용 |
reset | 폼의 엔트리를 디폴트 값으로 재설정시 사용 |
객 체 | 프로퍼티 | 설 명 |
---|---|---|
button | name | 버튼의 name 속성에 대한 액세스 제공 |
type | 객체의 유형 지정 | |
value | 객체의 값 지정 | |
checkbox | checked | 체크박스가 현재 체크되어 있는지를 식별 |
defaultChecked | 체크박스가 디폴트로 체크되어 있는지 식별 | |
name | 체크박스의 HTML name 속성에 대한 액세스 제공 | |
type | 객체의 유형 식별 | |
value | 객체의 값 식별 | |
FileUpload | name | 객체의 name 속성에 대한 액세스 제공 |
type | 객체의 type 속성에 대한 액세스 제공 | |
value | 객체의 값 식별 | |
hidden | name | 객체의 name 속성에 대한 액세스 제공 |
type | 객체의 유형 식별 | |
value | 객체의 값 식별 | |
password | defaultChecked | 객체의 디폴트 값 식별 |
name | 객체의 name 속성에 대한 액세스 제공 | |
type | 객체의 유형 식별 | |
value | 객체의 값 식별 | |
radio | checked | 라디오 버튼이 체크되어 있는지 식별 |
defaultChecked | 라디오 버튼이 디폴트로 체크되어 있는지 식별 | |
name | 객체의 name 속성에 대한 액세스 제공 | |
type | 객체의 유형 식별 | |
value | 객체의 값 식별 | |
reset | name | 객체의 name 속성에 대한 액세스 제공 |
type | 객체의 유형 식별 | |
value | 객체의 값 식별 | |
select | length | 선택 리스트의 길이 식별 |
name | 객체의 name 속성에 대한 액세스 제공 | |
option | 선택 리스트가 제공하는 옵션 식별하는 배열 | |
selectedIndex | 선택 리스트 안에서 처음 선택된 옵션 식별 | |
type | 객체의 유형 식별 | |
submit | name | 객체의 name 속서에 대한 액세스 제공 |
type | 객체의 유형 식별 | |
value | 객체의 값 식별 | |
text | defaultValue | 텍스트 필드에 나타나는 디폴트 텍스트를 식별 |
name | 객체의 name 속성에 대한 액세스 제공 | |
type | 객체의 유형 식별 | |
value | 객체의 값 식별 | |
textarea | defaultValue | 텍스트 영역 필드에 나타나게 되는 디폴트 텍스트 식별 |
name | 객체의 name 속성에 대한 액세스 제공 | |
type | 객체의 유형 식별 | |
value | 객체의 값 식별 |
객 체 | 메 소 드 | 설 명 |
---|---|---|
button | Click() | 클릭된 버튼 시뮬레이트 |
blur() | 포커스 잃음 | |
focus() | 포커스 맞춤 | |
checkbox | Click() | 클릭된 체크 박스 시뮬레이트 |
blur() | 포커스 잃음 | |
focus() | 포커스 맞춤 | |
FileUpload | blur() | 포커스 잃음 |
focus() | 포커스 맞춤 | |
select() | 입력 영역을 선택 | |
hidden | 없음 | |
password | blur() | 포커스 잃음 |
focus() | 포커스 맞춤 | |
select() | 패스워드 필드에 나타나는 텍스트를 하이라이트 | |
radio | Click() | 라디오 버튼 클릭 시뮬레이트 |
blur() | 포커스 잃음 | |
focus() | 포커스 맞춤 | |
reset | Click() | 리셋 버튼 클릭 시뮬레이트 |
blur() | 포커스 잃음 | |
focus() | 포커스 맞춤 | |
select | blur() | 포커스 잃음 |
focus() | 포커스 맞춤 | |
submit | Click() | 제출 버튼 클릭 시뮬레이트 |
blur() | 포커스 잃음 | |
focus() | 포커스 맞춤 | |
text | blur() | 포커스 잃음 |
focus() | 포커스 맞춤 | |
select() | 텍스트 필드에 있는 텍스트 하이라이트 | |
textarea | blur() | 포커스 잃음 |
focus() | 포커스 맞춤 | |
select() | 텍스트 영역에 있는 텍스트 하이라이트 |
프로퍼티 | 설 명 |
---|---|
hash | URL의 앵커 부분(존재하는 경우) |
host | URL의 hostname:port 부분 |
hostname | URL의 host부분 |
href | 전체 URL |
pathname | URL의 경로명 부분 |
port | URL의 포트 부분 |
protocol | URL의 프로토콜 부분 |
search | URL의 쿼리 스트링 부분 |
프로퍼티 | 설 명 |
---|---|
hash | URL의 앵커 부분(존재하는 경우) |
host | URL의 hostname:port 부분 |
hostname | URL의 host부분 |
href | 전체 URL |
pathname | URL의 경로명 부분 |
port | URL의 포트 부분 |
protocol | URL의 프로토콜 부분 |
search | URL의 쿼리 스트링 부분 |
target | 링크의 HTML, target 속성 |
프로퍼티 | 설 명 |
---|---|
border | <:IMG> 태그의 BORDER 속성의 값 |
complete | 이미지가 완전히 로드되었는지 식별 |
height | <:IMG> 태그의 HEIGHT 속성의 값 |
hspace | <IMG> 태그의 HSPACE 속성의 값 |
lowsrc | <IMG> 태그의 LOWSRC 속성의 값 |
name | <IMG> 태그의 NAME 속성의 값 |
prototype | image 객체에 사용자 지정 프로퍼티를 추가할 때 사용 |
src | <IMG> 태그의 SRC 속성의 값 |
vspace | <IMG> 태그의 VSPACE 속성의 값 |
width | <IMG> 태그의 WIDTH 속성의 값 |
프로퍼티 | 설 명 |
---|---|
hash | area 객체의 HREF 속성의 파일 오프셋 부분 |
host | area 객체의 HREF 속성의 호스트 이름 부분 |
hostname | area 객체의 HREF 속성의 host:port 부분 |
href | area 객체의 완전한 HREF 속성 |
pathname | area 객체의 HREF 속성의 경로명 부분 |
port | area 객체의 HREF 속성의 포트 부분 |
protocol | area 객체의 HREF 속성의 프로토콜 부분 |
search | area 객체의 HREF 속성의 쿼리 스트링 부분 |
target | area 객체의 TARGET 속성 |
메 소 드 | 설 명 |
---|---|
getDate() getUTCDate() setDate() setUTCDate() |
Date 객체의 날짜를 설정하거나 리턴 |
getDay() getUTCDay() |
Date 객체의 한 주의 날짜를 설정하거나 리턴 |
getHours() getUTCHours() setHours() setUTCHours() |
Date 객체의 시간를 설정하거나 리턴 |
getMilliseconds() getUTCMilliseconds() setMilliseconds() setUTCMilliseconds() |
Date 객체의 밀리초 값을 설정하거나 리턴 |
getMinutes() getUTCMinutes() setMinutes() setUTCMinutes() |
Date 객체의 분을 설정하거나 리턴 |
getMonth() getUTCMonth() setMonth() setUTCMonth() |
Date 객체의 달을 설정하거나 리턴 |
getSeconds() getUTCSeconds() setSeconds() setUTCSeconds() |
Date 객체의 초를 설정하거나 리턴 |
getTime() getUTCTime() |
Date 객체의 시간을 설정하거나 리턴 |
getTimeZoneOffset() | Date 객체의 시간대 오프셋(분)을 리턴 |
getYear() getFullYear() getUTCFullYear() setYear() setFullYear() setUTCFullYear() |
Date 객체의 연도를 리턴하거나 설정한다. 완전한 연도를 나타내는 방법으로 4자리 연도 값을 사용한다. |
toGMTString() | 날짜를 Internet GMT(Greenwich Mean Time) 포맷의 스트링으로 변환 |
toLocaleString() | 날짜를 로케일(locale)포맷의 스트링으로 변환. 로케일 포맷이란 사용자가 위치해 있는 지형적 위치에서 일반적으로 사용하는 포맷 의미 |
toString() | Date 객체의 스트링 값을 리턴 |
valueOf() | 1970년 1월 1일 자정 이후의 밀리초 값 리턴 |
toUTCString() | UTC에서 시간을 나타내는 스트링 값을 리턴 |
생 성 자 | 설 명 |
---|---|
Date() | 현재 날짜와 시간으로 Date 인스턴스 만듬 |
Date(dateString) | dateString 파라미터에 지정되어 있는 날짜로, Date 인스턴스를 만든다. dateString의 포맷은 "월,일,연도,시:분:초" |
Date(milliseconds) | 1970년 1월 1일 자정 이후 지정된 밀리초 값으로 Date 인스턴스를 만든다. |
Date(year,month, day,hours,minutes, seconds,milliseconds) |
년,월,일,시,분,초,밀리초 정수에 따라 지정된 날짜로 Date 인스턴스를 만든다. 연도와 월 파라미터는 제공되어야 하고 다른 나머지 파라미터가 포함되면 앞에 오는 모든 파라미터가 제공되어야 한다. |
프로퍼티 | 설 명 |
---|---|
E | Euler의 상수. 이것은 계산을 하는 어디에서나 발견할 수 있으며 자연대수의 기초 |
LN2 | 2의 자연대수. 이것은 자연대수와 밑이 2인 대수 사이의 전환에 사용되는 간단한 상수 |
LN10 | 10의 자연대수. LN2와 마찬가지로 대수 변환에 사용 |
LOG2E | 밑이 2인 E의 대수. 이것은 밑이 10인 대수를 밑이 E인 대수로 변환시 사용 |
PI | 원의 원주 대 지름의 비율 |
SQRT1_2 | 1/2의 제곱근은 많은 삼각법 계산에서 사용 |
SQRT2 | 2의 제곱근은 대수식에서 흔히 사용 |
메 소 드 | 설 명 |
---|---|
abs(x) | x의 절대값 리턴 |
acos(x) | x의 아크 코사인값 라디안으로 리턴 |
asin(x) | x의 아크 사인값 라디안으로 리턴 |
atan(x) | x의 아크 탄젠트 값을 라디안으로 리턴 |
atan2(x,y) | (x,y)에 해당하는 극좌표의 각도를 리턴 |
ceil(x) | x보다 크거나 작은 최소 정수값 리턴 |
cos(x) | x의 코사인 값 리턴 |
exp(x) | eX를 리턴 |
floor(x) | x보다 작거나 같은 최대 정수값 리턴 |
log(x) | x의 자연대수 리턴 |
max(x,y) | x, y 중 큰 값 리턴 |
min(x,y) | x, y 중 작은 값 리턴 |
pow(x,y) | xy를 리턴 |
random() | 0과 1사이의 임의의 숫자 리턴 |
round(x) | x의 가장 가까운 정수로 반올림되는 값 리턴 |
sin(x) | x의 사인값 리턴 |
sqrt(x) | x의 제곱근 리턴 |
tan(x) | x의 탄젠트 값 리턴 |
메 소 드 | 설 명 |
---|---|
charAt(index) | 메소드가 적용되는 스트링의 지정된 인덱스에 있는 문자로 구성된 스트링을 리턴 |
charCodeAt(index) | 지정된 인덱스의 문자의 Unicode 인코딩 리턴 |
fromCharCode(codes) | 문자 코드의 컴마로 구분된 시퀀스에서 스트링 만듬 |
indexOf(pattern) | 스트링안에 들어있는 pattern 파라미터가 지정한 첫 번째 스트링의 인덱스 리턴, 패턴이 스트링 안에 들어있지 않으면 -1 리턴 |
indexOf(pattern,startIndex) | startIndex가 지정한 위치에서 검색을 시작하는 것을 제외하면 indexOf(pattern) 메소드와 같다. |
lastIndexOf(pattern) | 스트링에 들어 있는 pattern 파라미터가 지정한 마지막 스트링의 인덱스 리턴, 패턴이 스트링 안에 들어있지 않으면 -1 리턴 |
lastIndexOf(pattern,startIndex) | startIndex가 지정한 위치에서 검색을 시작하는 것을 제외하면 lastIndexOf(pattern)과 같다. |
splitSeparator() | 하나의 스트링을 분리자를 기반으로 하여 서브스트링의 배열로 분리 |
substring(startIndex) | startIndex에서 시작하는 스트링의 서브스트링을 리턴 |
substring(startIndex,endIndex) | startIndex에서 시작하고, endIndex에서 끝나는 스트링의 서브스트링을 리턴 |
toLowerCase() | 소문자로 변환된 스트링의 복사본 리턴 |
toString() | 객체의 스트링 값을 리턴 |
toUpperCase() | 대문자로 변환된 스트링의 복사본 리턴 |
valueOf() | 객체의 스트링 값을 리턴 |
각종 확장자 파일 모음 (0) | 2007.03.03 |
---|---|
insertAdjacentElement Method (0) | 2007.03.03 |
Flash OBJECT and EMBED tag attributes (0) | 2007.03.03 |
insertAdjacentElement Method |
Internet Development Index |
Inserts an element at the specified location.
Syntax
oElement = object.insertAdjacentElement(sWhere, oElement)
Parameters
sWhere Required. String that specifies where to insert the HTML element, using one of the following values:
beforeBegin Inserts oElement immediately before the object. afterBegin Inserts oElement after the start of the object but before all other content in the object. beforeEnd Inserts oElement immediately before the end of the object but after all other content in the object. afterEnd Inserts oElement immediately after the end of the object. oElement Required. Object that specifies the element to be inserted adjacent to the object that invoked the insertAdjacentElement method.
Return Value
Returns an element object.
Remarks
You cannot insert text while the document is loading. Wait for the onload event before attempting to call this method.
If you try to insert an object that already exists on the page, the existing object will be moved to the point that you specified in the insertAdjacentElement method; no new object will be created.
Example
This example uses the insertAdjacentElement method to add a new list item to an ol object.
Hide Example
<SCRIPT> function fnAdd() { var oNewItem = document.createElement("LI"); oList.children(0).insertAdjacentElement("BeforeBegin",oNewItem); oNewItem.innerText = "List Item 0"; } </SCRIPT> : <BODY> <OL ID = "oList"> <LI>List Item 1</LI> <LI>List Item 2</LI> <LI>List Item 3</LI> </OL> <INPUT TYPE = "button" VALUE = "Add Item" onclick="fnAdd()"> </BODY>
Standards Information
There is no public standard that applies to this method.
Applies To
TABLE Platform Version Win16: 5 Win32: 5 Unix: 5 Mac: 5 Windows CE: 5.5 Version data is listed when the mouse hovers over a link, or the link has focus. A, ACRONYM, ADDRESS, APPLET, AREA, B, BASE, BASEFONT, BDO, BGSOUND, BIG, BLOCKQUOTE, BODY, BR, BUTTON, CAPTION, CENTER, CITE, CODE, COL, COLGROUP, COMMENT, DD, DEL, DFN, DIR, DIV, DL, DT, EM, EMBED, FIELDSET, FONT, FORM, FRAME, FRAMESET, HEAD, hn, HR, HTML, I, IFRAME, IMG, INPUT type=button, INPUT type=checkbox, INPUT type=file, INPUT type=hidden, INPUT type=image, INPUT type=password, INPUT type=radio, INPUT type=reset, INPUT type=submit, INPUT type=text, INS, KBD, LABEL, LEGEND, LI, LINK, LISTING, MAP, MARQUEE, MENU, nextID, OBJECT, OL, OPTION, P, PLAINTEXT, PRE, Q, S, SAMP, SCRIPT, SELECT, SMALL, SPAN, STRIKE, STRONG, SUB, SUP, TABLE, TBODY, TD, TEXTAREA, TFOOT, TH, THEAD, TITLE, TR, TT, U, UL, VAR, XMP Move the mouse pointer over an element in the Applies To list to display availability information for the listed platforms.
자바스크립트 강좌, 사용법, 객체, 이벤트 등 (0) | 2007.03.03 |
---|---|
Flash OBJECT and EMBED tag attributes (0) | 2007.03.03 |
보기좋은 코딩원칙1-80칸의 원칙 (0) | 2007.03.03 |
This document lists the required and optional attributes of the OBJECT and EMBED tags used to publish Flash movies.
For specific usage information for these attributes, refer to sections of the Using Flash manual devoted to using OBJECT and EMBED tags (exact headings vary among Flash versions). Information is also available in Macromedia Flash OBJECT and EMBED tag syntax (TechNote 4150).
For more information on scripting with Flash see Scripting with Flash.
Note: Values in italics indicate that the developer chooses the value.
Last updated: | May 29, 2003 |
---|---|
Easy Link this TechNote |
http://www.macromedia.com/cfusion/knowledgebase/index.cfm?id=tn_12701
insertAdjacentElement Method (0) | 2007.03.03 |
---|---|
보기좋은 코딩원칙1-80칸의 원칙 (0) | 2007.03.03 |
CSS Properties To JavaScript Reference Conversion (0) | 2007.03.03 |
if(variable1 == variable2 && variable3 == variable4 && variable5 == variable6 && variable7 == variable8 && variable9 == variable10)
{
do_somthing();
}
일단 횡스크롤바가 생겨서 코드가 한눈에 안들어오고 if안에 뭐가 들어있나 찾아내기가 쉽지 않다. 같은코드를 아래처럼 수정했다.if(variable1 == variable2 &&
variable3 == variable4 &&
variable5 == variable6 &&
variable7 == variable8 &&
variable9 == variable10)
{
do_somthing();
}
라인이 조금 길어지긴했지만 우선 스크롤바가 없어져 코드가 한눈에 들어오고 if안에 것들이 열맞춰 정렬이 되어 있기때문에 한눈에 비교대상이 눈에 들어오고 쉬프트+방향키를 통해 에디팅하기도 편하다.Flash OBJECT and EMBED tag attributes (0) | 2007.03.03 |
---|---|
CSS Properties To JavaScript Reference Conversion (0) | 2007.03.03 |
asp 속도업 (0) | 2007.03.01 |
각종 Viewer (0) | 2007.04.10 |
---|---|
Foxit Reader (0) | 2007.04.07 |
[FreeMind V0.8.0]생각을 정리하는 마인드맵 (0) | 2007.02.11 |
CSS Property | JavaScript Reference |
---|---|
background | background |
background-attachment | backgroundAttachment |
background-color | backgroundColor |
background-image | backgroundImage |
background-position | backgroundPosition |
background-repeat | backgroundRepeat |
border | border |
border-bottom | borderBottom |
border-bottom-color | borderBottomColor |
border-bottom-style | borderBottomStyle |
border-bottom-width | borderBottomWidth |
border-color | borderColor |
border-left | borderLeft |
border-left-color | borderLeftColor |
border-left-style | borderLeftStyle |
border-left-width | borderLeftWidth |
border-right | borderRight |
border-right-color | borderRightColor |
border-right-style | borderRightStyle |
border-right-width | borderRightWidth |
border-style | borderStyle |
border-top | borderTop |
border-top-color | borderTopColor |
border-top-style | borderTopStyle |
border-top-width | borderTopWidth |
border-width | borderWidth |
clear | clear |
clip | clip |
color | color |
cursor | cursor |
display | display |
filter | filter |
font | font |
font-family | fontFamily |
font-size | fontSize |
font-variant | fontVariant |
font-weight | fontWeight |
height | height |
left | left |
letter-spacing | letterSpacing |
line-height | lineHeight |
list-style | listStyle |
list-style-image | listStyleImage |
list-style-position | listStylePosition |
list-style-type | listStyleType |
margin | margin |
margin-bottom | marginBottom |
margin-left | marginLeft |
margin-right | marginRight |
margin-top | marginTop |
overflow | overflow |
padding | padding |
padding-bottom | paddingBottom |
padding-left | paddingLeft |
padding-right | paddingRight |
padding-top | paddingTop |
page-break-after | pageBreakAfter |
page-break-before | pageBreakBefore |
position | position |
float | styleFloat |
text-align | textAlign |
text-decoration | textDecoration |
text-decoration: blink | textDecorationBlink |
text-decoration: line-through | textDecorationLineThrough |
text-decoration: none | textDecorationNone |
text-decoration: overline | textDecorationOverline |
text-decoration: underline | textDecorationUnderline |
text-indent | textIndent |
text-transform | textTransform |
top | top |
vertical-align | verticalAlign |
visibility | visibility |
width | width |
z-index | zIndex |
document.all.div_id.style.JS_property_reference = "new_CSS_property_value";
document.div_id.JS_property_reference = "new_CSS_property_value";
document.getElementById(div_id).style.JS_property_reference = "new_CSS_property_value";
Note the use of parentheses instead of square brackets in newer Mozilla's "getElementById()" reference.
보기좋은 코딩원칙1-80칸의 원칙 (0) | 2007.03.03 |
---|---|
asp 속도업 (0) | 2007.03.01 |
asp기본함수 (0) | 2007.03.01 |
CSS Properties To JavaScript Reference Conversion (0) | 2007.03.03 |
---|---|
asp기본함수 (0) | 2007.03.01 |
ASP에서 join과 split을 이용한 문자열 파싱(parsing) (0) | 2007.03.01 |
내 장 함 수 |
설 명 |
Abs(수) |
절대값 구하기 |
Array(배열1,배열2,.....) |
배열 반환 |
Asc(문자열) |
문자의 ANSI 문자값 반환 |
Atn(수) |
주어진 수를 아크탄젠트로 반환 |
CBool(식) |
주어진 식을 Boolean(True 또는 False)형식으로 반환 |
Cbyte(식) |
주어진 식을 Byte( 0~255 )형식으로 반환 |
CCur(식) |
주어진 식을 Currency(통화:-922,337,203,685,477.5808~ |
CDate(날짜식) |
주어진 식을 Date(날짜)형식으로 반환 |
CDbl(식) |
주어진 식을 |
Chr(ANSI문자코드) |
ANSI 문자코드를 일반문자로 반환 |
CInt(식) |
주어진 식을 Interger(정수:-32,768~32,767)형식으로 반환 |
CLng(식) |
주어진 식을 Long(-2,147,483,648~2,147,483,647)형식 반환 |
Cos(수) |
주어진 수의 코사인 값을 반환 |
CreateObject(클래스) |
다른 객체에 대한 참조를 만들어 반환 |
CStr(식) |
주어진 식을 String(가변 길이 문자열의 경우 0개에서 |
Date() |
현재 날짜를 반환 |
DateSerial(년,월,일) |
주어진 년,월,일의 Date(100년 1월 1일부터~9999년 12월 31일 |
Exp(수) |
주어진 수의 자연로그(e)를 반환 |
Filter(검색문자열의1차원배열,검색문자열) |
지정한 필터로 문자열 배열 반환 |
Fix(수) |
주어진 수의 정수 반환 |
FormatCurrency(수) |
컴퓨터 규정의 통화값 반환 |
FormatDateTime(날짜) |
규정된 날짜와 시간으로 반환 |
FormatNumber(수) |
규정된 숫자로 반환 |
FormatPercent(수) |
규정된 퍼센트값을 반환 |
Hex(수) |
주어진 수를 16진수 문자로 반환 |
Hour(시간) |
0과 23사이의 시간으로 반환 |
Inputbox(프롬프트) |
입력대화상자의 프롬프트를 생성 |
InStr(문자열,찾을문자열) |
주어진 문자의 위치값을 반환 |
InStrRev(문자열,찾을문자열) |
주어진 문자열의 위치값을 끝에서 부터 검색하여 반환 |
Int(수) |
주어진 수의 정수값만 반환 |
IsArray(변수) |
주어진 변수 배열여부를 Boolean값으로 반환 |
IsDate(식) |
주어진 식이 날짜로 변환되는지를 Boolean값으로 반환 |
IsEmpty(식) |
주어진 식의 변수가 초기화됐는지를 Boolean값으로 반환 |
IsNull(식) |
주어진 식의 데이타 유효성을 Boolean값으로 반환 |
IsNumberic(식) |
주어진 식의 값이 숫자화 될지 여부를 Boolean값으로 반환 |
IsObject(식) |
자동화 객체를 참조하는지의 여부를 Boolean값으로 반환 |
Join(목록) |
배열에 포함된 여러 문자열을 결합하여 만든 문자열을 반환, |
LBound(배열이름) |
주어진 배열에서 사용할 수 있는 가장 작은 첨자를 반환 |
LCase(문자) |
주어진 문자를 소문자로 반환 |
Left(문자열,수) |
주어진 문자열을 주어진 수만큼 문자를 반환 |
Len(문자열) |
주어진 문자열의 문자갯수를 반환 |
LoadPicture(그림파일명) |
그림 객체를 반환 |
Log(자연로그) |
주어진 수의 자연로그를 반환 |
LTime(문자열) |
주어진 문자열의 앞에 공백을 삭제하고 반환 |
Mid(문자열,시작) |
주어진 문자열에서 주어진 위치에서부터의 문자를 반환 |
Minute(시간) |
시간에서 분값을 반환 |
Month(날짜) |
달의 값을 반환 |
MonthName(달) |
주어진 달의 수를 문자열로 반환 |
MsgBox(프롬프트) |
대화상자의 메세지를 생성 |
Now() |
현재 날짜와 시간을 반환 |
Oct(수) |
주어진 수의 8진수 값을 반환 |
Replace(문자열,찾을문자열,바꿀문자열) |
주어진 문자열의 주어진 문자를 바꾸어 반환 |
Right(문자열,수) |
주어진 문자를 주어진 수만큼 오른쪽에서부터 반환 |
Rnd() |
난수를 반환 |
Round(수) |
주어진 수의 반올림 반환 |
RTrim(문자열) |
주어진 문자열의 뒤 공백이 없는 문자을 반환 |
ScriptEngine() |
사용 중인 스크립트 언어를 반환 |
ScriptEngineBuildVersion() |
사용 중인 스크립트 언어의 버젼 수를 반환 |
ScriptEngineMajorVersion() |
사용 중인 스크립트 언어의 주 버전 수를 반환 |
ScriptEngineMinorVersion() |
사용 중인 스크립트 언어의 보조버전 수를 반환 |
Second() |
시스템 시간의 초 값을 반환 |
Sgn(수) |
주어진 수의 부호를 나타내는 정수를 반환 |
Sin(수) |
주어진 수의 사인값을 반환 |
Space(수) |
주어진 수만큼의 공백이포함된 문자열을 반환 |
Split(문자열) |
주어진 문자열이 포함된 1차 배열을 반환. |
Sqr(수) |
주어진 수의 제곱근을 반환 |
StrComp(문자열,문자열) |
주어진 두 개의 문자열을 비교하여 결과값을 반환 |
StrReverse(문자열) |
주어진 문자열을 뒤에서 부터 읽어서 반환 |
String(수,문자열) |
주어진 문자가 주어진 수만큼 반복된 문자열을 반환 |
Tan(수) |
주어진 각도의 탄젠트 값을 반환 |
Time() |
현재 시간을 반환 |
TimeSerial(시,분,초) |
주어진 시간의 시간,분,초에 대한 시간값을 반환 |
TimeValue(시간) |
시간이 포함된 Date형식을 반환 |
Trim(문자열) |
주어진 문자열의 앞,뒤 공백이 없는 문자열 반환 |
TypeName(변수명) |
변수의 정보를 나타내는 문자열 반환 |
UBound(배열명) |
배열의 차원에서 가장 큰 첨자를 반환 |
UCase(문자열) |
주어진 문자열을 대문자로 반환 |
varType(변수명) |
변수의 형식을 나타내는 값을 반환 |
Weekday(날짜) |
요일을 나타내는 정수를 반환 |
WeekdayName(요일) |
요일을 나타내는 문자를 반환 |
Year(1970표기날짜) |
현재의 연도를 반환 |
asp 속도업 (0) | 2007.03.01 |
---|---|
ASP에서 join과 split을 이용한 문자열 파싱(parsing) (0) | 2007.03.01 |
전월세계약 6가지 포인트 (0) | 2007.02.28 |
join과 split는 문자열을 파싱(parsing)함에 있어 매우 유용한 함수들이다. 같단히 설명하자면, join은 하나의 일차원 배열의 내용을 하나의 문자열로 만드는 함수이고, split은 하나의 문자열 내용을 하나의 일차원 배열로 나누어 담는 함수이다.
join에 대한 문법은 다음과 같다:
join(list[, delimiter])
여기서 list는 문자열로 연결시킬 내용들이 들어 있는 배열을 나타낸다. Delimeter는 배열에 있는 요소들로부터 문자열을 만들 때 각 요소 사이에 들어갈 문자열을 의미한다. 이 값은 옵션으로 이것을 지정하지 않으면 내부적으로 빈 문자열(" ")로 처리된다. 이제 간단한 예를 한 번 살펴 보도록 하자.
Dim OneDimArray(5)
OneDimArray(0) = "Hello,"
OneDimArray(1) = "my"
OneDimArray(2) = "name"
OneDimArray(3) = "is"
OneDimArray(4) = "Daniel!"
Dim strSentence
strSentence = join(OneDimArray)
위의 코드는 strSentence에 "Hello, my name is Daniel!"을 저장하게 된다. 만일 strSentence = join(OneDimArray) 부분을 strSentence = join(OneDimArray, ",") 부분으로 변경하면 strSentence에는 "Hello,,my,name,is,Daniel!"이 저장된다. 즉, 디리미터(delimeter, 구분자)는 앞의 경우 디폴트인 " " 이고, 후자의 경우는 ","인 것이다. 만일 배열의 각 요소를 하나의 문자열로 만들 때 각 요소 사이의 구분자가 없이 붙이고 싶을 경우는 단순히 strSentence = join(OneDimArray, "")라고 해주면 된다. 그 결과는 "Hello,mynameisDaniel!"이 될 것이다.
split은 join의 반대 결과를 만든다. split은 문자열을 취하여 문자열의 각 요소들을 적절한 기준으로 잘라 내 일차원 배열로 담아낸다. split의 문법은 다음과 같다:
split(String Expression[, delimiter[, count[, compare]]])
여기서 반드시 필요한 파라미터는 배열로 담을 문자열, Expression이다. Delimeter는 join과 마찬가지로 옵션이다. 디폴트는 " " 이다. count는 결과로 반환할 부분 문자열의 갯수이다. compare는 부분 문자열을 비교하는 방법을 결정한다. 이제 간단한 예를 한 번 살펴 보도록 하자.
Dim strSentence
strSentence = "Hello, my name is Daniel!"
Dim OneDimArray
OneDimArray = split(strSentence)
위의 코드는 strSentence에 담겨 있는 문자열을 OneDimArray란 일차원 배열의 각 요소에 "Hello,", "my", "name", "is", "Daniel!"을 저장한다. 만일 OneDimArray 배열에 3 요소만 저장하고 싶은 경우 count 파라미터를 이용하여 부분 문자열의 갯수를 정해주면 된다. 즉, OneDimArray = split(strSentence) 부분을 OneDimArray = split(strSentence, " ", 3)으로 변경시켜주면 된다. 이 결과는 "Hello,", "my", "name is Daniel!"이 된다. 만일 구분자로 컴마(,)를 사용하고 싶다면 OneDimArray = split(strSentence) 부분을 OneDimArray = split(strSentence, ",")로 변경시켜주면 된다. 이 결과는 "Hello", "my name is Daniel!"이 될 것이다.
앞에서도 언급했지만 join과 split은 서로 반대 관계이다. 예를 들어, 다음과 같은 코드를 보자.
Dim strSentence, strCopy
strSentence = "Hello, my name is Bob!"
strCopy = join(split(strSentence))
위의 코드에서 strCopy와 strSentence는 동일한 값을 갖는다.
지금까지 join과 split의 사용 방법에 대해 알아 보았다. 그렇다면 이 함수들은 언제 유용하게 사용될 수 있을까? 사실 ASP에서 문자열을 조작함에 있어 join과 split의 사용은 필수적이다. 하나의 예를 들기 위해 지난 시간에 살펴보았던 "AdRotator를 이용하여 배너 광고 로테이션 시키는 방법"에서 사용한 AdRotator.txt 파일을 살펴 보도록 하자. 그 파일에는 다음과 같은 형식의 데이터들이 저장되어 있다:
Advertiser Name
Advertiser URL
Advertiser Category
Banner ID
Comment
*
Advertiser Name
Advertiser URL
Advertiser Category
Banner ID
Comment
*
Advertiser Name
Advertiser URL
Advertiser Category
Banner ID
Comment
*
...
이런 텍스트 파일을 이용하여 작업을 할 때 제일 먼저 하는 일은 FileSystemObject 객체를 이용하여 전체 텍스트 내용을 하나의 문자열로 읽어 들이는 것이다. 그 문자열을 str이란 변수로 담았다고 한다면 다음으로 할 일은 recArray = split(str, "*")을 해주는 것이다.
이렇게 함으로써 하나의 레코드 단위를 배열의 각 요소로 저장할 수가 있다. 마지막으로 레코드에 있는 각각의 요소를 얻으려면 elementArray = split(recArray(i), chr(13))이라고 해주면 된다. 여기서 chr(13)은 라인이 분리되어 있는 값을 의미한다.
이런 과정을 거침으로써 텍스트 파일의 내용을 적절히 파싱(parsing)을 할 수 있게 된다.
asp기본함수 (0) | 2007.03.01 |
---|---|
전월세계약 6가지 포인트 (0) | 2007.02.28 |
정규식 (0) | 2007.02.27 |
1. 집주인에게 먼저 연락하지 말
주택임대차보호법은 집주인이 계약 만기 한달 전까지 통보하지 않으면 기존 계약과 같은 조건으로 계약이 2년 연장된 것으로 간주한다. 따라서 계약 만기가 다가왔다고 해서 세입자가 집주인에게 먼저 연락할 필요는 전혀 없다. 계약을 연장할 것인지, 계약 조건을 바꿀 것인지는 어디까지나 집주인이 먼저 의사를 통보하는 게 순서다.
2. 인상액을 월세로 돌릴 때는
현행법상 2년의 전·월세 계약이 끝나 집주인들이 전·월세금을 대폭 인상하거나 집을 비워달라고 요구할 때 세입자가 대항할 방법은 없다. 전세금을 올려 줄 목돈이 없는 경우에는 인상되는 전세금을 월세로 돌려 내는 쪽으로 집주인과 합의하는 것이 하나의 방법이다. 이때 전환이율은 해당 지역의 월세 시세로 하는 게 원칙이다. 최근 전세금을 월세로 돌릴 때 적용되는 이율은 서울, 수도권의 경우 월 1%(연 12%) 수준이다. 전세금이 2천만원이면 월세는 20만원이 된다.
3. 임차권 등기명령 활용해야
이사하기로 했는데 전셋집이 빠지지 않아 보증금을 돌려받지 못하는 경우가 있을 수 있다. 이처럼 집주인이 계약 만기 후 보증금을 돌려주지 않을 경우에는 보증금 반환청구 소송을 제기하고 확정 판결을 받은 뒤 경매를 통해 보증금을 회수할 수밖에 없다. 다만 소송에 6개월 정도의 기간이 소요되고 경매절차도 6개월이 걸리는 점을 유의해야 한다. 이 경우 보증금을 돌려받지 못한 채 불가피하게 이사를 해야 할 경우가 생길 수 있다. 이때 주민등록을 옮기면 경매에서 우선순위를 확보할 권리인 ‘대항력’을 상실하기 때문에 주의해야 한다. 이런 경우에는 관할 법원에 임차권 등기명령 신청을 해 등기된 것을 확인한 뒤 주민등록을 옮겨야 대항력을 인정받는다.
4. 집주인 바뀌었어도 종전 계약은 유효
전세계약 기간 중 집주인이 바뀌어도 집을 비워줄 필요는 없다. 또 새 주인이 전세금을 올려달라고 할 때도 세입자는 이전 집주인과 계약한 내용을 바꾸는 계약을 맺을 의무가 없다. 다만, 전셋값이 주변 시세와 크게 차이가 나면 새 집주인이 보증금의 5% 범위에서 올려달라고 요구할 수는 있다. 이 경우라도 계약일로부터 1년이 경과해야 가능하다.
5. 계약 해지하고 이사가려면
세입자가 계약 기간이 남은 상태에서 임대차 계약을 해지할 때는 집 주인과 합의해야만 가능하다. 세입자가 개인 사정을 들어 일방적으로 계약을 해지할 수 없으며, 집주인은 계약기간 만료일까지는 보증금을 돌려줄 의무가 없다. 따라서 집주인에게 사정을 설명하고 다른 세입자를 구해 보증금을 받는다는 조건으로 서로 합의하는 게 현실적이다. 이 경우 중개수수료 등 이사 비용은 세입자가 부담해야 한다.
6. 보증금 못 받았을땐 임차권 등기명령 활용
건설교통부는 세입자들의 주거 안정을 위해 지난달 전·월세 지원센터(1577-3399)를 경기 수원시 국민임대주택 홍보관에 설치했다. 전·월세 계약과 관련해 궁금한 사항이 있으면 도움을 받을 수 있다.
ASP에서 join과 split을 이용한 문자열 파싱(parsing) (0) | 2007.03.01 |
---|---|
정규식 (0) | 2007.02.27 |
용량계산기 (0) | 2007.02.25 |
전월세계약 6가지 포인트 (0) | 2007.02.28 |
---|---|
용량계산기 (0) | 2007.02.25 |
JavaScript 키워드 정리 (0) | 2007.02.24 |
정규식 (0) | 2007.02.27 |
---|---|
JavaScript 키워드 정리 (0) | 2007.02.24 |
JavaScript 모음 (0) | 2007.02.23 |
용량계산기 (0) | 2007.02.25 |
---|---|
JavaScript 모음 (0) | 2007.02.23 |
[팁] .NET 로딩페이지 구현하기 (0) | 2007.02.23 |