http://apache.tt.co.kr/
http://apache.mirror.cdnetworks.com/
http://mirror.apache-kr.org/
http://ftp.kaist.ac.kr/pub/Apache/
'분류 전체보기'에 해당되는 글 2491건
- 2008.08.12 Table 줄바꿈
- 2008.08.12 [css] 인쇄를 위한 스타일
- 2008.08.12 CSS & JAVASCRIPT 최적화 도구
- 2008.08.12 사용자 생성 및 계정 관리
- 2008.08.12 자바스크립트 그래프
- 2008.08.12 오른쪽 마우스 메뉴에 도스창 열기 추가하기
- 2008.08.12 Network Monitor(네트워크상의 트래픽보기)
- 2008.08.12 아파치 2.X 버전에서 mod_cband를 이용한 트래픽관리
- 2008.08.12 간단한 핸드폰게임 hex에디트 2
- 2008.08.12 효과적인 PE 파일 분석 도구 "PEiD" v0.94
- 2008.08.12 내컴에 깔려있는 프로그램 검색
- 2008.08.12 초간단 패킷 프로그램
- 2008.08.12 이더리얼 패킷분석
- 2008.08.12 패킷 분석 툴 ie 7 가능
- 2008.08.12 GWT(Google Web Toolkit)의 장점과 단점
- 2008.08.12 Google Web Toolkit
- 2008.08.12 개발자가 놓치기 쉬운 자바 의 기본원리
- 2008.08.12 Google Doctype
- 2008.08.12 java 초보개발자를 위한 학습 로드맵
- 2008.08.12 파일 검색 및 총 라인수 구하기
- 2008.08.08 Apache Download Mirrors
- 2008.08.08 Anyframe 등장 기사
- 2008.08.08 자바스크립트 튜토리얼 정리 끝
- 2008.08.08 anyframe의 등장
- 2008.08.08 web 2.0 싸이트 정리
- 2008.08.08 홈페이지에서 홈페이지를 찍는다.(썸네일이미지만들기)
- 2008.08.07 textarea의 글자수와 라인수 제한
- 2008.08.07 자주 쓰이는 JavaScript
- 2008.08.07 자주쓰는 javascript StringUtil ver 1.0
- 2008.08.07 자바스크립트 자주쓰는 펑션들..
1. 소스
<html>
<head>
<title>Bizest 체험관 - KIS</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<link rel="alternate" type="application/rss+xml" href="/rss/" title="RSS feed for Bizest KIS"/>
<link rel="stylesheet" type="text/css" href="/skin/x4/css/blue.css" />
<link rel="stylesheet" type="text/css" href="/skin/x4/css/layout.css" />
<link rel="stylesheet" type="text/css" href="/skin/x4/css/form.css" />
<link rel="stylesheet" type="text/css" href="/skin/x4/css/form.css" />
<link rel="stylesheet" media="print" type="text/css" href="/skin/x4/css/print.css" />
print.css
body {
/*
font-family:"Times New Roman", serif;
font-size:12pt;
*/
background:none;
margin-left: 20px;
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
}
#container {
width:100%;
}
#container_head {
DISPLAY: none;
}
#container_body .left {
DISPLAY: none;
}
#container_body {
width:100%;
}
#container_body .right {
width:100%;
}
#container_footer {
DISPLAY: none;
}
출처 : http://www.ihelpers.co.kr/programming/tipntech.php?CMD=view&TYPE=0&KEY=&SC=S&&CC=&PAGE=1&IDX=639
- JS Minifier
- JSMin
- JSLint : JavaScript Verifier
- Javascript compressor : JavaScript 압축 도구
- CSS & JavaScript Compressor : CSS & JavaScript 압축 도구
- ShrinkSafe : JavaScript 압축 도구
- Huffman JavaScript Compression
- SOC (Safe Obfuscator/Compressor)
- ANT 프로젝트 구축으로 로컬에서 자유자제로 JavaScript 압축 : 여기
- CSS OPTIMIZER : CSS파일의 사이즈를 압출해주는 툴
- CSS compressor : CSS 압축기
- ROBSON CSS COMPRESSOR : CSS 압축도구
- CSS DRIVE CSS COMPRESSOR : CSS 압축도구
- CSS Compressor from Lottery Post : CSS 압축기
- FLUMPCAKES CSS OPTIMIZER : CSS파일을 최적화 도구
- CSS ANALYZER : URL방식으로 CSS를 Validation
- CSS TIDY : open source 기반의 CSS parser와 optimizer
- 온라인으로도 최적화 사이트
- CLEAN CSS : CSS를 formatting하고 optimizing하는 온라인 도구
- CSSCHECK : URL기반으로 CSS파일을 기입하면 코드에 대한 피드백을 리포팅합니다. Warning과 에러 정보를 제공합니다.
- Code Beautifier (Based on CSS Tidy)
- CSS Optimizer : 다운로드 클라이언트를 사용하여 CSS를 최적화함
출처 : http://www.mimul.com/pebble/default/2008/01/29/1201616760000.html
사용자 생성 및 계정 관리
1. 계정 조회
현재 시스템에 로그인된 사용자 계정을 조회 / 사용자 계정에 대한 정보를 확인
cat –n /etc/passwd
root : x : o : o : root : /root : /bin/bash
1 2 3 4 5 6 7
1 : 사용자명
2 : 패스워드 (/etc/shadow 파일에 암호화되어 있음)
3 : 사용자 계정 uid
4 : 사용자 계정 gid
5 : 사용자 계정 이름 정보
6 : 사용자 계정 홈 디렉토리
7 : 사용자 계정 로그인 셀
cat –n /etc/shadow
root : #$%!234^x13 : 11535 : o : 99999 : 7 : : : :
1 2 3 4 5 6 7 8 9
1 : 사용자명
2 : 패스워드
3 : 패스워드 파일 최종 수정일
4 : 패스워드 변경 최소일
5 : 패스워드 변경 최대일
6 : 패스워드 만료 경고 기간
7 : 패스워드 파기 기간 (패스워드 파기 후 계정 비활성 기간)
8 : 계정 만료 기간
9 : 예약 필드
2. 계정 생성 및 암호 설정
useradd 생성할 계정명
passwd 생성한 계정명
useradd [옵션] 로그인 계정
-c comment : 사용자 이름 또는 정보
-d home_directory : 사용자 계정 홈 디렉토리
-e expire_date : 사용자 계정 유효 기간
-f inactive_time : 비활성 기간
-g initial_group : 기본 그룹
-G grout : 다음 그룹
-s shell : 기본 로그인 셀
-u uid : 사용자 계정 uid
3. 계정 변경
usermod [옵션] 로그인 계정
-c comment : 사용자 이름 또는 정보
-d home_directory : 사용자 계정 홈 디렉토리
-e expire_date : 사용자 계정 유효 기간
-f inactive_time : 비활성 기간
-g initial_group : 기본 그룹
-G grout : 다음 그룹
-s shell : 기본 로그인 셀
-u uid : 사용자 계정 uid
usermod –d /home/user –m user
usermod –e 2003-04-05 user
usermod –f 3 user
usermod –g users user
4. 계정 삭제
userdel –r 계정 (-r : 해당 계정자의 홈디렉토리까지 한 번에 삭제)
5. 그룹조회
cat –n /etc/group
6. 그룹생성
groupadd [-g GID [-o]] 그룹 id (-o : GID 499이하 값으로 지정)
[-r] 그룹 id 499이하 값으로 자동 지정
[-f] 강제로 생성
groupadd –g 900 toheart (900 – groupid / toheart – 그룹명)
7. 그룹변경
groupmod [-g gid [-o]] gid변경
[-n] 새로운 그룹명으로 변경
groupmod –g 700 toheart
groupmod –n kkum toheart
8. 그룹삭제
groupdel group group 제거
출처 : http://cafe.naver.com/frody.cafe?iframe_url=/BoardRead.do%3Farticleid=11
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> obxGetColor, obxStickGraph</title>
<meta http-equiv="content-type" content="text/html; charset=euc-kr" />
<script>
IE=(window.showModalDialog) ? true : false;
function obxGetColor(color,gap) {
var rtn='',col,tmp;
for(var x=0;x <6; x+=2) {
col=parseInt(color.substr(x,2),16)+gap;
if (col > 255) col = 255;
else if (col < 0) col=0;
if(col < 10) rtn+='0'+col.toString(16);
else rtn+=col.toString(16);
}
return rtn;
}
function obxStickGraph(dsize) {
this.step=3;
this.speed=10;
this.total=0;
this.max=0;
this.dsize=dsize;
this.statictext=false;
this.item= new Object();
this.add = function (id,size,color,text) {
this.total += size;
this.max=Math.max(this.max,size);
this.item[id]= {'size' : size, 'color' : color.replace('#',''), 'text' : text}
}
this.draw = function (id,action) {
var dColor=obxGetColor(this.item[id].color,-20);
document.write("<div></div>");
//this.item[id].div=document.body.appendChild(document.createElement('div'));
var divs=document.getElementsByTagName('div');
this.item[id].div=divs[divs.length-1];
this.item[id].div.style.borderLeft="1px solid #"+dColor;
this.item[id].div.style.overflow="hidden";
this.item[id].div.style.height="11px";
if(!action) this.actDraw(id);
else this.actDraw(id,5);
}
this.getCss= function(width,height,color,bwidth,bcolor) {
if(width<1)width=1;
return "overflow:hidden;width:"+width+";height:"+height+";background-color:"+color+";border-right:"+bwidth+"px #"+bcolor+" solid";
}
this.actDraw= function(id,limit) {
var pp = this.item[id].size / this.total;
var sizep = this.item[id].size / this.max;
if(!limit) var size=this.dsize * sizep;
else size=limit;
var hit = Math.round(this.max/this.dsize*size);
var percent =(Math.round(this.max/this.dsize*size)/this.total*100).toString().match(/[0-9]*(?:\.[0-9][0-9])?/);
var text = (this.item[id].text) ? this.item[id].text.replace('#',hit).replace('$',percent) : percent + " %"
var Color=this.item[id].color;
var hColor=obxGetColor(Color,20);
var hhColor=obxGetColor(Color,30);
var dColor=obxGetColor(this.item[id].color,-20);
var add='',d;
if(IE || opera) d=new Array(3,2,1);
else d=new Array(3,4,5);
this.item[id].div.innerHTML= ''
+'<div style="'+this.getCss(size-d[0],1,hColor,1,hhColor)+'"></div>'
+'<div style="'+this.getCss(size-d[1],2,hColor,3,hhColor)+'"></div>'
+'<div style="'+this.getCss(size-d[2],2,hColor,5,hhColor)+'"></div>'
+'<div style="'+this.getCss(size-d[2],1,hhColor,5,hhColor)+'"></div>'
+'<div style="'+this.getCss(size-d[2],2,Color,5,hhColor)+'"></div>'
+'<div style="'+this.getCss(size-d[1],2,Color,3,hhColor)+'"></div>'
+'<div style="'+this.getCss(size-d[0],1,dColor,1,hhColor)+'"></div>'
+'<span style="position:relative;top:'+(-11-IE)+'px;left:'+(((this.statictext)?this.dsize*sizep:size)+5)+'px;font:7pt verdana">'+text+'</span>'
if(limit)
if(this.dsize * sizep > limit) {
obxStickGraphRunObject=this;
setTimeout('obxStickGraphRunObject.actDraw("'+id+'",'+(limit+this.step)+');',this.speed);
}else{
setTimeout('obxStickGraphRunObject.actDraw("'+id+'");',this.speed);
}
}
}
grp=new obxStickGraph(200) ;
grp.add('id1',100,'F8CF7B');
grp.add('id2',200,'#D1D3D3');
grp.add('id3',500,'FDB480','# hit ($ %)');
grp.add('id4',300,'3399ff','# hit');
</script>
<style>
td {font: 11px gulim}
</style>
</head>
<body>
<table>
<tr>
<td>
항목 1
</td>
<td width="300">
<script>grp.draw('id1',true);</script>
</td>
<td>
동적 드로우, 기본출력
</td>
</tr>
<tr>
<td>
항목 2
</td>
<td>
<script>grp.draw('id2');</script>
</td>
<td>
정적 드로우, 기본출력
</td>
</tr>
<tr>
<td>
항목 3
</td>
<td>
<script>grp.draw('id3',true);</script>
</td>
<td>
동적 드로우, "# hit" 출력
</td>
</tr>
<tr>
<td>
항목 4
</td>
<td>
<script>grp.draw('id4');</script>
</td>
<td>
정적 드로우, "# hit" 출력
</td>
</tr>
</table>
<xmp>
생성 :
<script>
grp=new obxStickGraph(200) ;
//젤 긴게 200px 만하게 grp란걸 만든다 (그래프 길이"만" 입니다, 글자 때문에 더 깁니다.)
grp.add('id1',100,'F8CF7B');
//그 grp로 명령을 내립니다.
// "id1" 아이디로 100이란 값을 넣어준다 이때 색은 F8CF7B로
//색은 조금 어두운 부분(그래프 밑부분)색입니다
grp.add('id2',200,'#D1D3D3');
grp.add('id3',500,'FDB480','# hit ($ %)');
// 4번째 인자는 출력 문잡니다. #은 값으로 $는 퍼센트값으로 바뀝니다
grp.add('id4',300,'3399ff','# hit');
</script>
출력 :
<script>
grp.draw('id1',true);
//아이디에 해당되는 그래프를 출력합니다,
//이때 두번째 인자는 옵션이고 true로 해주면 동적으로 그립니다.(비추-_-;)
</script>
동적옵션코드 :
<script>
grp.step = 3;
grp.speed = 10;
//그려주기(grp.draw()) 전에 이런 코드를 넣어주셔도 됩니다.
//동적으로 그릴때 쓰는 옵션인데
//스텝은 한번에 늘어나는 길이(픽셀)고, 스피드는 한번 돌아가는;; 속도입니다. 적을수록 빠르고 0이 최소값입니다.
+yser님의 조언
grp.statictext=true
//텍스트 표시를 정적으로 합니다.
</script>
</xmp>
</body>
</html>
00 오른쪽 마우스 메뉴에 도스창 열기 추가하기
원문 : http://kkamagui.springnote.com/pages/392898
참고 : http://zextor.tistory.com/2669790
들어가기 전에...
- 이 글은 kkamagui에 의해 작성된 글입니다.
- 마음껏 인용하시거나 사용하셔도 됩니다. 단 출처(http://kkamagui.tistory.com, http://kkamagui.springnote.com)는 밝혀 주십시오.
- 기타 사항은 kkakkunghehe at daum.net 이나 http://kkamagui.tistory.com으로 보내주시면 반영하겠습니다.
1.추가 방법
DOS 시절부터 컴퓨터를 이용하였거나 프로그래머 개발자의 경우 아직도 Dos이용하고 있습니다.
하지만 DOS를 실행하고 원하는 폴더에 접근하기 위해서는 원도우키 + R 또는 [시작]→[실행] 후 “ CMD “ 를 입력 후 도스창이 실행되면 CD 명령어를 이용하여 원하는 폴더에 이동할 수 있습니다.
레지스트리를 수정하여 탐색기를 이용하여 먼저 가고자 하는 폴더에 접근 후 DOS를 실행 하여 바로 해당 폴더의 경로로 연결되어 사용하기 편리합니다.
1. [시작]→[실행]에서 “regedit “를 입력하고 레지스트리 편집기를 실행한 후, 다음 키 값을 찾는다. HKEY_CLASSES_ROOT\Directory\shell
2. Shell 키 위에서 마우스 오른쪽 마우스 클릭(또는 shell 키 선택 후 오른쪽 공백에서 오른쪽 마우스 클릭) 후 [새로 만들기(N)] → [키]를 선택합니다.
3. 새로운 키의 이름을 DOS(이름은 원하시는 이름으로 하셔도 됩니다.)로 수정합니다.
4. 만들어진 DOS 키를 클릭 후 오른쪽의 기본값을 더블 클릭하여 오른쪽 마우스에 표시될 이름을 입력하여 주십시오. ( 예를 들어 도스창이라 입력합니다. )
5. 다음 새로 만들어진 DOS에서 Shell 과 마찬가지로 새로운 키를 만들어 Command 이름으로 수정합니다. ( DOS 와는 달리 반드시 command 이름으로 하여야 합니다. )
6. 만들어진 Command 키를 클릭 후 오른쪽의 기본값을 더블 클릭하여 cmd.exe /k cd "%1" 이라는 문자열을 입력하여 주십시오.
7. 컴퓨터를 재 시작하여 탐색기 실행 후 가고자 하는 폴더를 선택 후 오른쪽 마우스 클릭 후 도스창을 클릭하시면 해당 폴더의 경로로 도스창이 열리는 것을 확인 할 수 있습니다.
본 자료는 (주)웰비아닷컴 의 커뮤니티 - 활용팁 에서 스크랩한 것입니다.
이 자료 외에도 많은 정보가 있으니 필요하신 분은 직접 방문해 보시길 바랍니다.
본 페이지에서는 재부팅 후에 사용할 수 있다고 기술하였지만 바로 사용하고 싶으시면 아래와 같이 해주시면 됩니다.
1. '시작' 이 있는 작업표시줄에 마우스 오른쪽 버튼을 눌러 작업관리자를 띄움니다.
2. 프로세스 탭에서 explorer.exe 를 선택하여 프로세스 끝내기를 합니다. 경고가 뜰 경우 그냥 "예" 를 선택하십시오.
3. 그럼 밑에 작업표시줄이 없어질 것 입니다.
4. 그럼 아까 작업관리자의 응용 프로그램 탭으로 이동한 후 새 작업을 클릭합니다.
5. 열기 옆에 있는 입력창에 "explorer" 를 입력합니다.
6. 이제 탐색기의 오른쪽 메뉴에 DOS를 사용할 수 있습니다.
Network Monitor (Netmon)는 네트워크 프로토콜 트래픽 분석 유틸리티입니다.
Network Monitor 3.1 을 사용해서 네트워크 프로토콜을 수집하는 몇 가지 방법을 정리하였습니다.
Netmon 2.x와 3.x의 가장 큰 변화는 캡쳐 필터링이라고 생각합니다.
캡쳐 필터링 옵션 변화에 따른 패킷 수집 방법을 사례 별로 아주 기본적인 테스트를 해 봅니다.
일반적으로 Netmon 트래픽을 수집하기 위해서는 Client와 Server 측에서 함께 로그 수집을 해야
문제 해결을 위한 보다 정확한 데이터를 얻을 수 있습니다.
아래 그림은 Netmon 3.1 인터페이스입니다.
Catpure Filter 제어, Frame Summary, Frame Details, Hex Details 값을 바로 확인할 수 있습니다.
Capture Filter 에 Filter 구문을 작성한 뒤 반드시 Verify, Apply 하여 체크 및 필터를 적용해야 합니다.
[환경]
Server : 192.168.0.100
Client : 192.168.0.133
Case 1. 특정 Source IP Address(192.168.0.133) 에서 유입되는 Packet 확인
Client 에서 Server 로 터미널 서비스 접속을 시도 하였습니다.
Case 2. TCP Source Port 가 3389인 frame 확인
Client 에서 Server 로 터미널 서비스 접속을 시도 하였습니다.
Case 3. 3389 port Packet은 캡쳐하지 않음
터미널 서비스 3389 포트 커넥션을 시도 하였으나 아래 그림과 같이 캡쳐되지 않습니다.
Case 4. ARP Packet 찾기
Case 5. Source Port 1096, Destination Port 3389 과 일치하는 Packet
Case 6. Command 명령을 이용한 Packet 수집
수집이 완료되면 Ctrl + C 를 입력하여 수집을 중지합니다.
자, 수집을 하셨으니 이제 분석을 해야겠죠?
누가하죠? 어떻게?.... What?
약은 약사에게 패킷 분석은 과장님에게 ^^;
[참고자료]
Microsoft Network Monitor 3.1
http://www.microsoft.com/downloads/details.aspx?familyid=18b1d59d-f4d8-4213-8d17-2f6dde7d7aac&displaylang=en
The Basics of Reading TCP/IP Traces
http://support.microsoft.com/kb/169292/en-us
Explanation of the Three-Way Handshake via TCP/IP
http://support.microsoft.com/kb/172983/en-us
Into to Filtering with Network Monitor 3.0
http://blogs.technet.com/netmon/archive/2006/10/17/into-to-filtering-with-network-monitor-3-0.aspx
작성자 : Lai Go / 작성일자 : 2008.07.01
아파치 2.X 버전에서 mod_cband를 이용한 트래픽관리
mod_cband 이란?
Apache에서 개별홈페이지의 일hit수 제한 및 트래픽을 관리하기 위해 사용하는 모듈로서apache 2.x버전에서 사용할 수 있으며 apache를 Dos방식과 Static방식 중 어느 방식으로 설치했느냐에 따라 적재방법 또한 다릅니다. DOS방식의 mod_cband 모듈적재 및 설정 방법을 알아보도록 하겠습니다.
[주요기능]
Apache2용 가볍운 트래픽제한 모듈
* 사용자별 대역폭제한 기능
* 가상호스트별 대역폭 제한 기능
* 목적지별 대역폭 제한 기능
* 제한기능:
o 모든사용자 대역폭 제한
o 다운로드 속제 제한
o 초당요청수 제한
o 아이피대역별 제한
* Support for virtualhosts
* Support for defined users
* 제한결과 웹을 통한 확인 (/cband-status)
* 각 사용자별 제한 결과 확인(/cband-status-me)
( 1 ) 다운로드
http://freshmeat.net/redir/mod_cband/60304/url_tgz/mod-cband-0.9.7.5.tgz
http://cband.linux.pl/downloads
리눅스 쉘 명령어
① tar zxvf mod-cband-0.9.7.5.tgz 파일을 다운로드 합니다.
wget은 웹에서 자동적으로 파일을 받아오는데 사용되는 유틸리티이며 HTTP, HTTPS, FTP 프로토콜을 지원합니다.
[root@nextline bin]# wget
http://freshmeat.net/redir/mod_cband/60304/url_tgz/mod-cband-0.9.7.5.tgz
( 2 ) 압축해제
[tar 명령어 옵션]
tar 명령어는 파일을 묶거나 풀 때 사용되는 리눅스 명령어 입니다.
c : tar 파일을 생성할 때 사용합니다.(여러 개의 파일을 하나의 파일로 묶을 때)
v : 묶을 때나 풀어줄 때 파일들의 내용을 자세하게 보여줍니다.
z : gzip과 관련하여 압축이나 해제를 한꺼번에 하려고 할 때 사용합니다.
x : 주어진 이름의 파일에 대하여 추출합니다.
사용법 : tar [옵션] 파일명
리눅스 쉘 명령어
① 다운로드된 mod-cband-0.9.7.5.tgz 파일의 압축을 해제 합니다.
[root@nextline bin]# tar zxvf mod-cband-0.9.7.5.tgz
( 3 ) 컴파일
리눅스 쉘 명령어
① 압축 해제한 mod-cband-0.9.7.5 디렉토리로 이동 합니다.
[root@nextline bin]# cd mod-cband-0.9.7.5
② ./configure 명령을 실행합니다.
./configure 명령은 프로그램을 설치하기 위해 환경설정을 하는 것으로 ./configure 후Makefile파일이 생성됩니다. 모듈을 적재하기 위해 컴파일을 합니다.
[root@nextline mod_throttle-3.1.2]# ./configure
( 4 ) make
리눅스 쉘 명령어
① make 명령을 실행합니다.
make 명령은 대상 디렉토리의 Makefile이라는 이름을 가지고 있는 파일을 보고, 거기에 설정되어 있는 컴파일 명령을 shell을 통해서 실행하는 명령입니다. ./configure 작업에 의해 생성된 Makefile을 참조하게 되며 소스코드를 실제로 컴파일해서 bibary 파일을 생성합니다.
[root@nextline mod_throttle-3.1.2]# make
( 5 ) make install
① make install 명령을 실행합니다.
make 명령에 의해 생성된 binary 파일을 지정된 디렉토리로 이동시켜주며 실제 프로 그램 설치 작업이 이루어집니다.
[root@nextline mod_throttle-3.1.2]# make install
( 6 ) mod_cband.so 파일생성 확인
① ls 명령어를 이용하여 아파치 모듈들이 위치한 modules 디렉토리에 mod_cband.so 파일이 생성 되었는지 확인합니다.
[root@nextline mod-cband-0.9.7.5]# ls /usr/local/apache/modules/
( 7 ) 모듈적재 확인
[vi 에디터 사용법]
사용형식 : vi [옵션] [생성할 파일명/편집할 파일명]
vi 에디터는 입력모드, 명령모드, 실행모드로 구분됩니다.
입력모드 : vi 편집화면에서 문자를 입력할 수 있는 모드로서 입력모드로 진입하기 위해서는 i, a, o, I, A, O, R등이 있습니다. 즉 초기 vi 편집기 모드는 명령어 모드로 진입을 하기때문에 문자를 입력하기 전에 앞의 단축키중 하나를 먼저 입력해야 원하는 문자를 입력할 수 있습니다.
명령모드 : 커서이동/문자삭제/문자(열)교체/문자열검색 등을 할수 있는 모드로서 입력모드에서 편집이 완료되면 Esc키를 눌러 명령모드로 진입하면 됩니다.
실행모드 : 특별한 명령어를 실행하는 모드로서 명령어모드에서 ":"(콜론)를 누르면 vi 화면 하단 좌측에 vi 특수명령어를 입력할 수 있습니다.
실행모드의 일반적으로 쓰이는 특수 명령어
q : 수정 작업이 이루어지지 않은 상태에서 vi 편집기에서 빠져나옵니다.
q! : 수정 작업이 이루어진 부분을 적용시키지 않고 vi 편집기를 강제로 빠져나옵니다.
w : 수정된 작업을 저장합니다.
wq : 수정된 작업을 저장하고 vi 편집기에서 빠져나옵니다.
초기 명령어모드 -> 입력모드진입 -> 편집 -> 명령어모드 -> 실행모드 -> 종료
① httpd.conf파일에 모듈이 등록되었는지 확인합니다.
[root@nextline mod-cband-0.9.7.5]# vi /usr/local/apache/conf/httpd.conf
LoadModule cband_module libexec/mod_cband.so
( 8 ) httpd.conf파일의 메인 환경설정
메인 설정 부분은 가상호스트에도 공통으로 적용되는 설정으로 mod_cband 모듈을 적용시키기 위해 아파치 환경 설정파일인 httpd.conf을 수정합니다.
① vi 에디터를 이용하여 httpd.conf파일을 엽니다.
[root@nextline mod-cband-0.9.7.5]# vi /usr/local/apache/conf/httpd.conf
② 아파치에 cband 모듈을 적용시키기 위해 다음 라인을 추가 합니다.
<IfModule mod_cband.c>
<Location /cband-status>
SetHandler cband-status
</Location>
<Location /cband-status-me>
SetHandler cband-status-me
</Location>
<Location /~*/cband-status-me>
SetHandler cband-status-me
</Location>
<Location /cband-status>
Order deny,allow
Deny from all
Allow from all
</Location>
</IfModule>
③ 트래픽 관리자모드 접근 ip설정
<Location /cband-status>
Order deny,allow
Deny from all
Allow from all
</Location>
위 설정은 throttle로 분석된 일hit 및 일 트래픽 제한에 대하여 상황페이지를 볼 관리자페이지에 대한 접속제한 설정입니다. 즉 관리자PC 한곳에서만 분석된 결과페이지를 볼 수 있도록 하려면 아래와 같이 수정합니다.
관리자 PC 아이피 : XXX.XXX.XXX.XXX
<Location /cband-status>
Order deny,allow
Deny from all
Allow from XXX.XXX.XXX.XXX
</Location>
( 9 ) 가상호스트 환경설정
개별 홈페이지 트래픽 현황 및 관리를 하기 위해서는 httpd.conf <Virtual Hosts>부분에 홈페이지 별로 설정을 하여야 합니다.
nextline.co.kr 도메인에 하루에 300M(300*1024*1024byte)의트래픽을 제공하는 설정입니다. bit로 따지면, 2.4Gbit/일 트래픽을 제공하는 것입니다. 만약 하루에 300M를 초과했다면, 503 에러 페이지가 뜨게 됩니다.
① nextline.co.kr 도메인을 가진 가상호스트를 추가 하도록 하겠습니다.
<VirtualHost xxx.xxx.xxx.xxx>
DocumentRoot /home/nextline/public_html
Servername nextline.co.kr
ServerAlias www.nextline.co.kr
CBandLimit 300Mi
CBandPeriod 1D
</VirtualHost>
② httpd.conf 설정 후 적용시키기 위해 apache를 재 시작 시켜 줍니다.
[root@nextline mod-cband-0.9.7.5]# /usr/local/apache/bin/apachectl restart
( 10 ) 서버전체 cband 상황보기 (관리자모드)
일hit수 일전송량의 제한을 웹브라우즈로 확인하기 위하여 다음과 같은 URL로 확인하도록 하겠습니다. 먼저 서버전체의 제한사항을 관리자가 확인하기 위한 예입니다.
cband 페이지는 기본 15초마다 리플레쉬 합니다.
① 주도메인이 nextline.co.kr로 설정된 예입니다.
확인하는 방법 :http://IP주소/cband-status
② 개별사이트 cband 상황보기 (사용자모드)
확인하는 방법 : http://nextline.co.kr/cband-status-me
( 11 )지시자 및 단위설명
단위
전송속도 단위
kbps, Mbps, Gbps - bits per second:1024, 1024*1024 , 1024*1024*1024 bps
kb/s, Mb/s, Gb/s - bytes persecond: 1024, 1024*1024, 1024*1024*1024 b/s
기본 : kbps
트래픽 쿼터 단위
K, M, G - bytes: 1000, 1000*1000,1000*1000*1000 bytes
Ki, Mi, Gi - bytes: 1024, 1024*1024,1024*1024*1024 bytes
기본 : K
시간(기간) 단위
S, M, H, D, W - 초, 분, 시간, 일, 주
기본 : S
지시자들
이름 : CBandDefaultExceededURL
설명 : 제한을 초과했을때보여줄 URL (지정하지 않으면, 503 에러 페이지)
문맥 : Serverconfig
문법 :CBandDefaultExceededURL URL
이름 : CBandDefaultExceededCode
설명 : 제한을 초과했을시 보여줄 에러코드
문맥 : Server config
문법 :CBandDefaultExceededCode HTTP_CODE
예제 :CBandDefaultExceededCode 509
이름 : CBandScoreFlushPeriod
설명 : scoreboard 파일에기록할 요청수, mod_cband 의 성능에 영향을 준다.
기본값 : 1
문맥 : Server config
문법 :CBandScoreFlushPeriod 요청수
예제 :CBandScoreFlushPeriod 100 (매 100번의 요청에 한번씩 scoreboard 파일에 기록)
이름 : CBandSpeed
설명 : 가상호스트 도메인의 최대 속도,요청수, 접속수 설정
문맥 :<Virtualhost>
문법 : CBandSpeed kbpsrps max_conn
kbps - 초당 최대 전송속도
rps - 초당 최대 요청수
max_conn - 최대 동시 접속수
예제 : CBandSpeed 102410 30
최대 1024kbps전송속도로 제한, 초당 10개의 요청 처리, 동시 접속을 30개로 제한.
이름 : CBandRemoteSpeed
설명 : 접속자(IP)의 최대속도, 요청수, 접속수 제한 (접속자당 설정)
문맥 :<Virtualhost>
문법 : CBandRemoteSpeedkbps rps max_conn
kbps - 초당 최대 전송속도
rps - 초당최대 요청수
max_conn - 최대 동시 접속수
예제 : CBandRemoteSpeed20kb/s 3 3
접속자(ip)에대해 최대 20kb/s , 초당 3개의 요청, 동시 접속 3개로 제한.
이름 : CBandClassRemoteSpeed
설명 : 정의한 class(ip 범위)에대해 최대속도, 요청수, 접속수 제한
문맥 :<Virtualhost>
문법 :CBandClassRemoteSpeed class_name kbps rps
class_name - 이미 정의한 클래스 이름 (IP범위)
kbps - 초당 최대 전송속도
rps - 초당 최대 요청수
max_conn - 최대 동시 접속수
예제 : <CBandClassgooglebot_class>
CBandClassDst 66.249.64/24
CBandClassDst 66.249.65/24
CBandClassDst 66.249.79/24
</CBandClass>
CBandClassRemoteSpeedgooglebot_class 20kb/s 2 3
위에서 정의한클래스(googlebot_class)의 요청에는 20kb/s 의 전송속도,
초당 3개의 요청, 동시 접속 3개로 제한.
이름 : CBandRandomPulse
설명 : 속도 제한을 위해서 임의의파형을 생성한 다음 처리하는 mod_cband의 처리 방법이다. 부하가 많을 때는 자동 Off된다.
문맥 : Global
문법 : CBandRandomPulseOn/Off
이름 : CBandLimit
설명 : 제한할 전송량을 설정한다.(기간은 CBandPeriod 에서 설정)
문맥 :<Virtualhost>
문법 : CBandLimit limit
limit - 전송량, 사용단위: K (kilo), M (mega), G (giga), Ki (kibi), Mi (mebi),Gi (gibi)
예제 : CBandLimit 10M
전송양을 10M(10*1000*1000bytes)로 제한한다.
CBandLimit 10Mi
전송양을 10M(10*1024*1024bytes)로 제한한다.
이름 : CBandClassLimit
설명 : 정의한 class(ip범위)에대해 제한할 전송량 설정.
문맥 :<Virtualhost>
문법 : CBandClassLimitclass_name limit
class_name - 이미 정의한 클래스 이름(ip범위)
limit - 전송량, 사용단위: K (kilo), M (mega), G (giga), Ki (kibi), Mi (mebi),Gi (gibi)
이름 : CBandExceededURL
설명 : 제한을 초과했을시 보여줄URL, 지정하지 않으면 503 에러 발생
문맥 :<Virtualhost>
문법 : CBandExceededURLURL
이름 : CBandExceededSpeed
설명 : 전송양을 초과했을시 , 전송속도제한 설정.
문맥 :<Virtualhost>
문법 :CBandExceededSpeed kbps rps max_conn
kbps - 초당 최대 전송속도
rps - 초당 최대 요청수
max_conn - 최대 동시 접속수
이름 : CBandScoreboard
설명 : 가상호스트의 scoreboard파일 지정. (성능향상을 위해 필요)
문맥 :<Virtualhost>
문법 : CBandScoreboardpath
(path는 아파치(nobody또는 apache)권한으로 쓰기 가능해야 함)
이름 : CBandPeriod
설명 : 용량제한기간(이 기간이 지나면,측정되었던 용량은 지워진다.)
문맥 :<Virtualhost>
문법 : CBandPeriod period
period - 사용단위: S (초), M (분), H (시간), D (일), W (주)
예제 : CBandPeriod1W (1주일)
CBandPeriod 14D (14일)
CBandPeriod 60M (60분)
이름 : CBandPeriodSlice
설명 : 기간이 길때는 나눌 기간을명시한다.
기본값 : slice_len = limit
문맥 :<Virtualhost>
문법 : CBandPeriodSliceslice_length
예제 : CBandLimit 100G
CBandPeriod 4W
CBandPeriodSlice 1W
4주는 1주일 단위로 나뉜다(4W/1W = 4). 용량은 100G/4=25G
1주에 25G, 2주째 50G 이렇게 나눠 처리 된다.
이름 : <CBandUser>
설명 : 새로운 cband 가상 사용자설정
문맥 : Server config
문법 : <CBandUseruser_name>
이름 : CBandUserSpeed
설명 : cband 가상 사용자의 속도,요청수, 동시 접속수 제한
문맥 : <CBandUser>
문법 : CBandUserSpeedkbps rps max_conn
kbps - 초당 최대 전송속도
rps - 초당 최대 요청수
max_conn - 최대 동시 접속수
예제 : CBandUserSpeed100kb/s 10 5
이름 : CBandUserLimit
설명 : cband 가상 사용자의 저송용량 제한.
문맥 : <CBandUser>
문법 : CBandUserLimitlimit
limit - 사용용량, 사용단위: K (kilo), M (mega), G (giga), Ki (kibi), Mi (mebi),Gi (gibi)
예제 : CBandUserLimit 10M
CBandUserLimit 10Mi
이름 : CBandUserClassLimit
설명 : cband 가상 사용자의 정의한class(ip범위)에 대해 제한할 전송량 설정
문맥 : <CBandUser>
문법 :CBandUserClassLimit class_name limit
class_name - 지정한 class(IP범위)이름
limit -사용용량, 사용단위: K (kilo), M (mega), G (giga), Ki (kibi), Mi (mebi),Gi (gibi)
이름 : CBandUserExceededURL
설명 : cband 가상 사용자의,제한을 초과했을시 보여줄 URL,
지정하지 않으면 503 에러 발생 ( 가상호스트에서 )
문맥 : <CBandUser>
문법 :CBandUserExceededURL URL
이름 : CBandUserExceededSpeed
설명 : cband 가상 사용자의,전송양을 초과했을시 , 전송속도 제한 설정.
문맥 : <CBandUser>
문법 : CBandUserExceededSpeed kbps rps max_conn
kbps - 초당 최대 전송속도
rps - 초당 최대 요청수
max_conn - 최대 동시 접속수
이름 : CBandUserScoreboard
설명 : cband 가상 사용자의,scoreboard 파일 지정.
문맥 : <CBandUser>
문법 : CBandUserScoreboard path
(path는 아파치(nobody또는 apache)권한으로 쓰기가능해야 함)
이름 : CBandUserPeriod
설명 : cband 가상 사용자의, 용량제한기간(기간이 지나면, 측정되었던 용량은 지워진다.)
문맥 : <CBandUser>
문법 : CBandUserPeriodperiod
period - 사용단위: S (초), M (분), H (시간), D (일), W (주)
예제 : CBandUserPeriod 1W
CBandUserPeriod 14D
CBandUserPeriod 60M
이름 : CBandUserPeriodSlice
설명 : cband 가상 사용자의,기간을 나눌 기간 명시
기본값 : slice_len = limit
문맥 : <CBandUser>
문법 :CBandUserPeriodSlice slice_length
예제 : CBandUserLimit100G
CBandUserPeriod 4W
CBandUserPeriodSlice 1W
4주는 1주일 단위로 나뉜다(4W/1W = 4). 용량은 100G/4=25G
1주에 25G, 2주째 50G 이렇게 나눠 처리 된다.
( 12 ) 개별홈페이지 cband 정책 적용 예
① 자료실 속도제한
nextline.net 도메인에 대해서 속도를 1024kbps로 제한하며, 초당 10번의 연결, 동
시 접속자를 30으로 제한하는 예제입니다.
<VirtualHost xxx.xxx.xxx.xxx>
DocumentRoot /home/nextline1/public_html
Servername nextline.net
ServerAlias www.nextline.net
CBandSpeed 1024 10 30
CBandRemoteSpeed 20kb/s 3 30
</VirtualHost>
확인하는 방법 : http://nextline.net/cband-status-me
② 사용자 일트래픽 제공 및 초과시 연결수 제한 nextline.com 도메인에 대해 하루에 100Mbyte의 트레픽을 제공하며, 100M를 초가했다면, 속도를 128bps로 제한, 초당 5번의 연결, 동시접속자를 15로 제한하는 예제입니다.
<VirtualHost xxx.xxx.xxx.xxx>
DocumentRoot /home/nextline2/public_html
Servername nextline.com
ServerAlias www.nextline.com
CBandLimit 100Mi
CBandExceededSpeed 128 5 15
CBandPeriod 1D
</VirtualHost>
확인하는 방법 : http://nextline.com/cband-status-me
( 13 ) 그 외 적용 예를 들어보겠습니다.
① 한 사용자에 여러 도메인을 운영할 때 입니다.
위 설정은 nextline이라는 가상 사용자를 지%E
준비물:
utra edit - 에디터 프로그램입니다. hex에디트까지 가능하게 해줍니다.
qpst - 꼭 qpst가 아니여도 좋습니다. 핸드폰에 파일을 다운로드, 업로드만 가능하게 해주면 됩니다.
공학계산기 - 윈도우의 계산기나 손에 들고 있는 계산기면 OK. 윈도우의 계산기일경우 보기->공학용 을 찾아서 클릭해주시면 됩니다.
1. 이론
hex란 무엇인가?
hex란 hexagonal 의 단축형으로써 16진법이라는 뜻입니다. 우리들이 흔히 쓰는 10진수는 decimal, 2진수는 binary, 8진수는 octal 이라고 표시합니다. 간단하게 축약해서 16진수-hex, 10진수-dec, 2진수는 bin, 8진수는 oct 입니다.10진수는 0부터 9까지 가 1의 자리를 나타내며, 9에서 1이 더해지는순간 십의 자리에는 1이 일의 자리에는 0이 오는 10이 됩니다. 2진수는 0과 1 뿐입니다. 1에서 1이 더해지는순간 십의 자리에 1이 오고 일의 자리에 0이 와서 10이 됩니다. 즉 0(0), 1(1), 10(2) 입니다. 괄호안은 10진수로 읽었을때입니다. 8진수도 0부터 8까지로 이루어져있습니다. 마지막으로 16진수는 0부터 F까지 이루어져 있습니다. 이는 0,1,2,3,4,5,6,7,8,9,A(10),B(11),C(12),D(13),E(14),F(15)로 이루어져 있는 것입니다. 즉 9라는 숫자에서 1이 더해져도 십의 자리에 1이 오지않고 A가 됩니다. 이후로 B, C, D, E, F로 넘어가서 F에서 1이 더해지는순간 십의 자리에 1이 오고 일의 자리에 0이 와서 10이라는 숫자가 됩니다. 컴퓨터에 데이터가 저장될때에는 2진수와 16진수로 저장이 됩니다. 우리가 2진수는 123라는 숫자를 입력하게 되면 1111011이라는 숫자로 저장이됩니다. 16진수의 경우에는 7B라는 숫자로 저장이 됩니다. 하지만 2진수는 컴퓨터가 빠르게 이해는 할지몰라도 사람이 보고 읽고 이해하기엔(이를 가독성이라고 합니다) 너무 어렵죠. 그때문에 16진수코드를 쓰게 되는겁니다.
게임에서 hex조작은 어떻게 하나?
파일을 hex코드로 열어서 해당관련 숫자를 찾아서 숫자를 바꾸어주시면됩니다. 엉뚱한 코드를 손을 대셨다가 게임이 엉망이 되는 경우도 많으니 조심하셔야합니다. 이제 실습에 들어가보겠습니다.
일단 QPST로 접속을 합니다. 그리고 원하는 게임폴더로 찾아갑니다. 저의 경우에는 제일 만만한 판타지포에버2를 예로 들겠습니다. (참고로 저는 SKT통신사며 쓰이는 핸드폰은 MS500입니다.)
게임이 저장된 forever0.db 파일을 다운받습니다.
만약 ultra edit가 hex로 열지 못한다면 편집->hex기능을 찾아서 클릭해주시면 됩니다.
그리고 게임에 접속해서 케릭터의 골드, 레벨, 경험치, 스킬포인트, 찍은 스킬 등등을 공책이나 컴퓨터의 메모장에다가 잘 적어둡니다.
저의 경우 골드가 15032216골드 입니다. 약 1500만골드군요. 이미 이전에 손을 써두었기에 저런 골드가 가능해졌습니다.
자 15032216이라는 숫자를 계산기에 입력을 합니다. 그리고 이상태로 Hex를 클릭해보세요.
E55F98이라는 숫자로 바뀝니다. 앞으로 숫자는 2개씩 끊어서 보기로 합시다.
E5 5F 98 입니다. 이숫자를 잘 기억해두었다가, 아까 ultra edit로 연 forever0.db파일에서 맞는 숫자를 찾아봅니다.
아! 찾았군요! E5 5F 98 잘보입니다. 이 숫자를 FF FF FF 로 변경하시면 금액이 변경됩니다. FFFFFF라는 숫자는 10진수로 16777215입니다. 즉 약 1600만골드입니다.
이번엔 케릭터의 레벨을 찾아가봅시다. 저의 경우 케릭터의 레벨은 81입니다. 81이라는 dec숫자를 계산기로 통해서 hex로 바꾸면 51이라는 숫자가 됩니다. 이또한 찾아봅시다.
아! 또 찾았군요! 이 숫자를 FF로 바꾸시면 255레벨로 바뀝니다. 하지만 일반적인 게임들이 보통 99레벨이 끝인것을 감안해봐서 99레벨로 바꾸기로 합시다. 99라는 dec숫자를 hex로 바꾸어보면 63입니다. 아까 찾은 51이라는 숫자 대신 63을 바꾸어 적습니다.
그리고 파일을 저장해서 다시 qpst로 핸드폰으로 저장합니다.
그리고 게임을 실행해보시면??
와우!! 놀랍네요. 전부적용이 되어있습니다. 이제 레벨노가다와 골드노가다는 안해도 되겠군요.
기타 제가 찾아서 쓰고 있는 주소들은
골드:0번 b,c,d라인
레벨: 1번 - 200번 4
2번 - 240번 7
3번 - 280번 a
스킬 : 1번 - 230 0 부터 240 0 까지
2번 - 270 3 부터 280 3 까지
3번 - 2b0 6 부터 2c0 6
exp : 200 a b
240 d e
290 0 1
스킬포인트 : 240 5
280 8
2c0 b
입니다.
위에 제가 적은것을 보는방법은 간단합니다. hex코드에서 왼쪽 끝을 보시면 해당 00000000h 라는 주소들과 위에는 0부터 f까지 주소가 있습니다. 이것을 찾아서 보시면 됩니다. 예를 들어 골드의 경우 00000000h의 주소의 b,c,d라인에 있다는 소리입니다.
이것으로 간단한 hex조작을 해보았습니다. 여러분들도 쉽게 하실수 있기를 기대하겠습니다. 만약 내용이 어렵다면 댓글을 주시면 빠르게 확인해서 답을 드리겠습니다
PE 파일이 어떤 컴파일러로 컴파일되었고,어떤 패킹 되었는지 알수있게 하는 프로그램입니다.
본 프로그램은 사용에 아무런 제한이 없는 프리웨어입니다.
EXE, DLL, SFX 등의 PE 파일을 분석해서 사용한 압축기, 암호화기, 컴파일러 정보를 표시하는 프로그램입니다. PE 파일 내의 470 개 이상의 서로 다른 기호들을 감지할 수 있습니다.
파일분석, 어셈블링, 디어셈블링 등을 하는 분들께 필요합니다.
본 프로그램은 사용에 아무런 제한이 없는 프리웨어입니다.
사용자PC에 설치되어 있는 프로그램에 대한 정보를 제공하고 사용자에게 설치된 프로그램의 용도 및 삭제 방법등을
제공합니다.
앞으로 더욱 더 양질의 리뷰를 제공할 예정입니다.
시작프로그램 관리기능
애니그레이를 통해서 사용자컴퓨터의 시작프로그램관리에 등제된 프로그램을 삭제 또는 관리하실수 있습니다.
사용자의 시작프로그램에 설치되어 있는 프로그램에 대해 애니그레이에 의뢰함으로서 시작프로그램에 등제된 프로그램에 대한 정보를 얻으실수 있습니다.
현재 실행중인 프로세스가 종료가 안될경우 애니그레이를 통해서 종료하실수 있습니다.
사용자가 애니그레이를 사용한 흔적을 히스토리를 통해서 확인하실수 있습니다.
애니그레이를 사용하기위한 기본지식을 얻으실수 있습니다
백신치료프로그램과는 개념이 다르며, 잘모르고 무턱대고 삭제되는 프로그램이나 사용자를 불편하게 하는 프로그램에 대한 정보를 제공하여, 사용자 스스로가 판단하고 삭제 또는 예방을 하도록 유도하는 프로그램입니다.
최소한 사용자PC의 레지스터리나 기타 시스템관련 파일을 거의 건드리지 않으며, 프로그램자체가 사용자가 편안하게 사용할수 있는 프로그램입니다.
앞으로 더욱더 연구하여 100% 프리웨어인만큼 사용자에게 유익한 프로그램이 되도록 연구개발하겠습니다.
다운로드 받은 파일을 실행하여 순서에 따라 설치 하시면 됩니다.
| |
|
- Java를 이용해 Rich Ajax 애플리케이션을 제작할 수 있는 오픈 소스 프레임워크.
- JavaScript/HTML 코드를 자동으로 생성해 냄.
- 모든 종류의 브라우저를 지원함.
- Pure JavaScript/DHTML at the client side.
- Pure Java at the server side.
2. GWT를 써야 하는 이유?
- No need to learn/use JavaScript language -> Leverage existing Java skills.
- No need to handle browser incompatibilities -> GWT handles them for you.
- No need to learn/use DOM APIs -> Use pure Java APIs.
- No need to handle forward/backward buttons -> GWT handles this for you.
- No need to build commonly used widgets -> GWT provides most of them.
3. GWT의 단점
- Java 1.4 버전까지만 지원.
- GWT로 자동 생성된 HTML과 JavaScript 코드는 꽤 무거움.
- Hosted 모드에서는 실행 속도가 느림.
- 다양한 Widget을 제공하지 않음.
- 동기식(Synchronization) RPC(Remote Procedure Call)를 지원하지 않음.
- Modal 대화창 개발에는 적합하지 않음.
- 클라이언트는 client 폴더의 하위 폴더에만 접근할 수 있음.
- 쓸만한 무료 UI 디자이너 툴을 제공하지 않음.
- 한글 처리 문제.
* 출처
- http://www.ibm.com/developerworks/kr/library/os-ad-gwt1/index.html
- http://www.ibm.com/developerworks/kr/library/os-ad-gwt2/index.html
- http://www.ibm.com/developerworks/kr/library/os-ad-gwt3/index.html
- http://www.devbg.org/seminars/seminar-GWT-26-september-2007/AJAX-Applications-with-Google-Web-Toolkit-Nakov-v1.0.pdf
- http://blog.dev.daewoobrenic.co.kr/tc/jcfblog/entry/Google-Web-ToolkiGWT-%EB%8B%A8%EC%A0%90-%EB%B0%8F-%EC%B0%B8%EC%A1%B0-%EB%A7%81%ED%81%AC
- http://factorystories.springnote.com/pages/1089916
- http://naucika.tistory.com/15
출처 : http://chocodonut.tistory.com/248
Google Web Toolkit, Apache Derby, Eclipse를 사용하여 Ajax 애플리케이션 구현하기, Part 1: 환상적인 프론트엔드 (한글)자바 프레임웍에서 Ajax 애플리케이션 구현을 위한 Google Web Toolkit |
난이도 : 중급 Noel Rappin, Senior Software Engineer, Motorola, Inc. 2007 년 2 월 06 일 Google Web Toolkit (GWT)은 동적 Java™Script의 생성에 혁신을 가져왔습니다. GWT를 사용하면, 개발자들은 익숙한 자바 기술을 사용하여 사용자 인터페이스(UI)와 이벤트 모델을 디자인하고 대다수의 브라우저에 익숙한 코드를 만드는 일을 하게 됩니다. 이 글을 통해, GWT의 기초를 설명하고, GWT에서 Asynchronous JavaScript + XML (Ajax) 애플리케이션을 만드는 방법과, 자바 언어로 코드를 작성하는 방법을 설명합니다. 또한 온라인에서 피자를 판매하는 Slicr라고 하는 Web 2.0 비즈니스 샘플을 가지고, GWT 애플리케이션을 생성 및 실행하는 방법을 설명합니다. GWT를 사용하여, 전통적인 자바 GUI 인터페이스를 구현하는 것 보다 훨씬 더 쉽게, 더욱 풍부한 Ajax 브라우저 클라이언트 인터페이스를 구현할 수 있다. GWT가 매우 놀랍기는 하지만, 전체 웹 애플리케이션을 이것 하나로 만들 수는 없다. 서버에 데이터 스토어가 있어야 하고, 데이터를 자바 객체로 변환하여, GWT가 서버에서 클라이언트로 전달할 수 있도록 하는 프레임웍이 있어야 한다. 본 기술자료 시리즈에서, 100% 순수 자바 데이터베이스인 Apache Derby를 사용하는 방법을 설명한다. 이 글에서는 GWT에 대한 중점적인 설명과 더불어, GWT를 설정하는 방법과 사용자 액션에 반응하는 간단한 클라이언트 인터페이스를 구현하는 방법을 설명한다. 후속 기술자료에서는 Derby 데이터베이스를 설치하고, GWT 프론트엔드를 Derby 기반 백엔드에 연결하는 방법을 설명한다. 마지막으로, 개발 환경 밖에서 시스템을 전개하는 방법도 배운다.
GWT를 사용하여, 자바 프로그래밍 언어로 Ajax 애플리케이션을 개발할 수 있다. Ajax 애플리케이션의 장점은 전통적인 UI 애플리케이션과 연결되는 풍부한 인터랙티브 환경일 것이다. 그림 1은 샘플 GWT 인터페이스로서 데스크탑 이메일 애플리케이션이다. 이 데모는 GWT 웹 사이트에서 볼 수 있다. 그림 1. GWT 이메일 데모 GWT의 가장 고유한 기능은 Ajax 애플리케이션을 만들 수 있고, 자바 언어로 코드를 작성할 수 있다는 점이다. 선호하는 자바 통합 개발 환경(IDE)을 사용하여, 클라이언트를 디버깅 할 수도 있다. 자바 객체를 사용하여 클라이언트와 서버간 통신도 가능하고, 모든 것이 자바 애플릿 보다 가볍다. GWT는 기본적으로 컴파일러이다. GWT는 자바 코드를 HTML 페이지에 삽입되어 실행될 수 있는 JavaScript 코드로 변환하여 클라이언트 측 애플리케이션을 실행하는데 사용된다. JavaScript 코드는 거의 모든 브라우저에서 지원되므로 여러분은 프로그램의 인터페이스와 인터랙션에 집중할 수 있다. 물론, GWT가 컴파일러일 뿐이라면, 거론하지 않았을 것이다. 다행히도, 그 이상의 기능을 한다. GWT는 컴파일러 메커니즘 뿐 만 아니라, 아래와 같은 부가적인 특징이 있다.
본 시리즈에서는 이러한 기능들을 설명할 것이다. 하지만 먼저, GWT를 다운로드 및 설치해야 한다. 이 글을 쓰고 있는 현재, GWT 최신 버전은 1.2이다. (참고자료) GWT는 Microsoft® Windows® XP, Windows 2000, Linux® 그리고, Mac OS X에서 실행되는 GTK+ 2.2.1 또는 그 이후 버전에서 완벽히 지원된다. 다운로드 한 압축 파일을 원하는 디렉토리에 압축을 푼다. 버전들마다 약간 다르지만, 기본 엘리먼트는 다음과 같다.
GWT를 사용할 때, 일부 파일들은 임시 파일들을 관리하기 위해 GWT 홈 디렉토리에 놓인다. 다운로드를 마치면, 가장 먼저 프로젝트를 만들어야 한다. 온라인에서 피자를 파는, Slicr라고 하는 새로운 Web 2.0 비즈니스의 온라인 사이트를 구축할 것이다. GWT 프로젝트를 설정하는 방법들은 IDE를 사용할 것인지의 여부에 따라 다르다. 여기에서는 GWT 명령행 유틸리티의 지원도 받는 무료 Eclipse를 사용하도록 하자. 명령행 유틸리티를 사용하여 Eclipse 프로젝트를 만든다.
<GWT_HOME>/projectCreator -eclipse slicr 이 명령어로는 GWT 프로젝트에 필요한 최소한의 것만 만든다. 새로운 src 하위 디렉토리와 새로운 .project와 .classpath 파일이 생겼다. 지금 바로 프로젝트로 시작할 수 있지만, GWT는 그 이상의 구조를 기대한다. 다음 명령어를 사용하여 설정할 수 있다. <GWT_HOME>/applicationCreator -eclipse slicr com.ibm.examples.client.Slicr
이 명령어는 몇 가지 파일을 생성한다. .java 파일은 메인 클래스이고, 해당 클래스에 동반된 패키지 명에 부합되게 부모 디렉토리 들이 생성된다. 여러분은 최하위 디렉토리에는 client와 public이 생성되어 있는 것을 확인 할 수 있다. 앞에서 거론한 public 디렉토리에는 Slicr.html와 Slicr.gwt.xml을 확인 할 수 있다. 또한, GWT는 eclipse가 사용하게 될 Slicr.launch파일과 두 개의 셀 스크립트 파일을 생성 한다.
이제 프로젝트를 Eclipse로 옮긴다.
이 프로세스를 통해, 코드를 Eclipse로 옮겨서 볼 수 있다. GWT는 세 개의 중요한 파일들을 만들었다. 첫 번째가 Listing 1. slicr.gwt.xml
여기에서 GWT 애플리케이션에 대한 모듈을 정의할 수 있다. 모듈(module)은 GWT 코드의 기본 단위이고, 클라이언트가 사용하는 HTML 페이지가 참조한다. 두 번째 파일은 퍼블릭 디렉토리에서 만들어진 Slicr.html 파일이다. 이것은 웹 애플리케이션의 프론트 페이지로서 클라이언트로 보내지는 .html 파일이다. 실제로 필요하지 않는 많은 코멘트들이 들어있다. Listing 2는 파일의 핵심 부분이다. Listing 2. Slicr.html
가장 중요한 것은 바로 위의 .html 파일이다. 원하는 어떤 HTML이라도 추가할 수 있다. 가장 중요한 것은 HTML 파일에 원하는 어떤 내용이라도 추가 및 변형 할 수 있다는 것이다. 단지, GWT는 아래 네 가지 엘리먼트에 의해서 실행된다.
GWT는 재사용이 가능한(boilerplate) 자바 시작 클래스도 Listing 3과 같이 만든다. Listing 3. 자바 시작 클래스
위의 자바 클래스는 위의 코드는 단순하다고 할 수 있다. 처음 두 라인에 버튼과 레이블을 정의한다. 그 다음 두 라인에서는, 위의 코드 라인들 사이에 Swing에서와 같이 이벤트를 묶는데 사용하는 것과 비슷한 방식을 사용하여 이벤트 리스너(eventListner)를 정의한다. 위의 경우, 버튼을 클릭하면
GWT가 만든 샘플 프로그램을 실행해 보자. GWT 프로그램을 실행하는 두 가지 방법이 있다. 바로 웹 모드(Web mode)와 호스트 모드(hosted mode)이다. 웹 모드는 완전한 전개 모드로서, GWT 프로그램을 JavaScript 코드로 컴파일 한 후에 실행한다. 호스트 모드는 개발하는 동안 사용된다. 호스트 모드란, 클라이언트와 서버 코드를 한번에 시뮬레이트 하면서, 개발하는 동안 전개를 단순화 시키는 일종의 에뮬레이터이다. (호스트 모드는 Mac OS X에서는 불가능하다.) 디버거와 함께 IDE를 사용한다면, 호스트 모드에서 GWT 프로그램을 실행할 수 있으며, JavaScript로 컴파일 될 코드 부분에서 중단점(breakpoint)을 지정하고 그의 변수(variable)의 변경사항을 알아낼 수 있다. 이러한 부분은 개발 시 매우 유용하며, GWT로 작업하게 되면, 대부분 호스트 모드를 사용하게 된다. 또한, 여러 가지 방법들로 호스트 모드를 실행할 수 있다. 이전에 실행했던 그림 2. 호스트 모드 호출하기 호스트 모드에서 실행할 때, 두 개의 창이 나타난다. (처음 실행할 경우, 호스트 모드 설정이 초기화되는 동안 1분여의 시간이 걸린다.) 그림 3에서 보이는 첫 번째 창의 이름은 Google Web Toolkit Development Shell / Port 8888.이다. 여기에는 GWT의 에러와 로그 메시지들이 들어있다. 툴바를 사용하여, 새로운 호스트 브라우저를 열 수 있고, 스크린상의 로그를 확장, 축소, 삭제할 수 있다. 그림 3. 호스트 모드 쉘 윈도우 그림 4에 보이는 두 번째 창은 브라우저 모습이다. 보다시피, slicr.html 페이지에서 생성된 정적 HTML과 Slicr.java EntryPoint 클래스에서 생성된 버튼 위젯이 있다. 버튼을 클릭하면 레이블이 선택된다. 설정 단계에서 오류가 있었다면, 이 창을 볼 수 없고 대신 쉘에 에러 메시지가 나타난다. 모든 이름들이 정확한지를 확인하라. (특히, .launch 파일에서, 정확한 프로젝트 디렉토리가 지정되었는지를 확인한다.) 그림 4. 호스트 모드 브라우저 이 글에서는 스크린상에서 위젯을 실행시키는 것에 초점을 맞추겠다. 그림 5에 보이는 스크린은 매우 단순해 보이지만, 꽤나 기능적이다. 그림 5. Slicr 페이지가 로딩될 때 이러한 위젯들을 생성시키려면, Listing 4. 모듈 로드 이벤트 핸들러
Listing 5. 메인 패널 초기화 하기
Listing 6. SOUTH (buttons) 패널
GWT pizza type 의 패널은 Listing 7과 같이 복잡하지 않다. GWT Listing 7. WEST (pizza types) 패널
HTML을 실행하는 레이블인 EAST 패널 (toppings) 만들기 topping 패널은 Listing 8처럼 좀더 복잡하다. 사용자가 다양한 토핑을 가진 피자를 만들 수 있도록 해야 한다. 토핑 버튼을 클릭하면 두 쪽 모두 체크되지만, 한 쪽만 체크되거나, 개별적으로 삭제될 수 있다. 모든 것의 줄을 맞춰야 하기 때문에 Grid를 사용한다. Listing 8. 토핑 그리드
위젯을 설정했다면, 두 개의 정의된 리스너를 보자. 두 개 중 더 단순한 것이 Clear 버튼에 대한 것이다. Listing 9와 같이 이 버튼은 Listing 9. Clear 버튼에 정의된 리스너
주: GWT에서, 토핑 버튼용 리스너는 더 복잡하다. 제휴 체크 박스들 중 어떤 것도 선택되지 않으면, 이 리스너는 두 개의 체크 박스 모두를 선택한다. 다른 상황에서는, 두 가지 모두를 지운다. Listing 10은 그 예이다. Listing 10. 버튼에 정의된 리스너
이번 글에서는 slicr 클라이언트를 구현해 보았다. 다음 글에서는 Derby 데이터베이스를 사용하여 서버 측에서 데이터 레이어를 구현하고, 데이터베이스에서 온 데이터를 GWT 클라이언트로 보내질 수 있는 자바 객체들로 변환하는 방법을 설명하겠다. 서버와 클라이언트를 연결하는 원격 프로시저 아키텍처도 설명한다. 서버 측이 개별적으로 실행되어야 한다면, 개발 및 실행 환경에 이를 전개하는 방법을 고려해야 한다. 또한, 인터페이스를 보기 좋은 모양으로 만드는 방법도 배울 것이다. 그 전에 GWT 다운로드 사이트에 가서 직접 실행해 보기 바란다. 교육
제품 및 기술 얻기
토론
|
개발자가 놓치기 쉬운 자바의 기본원리
- 전성호(커뮤니티본부 커뮤니티개발1팀), 2006년 10월
목차
-
- 1 객체지향의 구멍 static
- 2 Java는 Pointer언어이다? (Java에는 Pointer밖에 없다?)
- 3 상속과 interface의 문제점
- 4 package와 access 제어에 관한 이해
- 5 기타 Java 기능
- 6 이래도 Java가 간단한가?
- 7 Java 기능 적용 몇가지
- 8 Java 5.0 Tiger 에 대하여
-
- 8.1 Working with java.util.Arrays
- 8.2 Using java.util.Queue interface
- 8.3 java.lang.StringBuilder 사용하기
- 8.4 Using Type-Safe Lists
- 8.5 Writing Generic Types
- 8.6 새로운 static final enum
- 8.7 Using java.util.EnumMap
- 8.8 Using java.util.EnumSet
- 8.9 Convert Primitives to Wrapper Types
- 8.10 Method Overload resolution in AutoBoxing
- 8.11 가변적인 argument 개수 ...
- 8.12 The Three Standard Annotation
- 8.13 Creating Custom Annotation Types
- 8.2 Using java.util.Queue interface
- 8.1 Working with java.util.Arrays
- 9 The for/in Statement
-
- 9.1 for/in 의 자주 사용되는 형태
- 10 Static Import
-
- 10.1 static member/method import
- 11 References
1.1 Java는 객체지향 언어이다? #
- 오해1. "객체지향에서는 객체끼리 서로 메세지를 주고 받으며 동작한다." 라는 말을 듣고 다음과 같이 생각할 수 있다. "객체지향에서는 객체가 각각 독립하여 움직인다는 것인가, 그러면 각 객체에 독립된 thread가 할당되어 있단 말인가?" 그렇지 않다. "메세지를 보낸다"라는 것은 단순히 각 객체의 함수 호출에 불과하다.
- 오해2. "객체지향에서는 method가 class에 부속되어 있다"는 말을 듣고 다음과 같이 생각할 수 있다. "그러면 instance별로 method의 실행코드가 복제되고 있는 것이 아닌가?" 물론 이것도 오해다. method의 실행코드는 종래의 함수와 동일한 어딘가 다른곳(JVM의 class area)에 존재하며 그 첫번째 파라미터로 객체의 포인터 this가 건네질 뿐이다.
- 오해3. "그렇다면 각 instance가 method의 실행코드를 통째로 갖고 있지 않는 것은 확실하지만, method의 실행 코드의 포인터는 각 instance별로 보관하고 있는것이 아닌가?" 이것은 약가 애매한 오해이긴 하다. JVM 스펙에서는 class영역에 실행코드를 갖고 있으며, method 호출시 별도의 stack frame이 생성되어 실행되고 실행 완료시 복귀 주소를 전달한다.
1.2 전역변수 #
- (참고) final 초기화에서의 주의점. 예를 들어 다음과 같은 코드를 보았을때 우려되는 점은 무엇인가?
public final static Color WHITE = new Color(255, 255, 255);
- static field는 final의 경우와 달리 정말 "하나여도 되는지" 여부를 잘 생각해야 한다.
- static method는 주저하지 말고 쓰되 다음 두가지의 경우 매우 활용적이다.
- 다른 많은 클래스에서 사용하는 Utility Method 군을 만드는 경우. (주로 Utility Class의 method)
- 클래스 안에서만 사용하는 "하청 메소드(private method)". 이유를 예를 들어 설명하면, 아래와 같은 조금은 과장된 클래스가 있다고 하자.
public class T .. private int a; private int b; private int c; private int calc(){ c = a + b; return c * c; } ....other method or getter/setter...
private static int calc(int a, int b){ int c = a + b; return c * c; }
2.1 Java는 primitive형을 제외하곤 모두 Pointer이다 #
2.2 null은 객체인가? #
- null object의 instance method 호출
- null object의 field(member variables)에 대한 액세스 또는 그 값의 변경
- null의 길이를 배열처럼 취득할 경우
- null의 slot을 배열처럼 액세스 또는 수정
- null을 Throwable처럼 throw 할 경우
2.3 String에 대하여 #
String str = "111222"; String a = "111"; String b = "222"; String c = "111"; String d = b; String t = str.substring(0,3); //111
- str == (a + b) ==> 이것은 두개의 참조와 하나의 참조를 비교했으므로 당연히 false이다.
- a == b ==> 이것은 당연히 false
- d == b ==> 이것은 동일한 reference이므로 true
- a == t ==> a 와 t 는 둘다 값이 "111"이다. 하지만 이것은 서로 다른 참조를 가져 false이다. 그렇다면 다음 5번도 false일까?
- a == c ==> 이것은 true이다. 아.. 4번과 혼란스럽다. 이것이 참인 이유는? ==> 이것의 해답은 JSR 3.10.5에 다음과 같이 나와 있기 때문이다.
2.4 객체지향의 캡슐화 파괴 주의 #
//(참고)Member에는 두개의 field(Identity Class 형의 ID와 Family Class 형의 family)가 있다. /** shallow copy */ Member shallowCopy(){ Member newer = new Member(); newer.id = this.id; newer.family = this.family; return newer; } /** deep copy */ Member deepCopy(){ Member newer = new Member(); newer.id = new Idetity(this.id.getId(), this.id.getName()); newer.family = new Family(this.family.getFamilyName(), this.family.getFamilyInfo()); return newer; }
- 모든 field(member variable)를 생성자(constructor)를 이용하여 초기화 한다.
- 모든 field는 private으로 선언하고, getter method는 만들되 setter는 기술하지 않는다.
2.5.1 배열은 object 인가? #
2.5.2 배열의 length는 왜 field(member variable)인가? #
2.5.3 final과 배열에 대하여... #
2.5.4 "Java에서의 다차원 배열은 존재하지 않는다." #
2.6.1 "Java에서 parameter(argument) 전달은 무조건 'call by value' 이다" #
2.6.2 "C와 같은 언어는 static linking이지만, Java는 dynamic linking이다." #
2.7.1 "Garbage Collection은 만능이 아니다." #
2.8.1 "결국 Java에는 pointer가 있는 것인가, 없는 것인가?" #
// 이부분에 대해 Object를 이해하시면 족히 이런 문제는 사라질것으로 봅니다.
// 클래스에 대한 인스턴스(object)들은 reference로 밖에 가질(참조될)수 없기 때문입니다.
// 컴파일러 입장이 아닌 언어 자체의 사상을 가지고 쉽게 이해시키는 것이 좋을것 같습니다.
3.1.1 상속에 있어서의 생성자(constructor) #
3.1.2 "down cast는 본질적으로 매우 위험하다" #
3.1.3 "추상클래스에 final이 있으면 compile error이다" #
3.2.1 "interface는 interface일뿐 다중 상속의 대용품이 아니다." #
3.3 상속 제대로 사용하기 #
- 상속에서는 슈퍼클래스가 허용하고 있는 조작을 서브클래스에서 모두 허용해야 하지만, composition과 delegation에서는 조작을 제한할 수 있다.
- 클래스는 결코 변경할 수 없지만, composition하고 있는 객체는 자유롭게 변경할 수 있다. 예를 들면 학생 클래스가 영원이 학생이 아니라 나중에 취직을 하여 직장인 클래스가 될수 있다.
- Shape(부모)의 공통된 내용을 구현한 구현 클래스(ShapeImpl)를 만든다.
- Polyline과 Circle 클래스에서 ShapeImpl을 composition하고 부모와 공통되지 않는 method를 각각 위임 받는다.
- ShapeImpl 클래스의 method를 추출한 ShapeIF interface를 작성하고 Polyline과 Circle에서는 implements 한다.
4.1.1 "package는 '계층구조' 인가?" #
4.1.2 "compiler 가 인식하는 class검색 순서(소스코드내 클래스가 발견될 경우 그 클래스의 위치를 찾는 순서)" #
- 그 class자신
- 단일형식으로 임포트된 class
- 동일한 패키지에 존재하는 다른 class
- 온디멘드 형식(..* 형태) 임포트 선언된 class
4.2.1 "interfacde member의 access 제어" #
4.2.2 그렇다면 interface를 다른 package에 대하여 숨기고 싶으면 어떻게 하는가? #
5.1.1 "Multi Thread에서는 흐름은 복수이지만 data는 공유될 수 있다." #
5.1.2 "Thread는 객체와 직교하는 개념이다." #
- Multi Thread에서는 Thread라는 처리 흐름이 2개 이상 존재할 수 있다.
- 어떤 Thread에서 움직이기 시작한 method가 다른 method를 호출 했을때 호출된 측의 method는 호출한 측의 method와 동일한 Thread에서 동작한다.
- Thread의 경계와 객체의 경계는 전혀 관계가 없다. 즉, Thread와 객체는 직교하고 있다.
5.1.3 "Synchronized 의 이해" #
synchronized void method1(){ ... } void method2(){ synchronized(this){ ... } }
5.1.4 "Thread 사용법의 정석은?" #
- Runnable을 implements하고 Thread의 참조를 보유(composition) 하는 방법. 이경우는 단지 Runnable만 implement함으로서 해결되는 경우가 대부분이긴 하지만, 그 class 내에서 해당 class의 Thread를 조작하게 된다면 composition한 Thread 객체에 delegation하면 된기 때문이다.
- Thread class를 상속하는 방법. JDK의 소스를 보면 Thread class에는 Runnable을 implements 하고 있다. 그리고 run method는 native method이다. 따라서 Thread를 상속한 모든 클래스는 사실 Runnable을 implements하고 있는 것이다. run method는 abstract가 아니므로 구현되어 있고 우리는 이를 오버라이드하여 사용하고 있다. 이 방식을 사용하면 Thread의 method를 안팍으로 자유롭게 호출할 수 이지만, 이미 다른 class를 상속하고 있다면 이 방식을 사용할 수는 없다.
5.2.1 "finally 절은 반드시 어떠한 경우에도 실행되는가?" #
try{ ... System.exit(1); }catch(...){ }finally{ ... //이 부분은 실행되지 않는다. }
5.2.2.1 Error #
5.2.2.2 RuntimeException #
5.2.2.3 그밖의 Exception #
5.2.3 "OutOfMemoryError는 어떻게 처리해야 하는가?" #
5.3 Object Serialize #
5.3.1 "Serialize를 위해서는 marker interface인 java.io.Serializable interface를 implements해야한다." #
5.3.2 "super class는 Serializable이 아닌데 sub class만 Serializable인 경우의 문제점" #
5.3.3 "transient field의 복원(?)관련" #
private void writeObject(java.io.ObjectOutputStream out) throws IOException;private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
5.3.4 "Stack Overflow에 주의하라!" #
private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWrtieObject(); //이 코드는 무조건 들어가게 되는데 이곳 소스의 System.arraycopy()에서 overflow발생한다. s.writeInt(size); //이부분이 실제 추가되어 Stack Overflow를 예방한다. for(Entry e = ...) s.writeObject(e.element); } ... } //readObject()도 이와 같은 개념으로 변경되어 있다.
5.4.1 "중첩클래스의 개념" #
5.4.2 "내부클래스는 부모의 참조를 몰래 보유하고 있다." #
class Test{ class InnerClass { int i; ... } public static void main(String[] args){ InnerClass icls = new InnerClass(); ... } }
5.4.3 "local inner class에 대하여" #
public class OuterClass { public int get(){ int i = 9; int id = 99; int id2 = 99; final int id3 = 100000; class LocalInnerClass { int id = 100; LocalInnerClass(){ System.out.println("LocalInnerClass"); } int getId(){ return id3 + id; } } LocalInnerClass lic = new LocalInnerClass(); return id + lic.getId(); } public static void main(String[] args){ OuterClass outer = new OuterClass(); System.out.println("id = " + outer.get()); //결과 값은 "100000(id3) + 100(LocalInnerClass.id) + 99(OuterClass.get())" 인 100199가 나온다. } }
5.4.4 "anonymous class(무명클래스)에 대하여" #
class AnonymousTest { private interface Printable { void print(); } static void doPrint(Printable p){ p.print(); } public static void main(String[] args){ doPrint( new Printable(){ public void print(){ System.out.println("this is new Printable print()"); } }); } }
6.1.1 "overload란 이름이 가고 인수가 다른 method에 compiler가 다른 이름을 붙이는 기능" #
//IFS.java interface IFS { public String getName(); } //Impl1.java class Impl1 implements IFS { public String getName(){ return "Impl1"; } } //Impl2.java class Impl2 implements IFS { public String getName(){ return "Impl2"; } } //main이 있는 OverloadTest.java public class OverloadTest { static void pr(int i){ System.out.println("pr_int : " + i); } static void pr(String s){ System.out.println("pr_string : " + s); } static void pr(IFS ifs){ System.out.println("pr_string : " + ifs.getName()); } static void pr_run(Impl1 i1){ System.out.println("pr_run : " + i1.getName()); } static void pr_run(Impl2 i2){ System.out.println("pr_run : " + i2.getName()); } public static void main(String[] args){ OverloadTest test = new OverloadTest(); test.pr(10); test.pr("Jeid"); IFS ifs1 = new Impl1(); test.pr(ifs1); IFS ifs2 = new Impl2(); test.pr(ifs2); //pr_run(ifs1); //pr_run(ifs2); } }
OverloadTest.java:36: cannot resolve symbol symbol : method pr_run (IFS) location: class OverloadTest pr_run(ifs1); ^ OverloadTest.java:37: cannot resolve symbol symbol : method pr_run (IFS) location: class OverloadTest pr_run(ifs2); ^ 2 errors
6.1.2 "그렇다면 overload에서 실제로 혼동되는 부분은 무엇인가?" #
class OverloadTest2 { static int base(double a, double b){ ... } //method A static int count(int a, int b){ ... } //method B static int count(double a, double b){ ... } //method C static int sum(int a, double b){ ... } //method D static int sum(double a, int b){ ... } //method E }
- base(3,4) 를 호출했을때 수행되는 method는? => 당연히 method A (3과 4는 정수라도 double이 되므로 정상적으로 수행됨)
- count(3,4) 를 호출했을때 수행되는 method는? => B와 C중 갈등이 생긴다. 이럴경우 JVM은 가장 한정적(more specific)한 method를 찾는다. 여기서 3과 4는 정수형에 가까우므로 method B 가 호출된다.
- count(3, 4.0) 을 호출했을때 수행되는 method는? => 이것은 4.0 이 double이므로 method C 가 더 한정적이므로 method C 가 호출된다.
- sum(3,4.0) 을 호출했을때 수행되는 method는? => 이것은 당연히 type이 일치하는 method D.
- sum(3,4) 를 호출했을때 수행되는 method는?? => 이런 코드가 소스내에 있으면 다음과 같은 compile 오류를 표출한다.
OverloadTest.java:48: reference to sum is ambiguous, both method sum(int,double) in OverloadTest and method sum(double,int) in OverloadTest match System.out.println("sum(3,4) = " + sum(3,4)); ^ 1 error
6.1.3 (참고) 또다른 혼동, overload한 method를 override 하면? #
6.2.1 "Java class의 member 4 종류" #
- instance field
- instance method
- static field
- static method
6.2.2 "override시 method 이름에 대한 함정" #
6.2.3 "또다른 나의(?) 실수 - 말도 안되는 오타" #
public class Member { private int memberNo; public int getMemberNo(){ return this.memberNo; } public void setMemberNo(int menberNo){ this.memberNo = memberNo; } ...... }
6.2.4 "static member를 instance를 경유하여 참조해서는 안 된다." #
ClassA a = new ClassA(); int i = a.AA; //instance를 경유하여 접근 int j = ClassA.AA; //올바르게 접근
6.2.5 "super keyword는 부모의 this" #
6.4.1 "생성자에 void 를 붙인다면?" #
public class ConstructorTest{ void ConstructorTest(){ System.out.println("Constuctor"); } ..... }
6.4.2 "if / switch 의 함정" #
.... if( a < 5 ) b = 3; c = 10; //이부분은 나중에 추가된 라인이다. if( isStudent ) if( isFemale ) sayHello("Hi~~"); else sayHello("Hello Professor~");
7.1.1 "interface 분리의 필요성" #
7.2 Java에서의 열거형 #
public static final int LEFT = 0; public static final int CENTER = 1; public static final int RIGHT = 2; ... label.setAlignment(Label.CENTER); ...
//LabelAlignment.java public class LabelAlignment { private LabelAlignment() {} //이는 생성자를 private으로 하여 다른데서는 만들지 못하도록 하기위함이다. public static final LabelAlignment LEFT = new LabelAlignment(): public static final LabelAlignment CENTER = new LabelAlignment(): public static final LabelAlignment RIGHT = new LabelAlignment(): } //변형된 Label.java 의 일부.. public synchronized void setAlignment(LabelAlignment alignment){ if( alignment == LabelAlignment.LEFT ){ ...//왼쪽으로 맞추기.. }else if( ... ... } } ...
//LabelAlignment.java public class LabelAlignment { private int flag; private LabelAlignment(int flag){ this.flag = flag; } public static final LabelAlignment LEFT = new LabelAlignment(0): public static final LabelAlignment CENTER = new LabelAlignment(1): public static final LabelAlignment RIGHT = new LabelAlignment(2): public boolean equals(Object obj){ return ((LabelAlignment)obj).flag == this.flag; } } //변형된 Label.java 의 일부.. public synchronized void setAlignment(LabelAlignment alignment){ if( LabelAlignment.LEFT.equals(alignment) ){ ...//왼쪽으로 맞추기.. }else if( ... ... } } ...
7.3 Debug write #
#ifdef DEBUG fprintf(stderr, "error...%d\n", error); #endif /* DEBUG */
if( Debug.isDebug ){ System.out.println("error..." + error); }
// 1. GetCallerSecurityManager.java public final class GetCallerSecurityManager extends SecurityManager { public Class[] getStackTrace(){ return this.getClassContext(); } } // 2. GetCallerClass.java public final class GetCallerClass { private static GetCallerSecurityManager mgr; static{ mgr = new GetCallerSecurityManager(); System.setSecurityManager(mgr); } public static void writeCaller(String str){ Class[] stk = mgr.getStackTrace(); int size = stk.length; for(int i = 0; i < size; i++){ System.out.println("stk[" + i + "] = " + stk[i]); } String className = stk[2].getName(); System.out.println("className is " + className + " : " + str); } } // 3. GetCallerClassMain1 : 호출하는 클래스 예제 1 public class GetCallerClassMain1 { public static void main(String[] args){ GetCallerClass.writeCaller(", real is 1."); } } // 4. GetCallerClassMain1 : 호출하는 클래스 예제 2 public class GetCallerClassMain2 { public static void main(String[] args){ GetCallerClass.writeCaller(", real is 2."); } }
className is GetCallerClassMain1 : , real is 1. className is GetCallerClassMain2 : , real is 2.
8.1 Working with java.util.Arrays #
package com.jeid.tiger;import java.util.Arrays;import java.util.Comparator;import java.util.List;public class ArraysTester { private int[] arr; private String[] strs; public ArraysTester(int size) { arr = new int[size]; strs = new String[size]; for (int i = 0; i < size; i++) { if (i < 10) { arr[i] = 100 + i; } else if (i < 20) { arr[i] = 1000 - i; } else { arr[i] = i; } strs[i] = "str" + arr[i]; } } public int[] getArr() { return this.arr; } public String[] getStrs() { return this.strs; } public static void main(String[] args) { int size = 50; ArraysTester tester = new ArraysTester(size); int[] testerArr = tester.getArr(); int[] cloneArr = tester.getArr().clone(); String[] testerStrs = tester.getStrs(); String[] cloneStrs = tester.getStrs().clone(); // clone test if (Arrays.equals(cloneArr, testerArr)) { System.out.println("clonse int array is same."); } else { System.out.println("clonse int array is NOT same."); } if (Arrays.equals(cloneStrs, testerStrs)) { System.out.println("clonse String array is same."); } else { System.out.println("clonse String array is NOT same."); } // 2부터 10까지 값 셋팅 Arrays.fill(cloneArr, 2, 10, new Double(Math.PI).intValue()); testerArr[10] = 98; testerStrs[10] = "corea"; testerStrs[11] = null; List<String> listTest = Arrays.asList(testerStrs); System.out.println("listTest[10] = " + listTest.get(10)); System.out.println("------- unsorted arr -------"); System.out.println("Arrays.toString(int[]) = " + Arrays.toString(testerArr)); System.out.println("Arrays.toString(String[]) = " + Arrays.toString(testerStrs)); Arrays.sort(testerArr); // Arrays.sort(testerStrs); //NullPointerException in sort method..(null이 없더라도 길이에 대한 크기 체크는 못함) Arrays.sort(testerStrs, new Comparator<String>() { public int compare(String s1, String s2) { if (s1 == null && s2 == null) { return 0; } else if (s1 == null && s2 != null) { return -1; } else if (s1 != null && s2 == null) { return 1; } else if (s1.length() < s2.length()) { return -1; } else if (s1.length() > s2.length()) { return 1; } else if (s1.length() == s2.length()) { return 0; } else { return s1.compareTo(s2); } } }); System.out.println("------- sorted arr -------"); System.out.println("Arrays.toString(int[]) = " + Arrays.toString(testerArr)); System.out.println("Arrays.toString(String[]) = " + Arrays.toString(testerStrs)); System.out.println("------------------------------------------------"); String[][] mstrs1 = { { "A", "B" }, { "C", "D" } }; String[][] mstrs2 = { { "a", "b" }, { "c", "d" } }; String[][] mstrs3 = { { "A", "B" }, { "C", "D" } }; System.out.println("Arrays.deepToString(mstrs1) = " + Arrays.deepToString(mstrs1)); System.out.println("Arrays.deepToString(mstrs2) = " + Arrays.deepToString(mstrs2)); System.out.println("Arrays.deepToString(mstrs3) = " + Arrays.deepToString(mstrs3)); if( Arrays.deepEquals(mstrs1, mstrs2)) { System.out.println("mstrs1 is same the mstrs2."); }else { System.out.println("mstrs1 is NOT same the mstrs2."); } if( Arrays.deepEquals(mstrs1, mstrs3)) { System.out.println("mstrs1 is same the mstrs3."); }else { System.out.println("mstrs1 is NOT same the mstrs3."); } System.out.println("mstrs1's hashCode = " + Arrays.deepHashCode(mstrs1)); System.out.println("mstrs2's hashCode = " + Arrays.deepHashCode(mstrs2)); System.out.println("mstrs3's hashCode = " + Arrays.deepHashCode(mstrs3)); }}
8.2 Using java.util.Queue interface #
package com.jeid.tiger;import java.util.LinkedList;import java.util.PriorityQueue;import java.util.Queue;public class QueueTester { public static void main(String[] args) { System.out.println("---------- testFIFO ----------"); testFIFO(); System.out.println("---------- testOrdering ----------"); testOrdering(); } private static void testFIFO() { Queue<String> q = new LinkedList<String>(); q.add("First"); q.add("Second"); q.add("Third"); String str; while ((str = q.poll()) != null) { System.out.println(str); } } private static void testOrdering() { int size = 10; Queue<Integer> qi = new PriorityQueue<Integer>(size); Queue<String> qs = new PriorityQueue<String>(size); for (int i = 0; i < size; i++) { qi.offer(10 - i); qs.offer("str" + (10 - i)); } for (int i = 0; i < size; i++) { System.out.println("qi[" + i + "] = " + qi.poll() + ", qs[" + i + "] = " + qs.poll()); } }}
8.3 java.lang.StringBuilder 사용하기 #
package com.jeid.tiger;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class StringBuilderTester { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("str1"); list.add("str2"); list.add("str3"); String ret = appendItems(list); System.out.println("ret = " + ret); } private static String appendItems(List<String> list) { StringBuilder sb = new StringBuilder(); for (Iterator<String> iter = list.iterator(); iter.hasNext();) { sb.append(iter.next()).append(" "); } return sb.toString(); }}
8.4 Using Type-Safe Lists #
package com.jeid.tiger;import java.util.Iterator;import java.util.LinkedList;import java.util.List;public class ListTester { public static void main(String[] args) { List<String> list = new LinkedList<String>(); list.add("str1"); list.add("str2"); list.add(new Integer(123)); // <-- String이 아니므로 compile error!! //Iterator에 String type을 명시하므로 정삭작동됨. for (Iterator<String> iter = list.iterator(); iter.hasNext();) { String str = iter.next(); System.out.println("srt = " + str); } //Iterator에 String type을 명시하지 않았으므로 아래 A 부분에서 compile 오류 발생!! for (Iterator iter = list.iterator(); iter.hasNext();) { String str = iter.next(); //A System.out.println("srt = " + str); } //byte, short, int, long, double, float 동시 사용 List<Number> lstNum = new LinkedList<Number>(); lstNum.add(1); lstNum.add(1.2); for (Iterator<Number> iter = lstNum.iterator(); iter.hasNext();) { Number num = iter.next(); System.out.println("num = " + num); } }}
8.5 Writing Generic Types #
class AnyTypeList<T> {//class AnyTypeList<T extends Number> { // <-- 이는 Number를 상속한 type은 허용하겠다는 의미. private List<T> list; //private static List<T> list; // <-- 이는 정적이므로 compile error 발생!!! public AnyTypeList(){ list = new LinkedList<T>(); } public boolean isEmpty(){ return list == null || list.size() == 0; } public void add(T t){ list.add(t); } public T grap(){ if (!isEmpty() ) { return list.get(0); } else { return null; } }}
8.6 새로운 static final enum #
package com.jeid.tiger;import com.jeid.BaseObject;import com.jeid.MyLevel;public class EnumTester extends BaseObject { private static long start = System.currentTimeMillis(); public static void main(String[] args) { try { test(); enum1(); } catch (Exception e) { e.printStackTrace(); } printEllapseTime(); } private static void test() throws Exception { byte[] b = new byte[0]; System.out.println(b.length); } private static void enum1() { //enum TestEnum { A, B }; //enum cannot be local!!! for(MyVO.TestEnum te: MyVO.TestEnum.values()){ System.out.println("Allow TestEnum value : " + te); } System.out.println("---------------------------------------"); MyVO vo = new MyVO(); vo.setName("enum1"); vo.setLevel(MyLevel.A); System.out.println(vo); System.out.println("isA = " + vo.isA() + ", isGradeA = " + vo.isLevelA()+ ", isValueOfA = " + vo.isValueOfA()); System.out.println("getLevelInKorean = " + vo.getLevelInKorean()); } private static void printEllapseTime() { System.out.println("==> ellapseTime is " + (System.currentTimeMillis() - start) + " ms."); }}package com.jeid.tiger;import com.jeid.BaseObject;import com.jeid.MyLevel;public class MyVO extends BaseObject { enum TestEnum { A, B }; // this is same public static final private int id; private String name; private MyLevel grade; // private List<T> list; public MyLevel getLevel() { return grade; } public void setLevel(MyLevel grade) { this.grade = grade; } public boolean isA() { return "A".equals(this.grade); } public boolean isValueOfA() { return MyLevel.valueOf("A").equals(grade); } public boolean isLevelA() { return MyLevel.A.equals(this.grade); } //A,B,C..대신 0,1,2... 도 동일함. public String getLevelInKorean() { switch(this.grade){ case A: return "수"; case B: return "우"; case C: return "미"; case D: return "양"; case E: return "가"; default: return "없음"; } } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
8.7 Using java.util.EnumMap #
package com.jeid.tiger;import java.util.EnumMap;public class EnumMapTester { private enum MyEnum { A, B, C }; // this is same the static final.. public static void main(String[] args) { MyEnum[] enums = MyEnum.values(); System.out.println("MyEnum is " + enums[0] + ", " + enums[1] + ", " + enums[2]); EnumMap<MyEnum, String> em = new EnumMap<MyEnum, String>(MyEnum.class); em.put(MyEnum.A, "수"); em.put(MyEnum.B, "우"); em.put(MyEnum.C, "미"); em.put(MyEnum.B, "가"); //key 중복은 HashMap과 동일하게 overwrite임. for (MyEnum myEnum : MyEnum.values()) { System.out.println(myEnum + " => " + em.get(myEnum)); } }}
8.8 Using java.util.EnumSet #
package com.jeid.tiger;import java.util.EnumSet;public class EnumSetTester { private enum MyEnum { A, B, C, a, b, c }; // this is same the static final.. public static void main(String[] args) { MyEnum[] enums = MyEnum.values(); System.out.println("MyEnum is " + enums[0] + ", " + enums[1] + ", " + enums[2]); EnumSet<MyEnum> es1 = EnumSet.of(MyEnum.A, MyEnum.B, MyEnum.C); EnumSet<MyEnum> es2 = EnumSet.of(MyEnum.a, MyEnum.b, MyEnum.c); EnumSet<MyEnum> es3 = EnumSet.range(MyEnum.a, MyEnum.c); if (es2.equals(es3)) { System.out.println("e2 is same e3."); } for (MyEnum myEnum : MyEnum.values()) { System.out.println(myEnum + " contains => " + es1.contains(myEnum)); } }}
8.9 Convert Primitives to Wrapper Types #
package com.jeid.tiger;public class AutoBoxingTester { public static void main(String[] args) { int i = 0; Integer ii = i; // boxing. JDK 1.4에서는 incompatible type error가 발생 했었으나 Tiger에서는 괜찮다. int j = ii; // unboxing for (ii = 0; ii < 5; ii++) { // Integer인데도 ++ 연산자 지원. } i = 129; ii = 129; if (ii == i) { System.out.println("i is same ii."); } // -128 ~ 127 사이의 수는 unboxing이 되어 == 연산이 허용되지만, // 그 범위 외의 경우 Integer로 boxing된 상태므로 equals를 이용해야함. // 이는 버그가 발생했을 경우 찾기 쉽지 않은 단점도 내포하고 있다.!! checkIntegerSame(127, 127); // same checkIntegerSame(128, 128); // Not same checkIntegerEquals(128, 128); // equals checkIntegerSame(-128, -128); // same checkIntegerSame(-129, -129); // Not same checkIntegerEquals(-129, -129); // equals System.out.println("--------------------------------------------"); Boolean arriving = false; Boolean late = true; String ret = arriving ? (late ? "도착했지만 늦었네요." : "제시간에 잘 도착했군요.") : (late ? "도착도 못하고 늦었군요." : "도착은 못했지만 늦진 않았군요."); System.out.println(ret); StringBuilder sb = new StringBuilder(); sb.append("appended String"); String str = "just String"; boolean mutable = true; CharSequence chSeq = mutable ? sb : str; System.out.println(chSeq); } private static void checkIntegerSame(Integer ii, Integer jj) { if (ii == jj) { System.out.println("ii = " + ii + ", jj = " + jj + " ==> jj is same ii."); } else { System.out.println("ii = " + ii + ", jj = " + jj + " ==> jj is NOT same ii!!"); } } private static void checkIntegerEquals(Integer ii, Integer jj) { if (ii.equals(jj)) { System.out.println("ii = " + ii + ", jj = " + jj + " ==> jj is equals ii."); } else { System.out.println("ii = " + ii + ", jj = " + jj + " ==> jj is NOT equals ii!!"); } }}
8.10 Method Overload resolution in AutoBoxing #
package com.jeid.tiger;public class OverloadTester { public static void main(String[] args) { double d = 10; Integer ii = new Integer(10); doSomething(10); doSomething(1000); doSomething(ii); doSomething(d); } private static void doSomething(Integer ii) { System.out.println("This is doSomething(Integer)"); } private static void doSomething(double d) { System.out.println("This is doSomething(double)"); }}
8.11 가변적인 argument 개수 ... #
package com.jeid.tiger;public class VarArgsTester { public static void main(String[] args) { setNumbers(1, 2); setNumbers(1, 2, 3, 4); setNumbers(1); // setNumbers(); //해당 되는 method가 없어 compile error!! System.out.println("=============================================="); setNumbers2(1, 2, 3, 4); setNumbers2(1); setNumbers2(); } // this is same setNumbers(int first, int[] others) private static void setNumbers(int first, int... others) { System.out.println("-----------setNumbers()----------- : " + first); for (int i : others) { System.out.println("i = " + i); } } // this is same setNumbers(int[] others) private static void setNumbers2(int... others) { System.out.println("-----------setNumbers2()----------- : " + (others != null && others.length > 0 ? others[0] : "null")); for (int i : others) { System.out.println("i = " + i); } }}
8.12 The Three Standard Annotation #
//정상적인 사용 @Override public int hashCode(){ return toString().hashCode(); } //스펠링이 틀려 compile error!! @Override public int hasCode(){ //misspelled => method does not override a method from its superclass error!! return toString().hashCode(); }
package com.jeid.tiger;public class AnnotationDeprecateTester { public static void main(String[] args){ DeprecatedClass dep = new DeprecatedTester(); dep.doSomething(10); //deprecated }}class DeprecatedClass { @Deprecated public void doSomething(int ii){ //deprecated System.out.println("This is DeprecatedClass's doSomething(int)"); } public void doSomethingElse(int ii){ System.out.println("This is DeprecatedClass's doSomethingElse(int)"); }}class DeprecatedTester extends DeprecatedClass { @Override public void doSomething(int ii){ System.out.println("This is DeprecatedTester's doSomething(int)"); }}
package com.jeid.tiger;import java.util.ArrayList;import java.util.List;public class AnnotationSuppressWarningsTester { @SuppressWarnings({"unchecked", "fallthrough"} ) private static void test1(){ List list = new ArrayList(); list.add("aaaaaa"); } @SuppressWarnings("unchecked") private static void test2(){ List list = new ArrayList(); list.add("aaaaaa"); } //warning이 없는 소스. private static void test3(){ List<String> list = new ArrayList<String>(); list.add("aaaaaa"); }}
8.13 Creating Custom Annotation Types #
package com.jeid.tiger;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Documented@Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation { String columnName(); String methodName() default "";}//사용하는 쪽..public class AnnotationTester { @MyAnnotation(columnName = "test", methodName = "setTest") private String test; @MyAnnotation(columnName = "grpid") public String grpid; ....}//위의 test 멤버의 경우 다음과 같이 접근 가능하다.Field testField = cls.getDeclaredField("test");if (testField.isAnnotationPresent(MyAnnotation.class)) { Annotatioin anno = testField.getAnnotation(MyAnnotation.class); System.out.println(anno.columnName() + ", method = " + anno.methodName());}
9.1 for/in 의 자주 사용되는 형태 #
//1. 가장 단순한 형태인 배열(array)String[] strs = { "aaa", "bbb", "ccc" };for (String str : strs) { System.out.println(str);}//2. List by using IteratorList<Number> lstNum = new LinkedList<Number>();lstNum.add(1);lstNum.add(1.2);for (Iterator<Number> iter = lstNum.iterator(); iter.hasNext();) { Number num = iter.next(); System.out.println("num = " + num);}//3. List를 바로 사용List<String> lst = new LinkedList<String>();lst.add("aaaaa");lst.add("bbbbb");lst.add("ccccc");lst.add("ddddd");for (String str : lst) { System.out.println("str = " + str);}// 4. List of ListList[] lists = { lst, lst };for (List<String> l : lists) { for (String str : l) { System.out.println("str = " + str); }}
10.1 static member/method import #
//예를 들어 System.out.println() 이라는 것을 사용하기 위해서는 다음의 import 문이 필요하다.import java.lang.System; //물론 java.lang 이기에 import 문이 필요없지만 예를 들자면 그렇다는 것이다.&^^//허나, Tiger에서는 다음과 같이 사용할수 있다.import static java.lang.System.out;...out.println(...);// method를 import 한다면..import static java.lang.System.out.println;...println(...);
11 References #
- http://java.sun.com/j2se/1.4.2/docs/index.html
- http://java.sun.com/j2se/1.5.0/docs/index.html
- SUN의 JLS
- http://java.sun.com/docs/books/jls/html/index.html
- Java 핵심원리 - 마에바시 가즈야 저 - 영진닷컴
- Java 1.5 Tiger - Brett McLaughlin 저 - O'Reilly
출처: http://dna.daum.net/technote/java/PrincipleOfJavaInternalForDeveloperEasyToLost
Welcome to Google Doctype. Written by web developers, for web developers.
What do you want to learn today?
Read HOWTO articles on
Dive into DOM objects, including
Style your pages with CSS
- CSS properties
- pseudo-classes and pseudo-elements
- at-rules
- colors
- ...and more on the way
Do you need help with an HTML element? We have an HTML reference from <a> to <xmp>.
------------------------------------------------------------------------------------------
Java는 웹 관련 프레임워크들이 너무 다양하고, Ruby나 Python 같은 경우에는 RubyOnRails나 Djanog 처럼 하나의 프레임워크 안에 기능별 프레임워크들도 모두 다 All in one 형태로 들어 있어서 혼란을 주지 않는 반면, Java는 각 영역별로 프레임워크가 모두 다르고, 또한 각 영역별로 존재하는 프레임워크들의 종류도 많아서 초보 개발자들에게 극심한 혼란을 주고 있다.
그래서 나름대로 Java Web 개발자들을 위한 학습 로드맵을 정리해 보았다.
1. Java 그 자체
많은 웹 개발자들이 마치 JSP 코드를 짤 줄 알면 그걸로 Java 웹 개발을 할 줄아는 것이라 생각하고 Java 그 자체를 소홀히 하는 것을 본다.
말도 안되는 소리이다. Java를 모르고서 Java 웹 개발을 제대로 한다는 것은 어불 성설이다. Java 그 자체를 먼저 공부하라.
특히 Java 5 문법을 숙지하길 권한다. 이제 우리나라도 점차 Java 5가 대세가 되어 가고 있다. 대부분의 프레임워크들과 WAS(JSP와 서블릿을 구동하는 서버)도 모두 Java 5를 기준으로 바뀌었으며, JVM 자체도 버전이 높을 수록 성능이 더 좋다.
2. JSP와 Servlet 그리고 Model 1
모델 1은, JSP 하나에 DB에 접속해서 쿼리를 날리는 등의 모든 업무적인 기능(Business Logic)을 넣고, 그 아래에 HTML 코드를 박아 넣는 식으로 개발하는 것을 의미한다.
아직도 많은 개발자들이 여기에 길들여져 있는데, 일단 JSP 자체에 대한 기본기를 익힌 뒤로는 재빨리 버려야 할 습관이다.
그리고 많은 개발자들이 Servlet을 무시하고 JSP만 하는 것을 보곤 하는데, Servlet에 대한 학습이 제대로 이뤄지지 않으면 더 나은 웹 개발이 곤란하다. Servlet에 대한 기초 개념을 확실히 잡길 권한다.
3. Model 2 - 프레임워크의 등장
JSP로 열심히 개발을 하다보니 프로젝트 규모도 커지기 시작하고, JSP 파일 크기도 수천줄에 달하는등 엄청나게 커진다.
그런데 이 JSP에다 두서없이 모든 기능을 다 때려 넣다보니 JSP마다 똑같은 기능들이 Copy&Paste로 들어가고, JSP 안에 들어 있는 Java 코드들에서 에러가 발생하면 찾아내서 디버깅 하는 일이 지옥같이 느껴지기 시작한다.
여기서 Model 2가 구원자로 등장한다.
Model 2는 말만 멋드러졌지 실제로는 간단한 개념이다.
JSP에서 수행하던 DB 쿼리 등의 작업을 Servlet에게 넘겨주고 JSP에서는 오로지 화면 출력만 담당하는 것이다.
Servlet에서 DB 쿼리등 화면 출력과는 상관없는 비지니스 로직을 일단 먼저 모두 수행하고, 그 결과를 request.setAttribute("key",결과객체);로 담은 다음 JSP 페이지로 포워딩(forward)을 하면 JSP에서는 request.getAttribute("key")로 그 객체를 받아서 화면에 뿌려주기만 한다.
이런 업무 수행단/화면 출력단의 철저한 역할 분리가 Model 2이다.
여기서 이러한 각 역할을 "MVC - Model View Controller" 라고 한다. 그래서 Model 2는 MVC와 동일한 의미로 사용하기 도 한다. MVC의 의미는 공부하면서 찾아보라.
이게 뭐가 좋냐고? 개발 기간이 좀 길어지고 프로젝트 규모가 쬐끔 커지고, 기존 프로젝트를 유지보수를 해보면 얼마나 좋은지 몸소 뼈져리게 느끼게 된다.
Model 2의 기능을 정형화해서 쉽게 구현하게 해주는 것이 MVC Framework들의 역할이다.
가장 유명한 Model 2 웹 프레임워크들은 다음과 같은 것들이 있다.
* 스트럿츠 1 - Struts 1
* 스트럿츠 2 - Struts 2
* 스프링 MVC - Spring MVC
* 기타 덜 유명한 Wicket, Stripes, JSF, Tapestry 등.
Struts 1은 MVC의 효시라고 할 수 있다. 우리에게 MVC라는 축복을 주기는하였으나, 나온지 오래된 만큼 낡은 개념들이 많이 녹아있고 쓸데 없이 복잡하고 배우기도 어려운 편이다.
오히려 Struts 2와 Spring MVC가 더 배우기 쉬울 것이며, 개발도 더 쉽다. 현재 추세는 Struts 2와 Spring MVC이다. 대형 포탈이나 SI 업체들도 Spring/Struts 2를 주로 채택하는 추세로 가고 있는 것으로 알고 있다.
둘 중 하나의 개념만 확실히 이해해도 다른 것을 배우는데 어려움이 별로 없으므로 그냥 둘중에 골라서 배우길 권한다. 나는 Spring을 선호한다.
그리고 MVC 프레임워크를 사용하기 시작하면서 View를 만드는 JSP에 대해서도 재조명이 시작된다. 기존에 Java 코드를 JSP에 직접 넣던 관행을 버리고 JSTL과 태그 라이브러리를 사용하거나 아예 JSP를 버리고 다른 템플릿 엔진으로 만들기도 한다. 이에 관해서는 맨 마지막에.
4. 퍼시스턴스 프레임워크 : JDBC 반복 작업에 짜증이 나기 시작하다.
현대 웹 개발에서 가장 큰 역할을 차지하는 것은 뭐니뭐니해도 단연 Database 작업이다.
지금까지는 아마도 JDBC에서 DB 커넥션을 맺고, 쿼리를 날리고 그 결과 ResultSet을 JSP로 넘겨주어서 출력하는 식으로 했을 것이다.
이미 다들 알고 있겠지만 JDBC를 사용하면 똑같은 코드가 굉장히 많이 반복해서 나온다. 한마디로 "삽질"의 전형이 JDBC 작업이다.
이것을 깨달은 많은 개발자들이 조금 어정짱하게 반복작업을 해결해주는 Util 클래스들을 프로젝트별로 만들어서 사용하곤 한다.
하지만, 물론 이에 대해 정형화하고 깔끔하고 훨씬 더 사용하기 쉬게 만들려는 노력이 이미 수년에 걸쳐 이루어졌다.
이렇게 DB관련된 작업을 정형화한 것들을 Persistence Framework 라고 한다.
* 아이바티스 - iBATIS : SQL Mapper - JDBC보다 더 쉽게 배우고, 더 편하게 사용한다.
* 하이버네이트 - Hibernate : 객체지향을 객체지향답게, 개발 기간을 엄청나게 단축시켜주다.
퍼시스턴스 프레임워크의 양대 산맥은 iBATIS와 Hibernate이다. 이 둘 모두 우리나라에 책이 나와 있다.
iBATIS는 SQL Mapper의 한 종류이고, Hibernate는 ORM의 한 종류이다.
이 둘의 차이는 iBATIS는 개발자가 SQL 쿼리를 직접 작성한 것을 객체에 매핑시켜주는 것이고, ORM은 DB 스키마와 객체간의 관계를 설정파일로 만들면 자동으로 쿼리를 만들어주는 것이다.
자, 이 둘을 보면 미국에서는 Hibernate가 인기가 좋고, 우리나라에서는 iBATIS가 사실상 SI 업계를 평정했다.
그러니까, 일단은 우리나라에서는 iBATIS를 공부하면 된다고 보면 된다.
이렇게 말하니까 마치 이 둘이 경쟁자 같은데, 사실 이 둘은 경쟁 상대라기 보다는 보완해주는 역할을 한다. SI에서 처럼 DB 테이블이 정규화 되어 있지 않은 경우에는 Hibernate같은 ORM을 사용하면 프로젝트를 말아먹을 수 있다.
iBATIS는 테이블 정규화에 무관하게, 개발자가 작성한 SQL을 객체로 매핑하기 때문에 DB 스키마가 마구 꼬여 있는 상황에서도 유연하게 작동하고, 개발자가 직접 SQL 튜닝을 할 수 있다는 장점이다.
그리고 Hibernate는 배우기가 굉장히 어려운 프레임워크이고 튜닝이 매우 어렵다. Hibernate책을 보면 캐싱을 통해 성능을 향상시키라고 하지만 캐싱은 iBATIS도 못지않게 잘 지원한다. 하지만 일단 배우면, 그로인한 코딩 생산성이 iBATIS가 감히 넘볼 수 없을 정도록 급격히 향상된다.
Hibernate는 DB 정규화가 잘되어 있는 웹 포탈 업체나 패키지 소프트웨어 제작시에 강력히 권장할만 하다.
5. IoC와 DI - 객체의 생성주기와 의존성을 관리하고 싶어지다
사실 내가 경험한 SI를 보면 4단계 까지만 가도 막장은 아닌 프로젝트라고 본다. 아직도 신규 프로젝트를 하면서도 Model 1에 JDBC로 코딩하는 것을 많이 보았기 때문이다.
앞서, MVC라는 형태로 웹 애플리케이션의 역할을 철저하게 분할해서 처리하라고 했었다.
이제 여기서 좀 더 역할을 분할하기 시작한다.
Database를 관장하는 코드(DAO)와 Database 처리 결과를 가지고 그외 비지니스 로직을 추가로 수행하는 코드(Service), 그리고 웹으로 들어온 요청을 받아서 비지니스 로직을 호출하고, 그 결과를 다시 웹(HTML 등)으로 내보내는 코드(Controller)로 분할을 하면 유지보수가 더 쉽고, DB가 Oracle에서 DB2 로 변경되는 식의 중대 변화가 있을 때도 DAO만 바꾸면 되는 식으로 변화에 대한 대처가 유연해 진다는 것을 깨닫기 시작한다.
이제는 각 역할별로 클래스를 분할하고 컨트롤러 객체는 서비스 객체에 서비스 객체는 DAO 객체에 의존해서 작동하도록 코드를 바꾸기 시작한다. 그리고 객체의 생성과 파괴 주기도 관리해야만 하게 된다. 객체를 하나만 생성하면 되는데 불필요하게 매번 new를 할 필요는 없으니까.
이렇게 객체의 생성/파괴 주기를 관리하고 객체간의 의존성을 관리해주는 프레임워크를 IoC 컨테이너라고 부른다.
1. Spring Framework
2. EJB 3.0
사실상 대세는 Spring Framework로 굳어졌다. EJB 3.0은 내가 안써봐서 뭐라 말은 못하겠다.
Spring MVC는 이 Spring Framework의 일부분이다.
Spring은 또한 AOP도 지원한다.
AOP 의 개념이 상당히 어려운 편이라서 개념 자체를 확실히 한마디로는 표현하지 못하겠다. 어쨌든 개발자들에게 가장 쉽게 다가오는 표현으로 하자면, AOP는 동일한 패턴으로 반복적으로 해야하는 일을 설정을 통해 자동으로 해주는 것이다.
이에 관한 가장 보편적인 예가 바로 트랜잭션이다.
지금까지는 아마도 비지니스 로직이 시작될 때 트랜잭션이 시작되고, 비지니스 로직이 끝날 때 트랜잭션을 종료하는 코드를 매번 작성해서 넣었을 것이다.
AOP를 사용하면, 비지니스 로직의 역할을 하는 메소드가 무엇인지 설정파일에 넣어주기만 하면 자동으로 메소드가 시작될 때 트랜잭션을 시작시키고, 메소드가 끝날 때 트랜잭션을 종료시켜준다. 물론 예외가 발생하면 트랜잭션을 rollback도 해준다. 따라서 Spring을 사용한 프로젝트에서는 트랜잭션 관련 코드를 볼 수 없을 것이다.
Spring 프레임워크는 기본적으로 IoC 컨테이너 역할을 하는 것이 핵심이다. 따라서 Spring을 사용한다고 해서 꼭 Spring MVC를 사용할 필요는 없다. Struts 2 + Spring + iBATIS 나 SpringMVC + Spring + Hibernate 등... 어떠한 조합이라도 가능하다.
6. 그 외
◈ Template Engine : JSP 보다 더 간결하면서 강력한게 필요해!
* JSP + JSTL : Sun이 지정한 산업표준이다. JSTL은 당연히 쓰고 있으리라 믿는다.
* Freemarker : 가장 권장할 만하다.
* Velocity : 굉장히 배우기 쉽다. JSTL보다 더 빨리 배워서 쓸 수 있다. 가독성도 좋다. 그러나 Freemarker 만큼 편하고 강력하지는 못하다.
많은 사람들이 Java 웹 개발을 그냥 "JSP 개발"이라고도 부르는데, MVC가 도입되고, Freemarker 같은 다른 템플릿 엔진을 사용하게 되면 더이상 JSP는 코빼기도 안보이게 된다. 그러므로.. JSP 개발이라는 말은 쓰지 않았으면 좋겠다.
◈ Layout Engine
* Sitemesh : 헤더 푸터 처럼 동일 패턴이 반복되는 레이아웃을 관리해준다.
◈ XML 도우미 : W3C DOM은 너무 어렵고 난잡하다. 좀 더 편한 XML관련 개발을 원한다면..
* JDOM : Java 표준으로 지정됐다고 한다.
* DOM4J
둘 다 비슷하게 편한거 같다. 예전엔 JDOM을 썼었는데, 나 같은 경우 현재 프로젝트에서는 DOM4J를 사용한다. Hibernate가 DOM4J를 사용하기 때문에, 별도의 라이브러리 더 넣는게 귀찮아서.
◈ 단위 테스트
* jUnit : 코드를 철저하게 테스트하자.
◈ 소스코드 버전관리
* CVS
* Subversion : 현재 대세는 Subversion
내가 최고 막장으로 꼽는 프로젝트는 아직도 FTP로 소스 관리하는 프로젝트이다. 이런 프로젝트에는 절대로 참여하지 않을 것이라고 굳게 맹세하고 또 맹세했다. --;
소스 코드 버전관리는 여러 개발자들이 동시에 개발할 때 소스코드를 저장하고 충돌을 관리해주며, 소스 변경 내역을 계속해서 추적해서 과거 소스로 언제든지 돌아갈 수 있도록 도와준다.
현재 대세는 Subversion이지만 CVS로도 버전관리의 이점을 충분히 만끽할 수 있다. 그리고.. 사실 CVS가 사용법을 익히기는 더 쉽다.
◈ 자동 빌드
* Ant : Ant 면 만사 Ok!
* Maven
아직도 javac 로 컴파일하고 있고, FTP로 파일 올려서 복사하고 있다면.. 이 모든일을 자동으로 명령 한방에 처리하도록 해야 실수도 적고, 퇴근도 일찍한다.
Ant로 빌드와 배포를 자동화 하자.
결론
내가 권하는 조합은
* SI 업체에서 일하는 경우 : Struts 2 혹은 SpringMVC + iBATIS + JSP/JSTL + 가능하다면 Spring Framework
* 웹 포털등과 같은 업계, 패키지 소프트웨어 제작 업체 : Struts 2 혹은 Spring MVC + Hibernate + Spring Framework + Freemarker + Sitemesh
어제 제가 개발한 시스템에 대해 윗분과 이야기 하는데
총 코딩 파일 라인수가 몇줄이냐고 물어보시는데 -_-;;
몰라서 당황했다는;; 전 나중에 산출물 작성할때나 알아볼까 했는데 흠.
암튼 이클립스에 라인수 측정하는 곳이 안보여서
예전에 만들어뒀던 소스 이용하여 약간 발전시켜 만들어 봤습니다.
이클립스에 이미 있는 기능이라면 저 또 뻘짓한 것이지만서도 ㅎㅎㅎ
뭐 공부용으로도 함 봐보셔도 괜찮을듯 싶습니다.
- Finder.java
/*
* @Finder.java Created on 2006. 08. 24
*
* Copyright (c) 2005 GHLab.com All rights reserved.
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Locale;
/**
* 파일 총 라인수 구하기.
*
* @version 1.0
* @author 김건호
*/
class Finder {
public static long totalFileSize = 0; // 전체 파일 사이즈 저장
public long fileSize = 0; // 파일 사이즈 저장
public static int totalFileLineCount = 0;
public int fileLineCount = 0;
// 파일 정보 저장
public ArrayList<FileDTO> fileList = new ArrayList<FileDTO>();
public final static int TOTAL_FIND_CODE = 0; // 전체 검색 코드
public final static int FILENAME_FIND_CODE = 1; // 파일명 검색 코드
public final static int EXTENSION_FIND_CODE = 2; // 확장자 검색 코드
public int findTypeCode = TOTAL_FIND_CODE; // 검색 코드
// 검색 파일명
public String findFileName = "*.*";
// 하위디렉토리 검색 여부
public boolean isFindUnderDir = false;
// 대소문자 구분
public boolean isUpperLower = false;
public static void main(String[] args) {
if (args.length == 0 || args.length > 3) {
StringBuffer sb = new StringBuffer();
sb
.append("사용법을 갈켜드리겠습니다~\n")
.append(
"예) Windows 폴더 내의 모든 파일의 용량 및 라인수를 추출하고 싶다면 아래처럼~\n\n")
.append("java Finder c:\\windows\n\n")
.append("파일을 지정하고 싶다면(기본 전체 파일 검색) 아래와 같은 옵션을 붙이면 됩니다.\n")
.append("확장자 지정 검색 -e, 파일 지정 검색 : -f\n")
.append("예) Windows 폴더 내의 확장자가 exe 인 파일을 검색\n\n")
.append("java Finder c:\\windows -e exe\n\n")
.append("하위 폴더를 포함하여 검색하고 싶다면 s 옵션을 붙이면 됩니다.\n")
.append(
"예) Windows 폴더와 하위 폴더의 모든 파일 중 파일명이 notepad.exe인 파일을 검색\n\n")
.append("java Finder c:\\windows -sf notepad.exe\n\n")
.append("파일명을 대소문자 구분하여 검색하려면 u 옵션을 붙이면 됩니다.\n")
.append(
"예) Windows 폴더와 하위 폴더의 모든 파일 중 확장자가 exe인 파일을 검색\n\n")
.append("java Finder c:\\windows -sue exe");
System.out.println(sb.toString());
System.exit(1);
}
Finder f = new Finder();
// 검색 경로
String path = null;
// 옵션
String option = "";
if (args.length > 0)
path = args[0]; // 검색 경로 저장
// 인자 갯수에 따른 분류
if (args.length > 1) {
// 옵션 저장
option = args[1];
// 검색 파일명 또는 확장자 저장
f.findFileName = args[2];
}
// 옵션에 의한 데이터 셋팅
if (option.indexOf("s") != -1)
f.isFindUnderDir = true;
// 대소문자 구분하지 않을 경우
if (option.indexOf("u") != -1)
f.isUpperLower = true;
// 확장자 검색일 경우
if (option.indexOf("e") != -1)
f.findTypeCode = Finder.EXTENSION_FIND_CODE;
// 파일명 검색일 경우
if (option.indexOf("f") != -1)
f.findTypeCode = Finder.FILENAME_FIND_CODE;
// 확장자 검색과 파일명 검색은 함께 쓸수 없다.
if (option.indexOf("e") != -1 && option.indexOf("f") != -1)
System.out
.println("확장자 검색과 파일명 검색 옵션 모두 입력하셨습니다.\n파일명 검색 모드로 자동 설정됩니다.");
// 디렉토리 존재 여부
File file = new File(path);
if (file.isDirectory() == false) {
System.out.println("정확한 경로를 입력하여 주십시오.");
System.exit(1);
}
// 디렉토리 끝에 \ 또는 / 이 없으면 붙임
String lastChar = path.substring(path.length() - 1, path.length());
if (lastChar.equals(File.separator) == false) {
path = path + File.separator;
}
try {
f.getSize(path);
} catch (Exception e) {
System.out.println("에러!! : " + e.getMessage());
e.printStackTrace();
}
System.out.println("검색된 파일 갯수 : " + f.fileList.size());
// 검색된 파일 갯수가 있을 경우에 정보 출력
if (f.fileList.size() > 0) {
System.out.println("총 파일 사이즈 : " + byteTranslater(totalFileSize));
System.out.println("총 라인수 : " + totalFileLineCount + "라인");
System.out.print("검색된 파일 정보를 보시겠습니까?(Y/N) : ");
String choice = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
System.in));
choice = in.readLine();
} catch (Exception e) {
choice = "N";
}
choice = choice.toUpperCase();
if (choice.equals("Y")) {
// 파일 정보 추출
FileDTO[] fdto = f.getFileList();
for (int i = 0; i < fdto.length; i++) {
System.out.println("파일 : " + fdto[i].getFilePath()
+ fdto[i].getFileName() + ", 사이즈 : "
+ byteTranslater(fdto[i].getFileSize())
+ ", 라인수 : " + fdto[i].getFileLineCount());
}
}
}
System.exit(1);
}
/**
* 해당 경로에서 파일을 찾아 용량, 라인수를 측정
*
* @param path
* 파일을 찾을 경로
* @param findFileName
* 모든 파일 찾기(*.*), 확장자로 찾기(*.java), 파일명 찾기(test.java)
* @param isFindUnderDir
* 하위디렉토리 검색 여부
* @throws Exception
*/
public void getSize(String path) throws Exception {
File dir = new File(path);
String[] list = dir.list();
File file;
BufferedReader br = null;
String fileName = null; // 파일명 저장
String filePath = null; // 파일 경로
String findFileName = this.findFileName;
for (int i = 0; i < list.length; i++) {
file = new File(path + list[i]);
fileSize = 0; // 해당 파일 크기 0으로 초기화
fileLineCount = 0; // 해당 파일 총 라인수 0으로 초기화
// 파일만 계산
if (file.isFile()) {
fileName = file.getName(); // 파일명 추출
// 대소문자 구분 하지 않는다면 모두 대문자로 변경
if (this.isUpperLower == false) {
fileName = fileName.toUpperCase(Locale.KOREAN);
findFileName = findFileName.toUpperCase(Locale.KOREAN);
}
filePath = file.getPath(); // 파일경로 추출
// 검색 형태에 따른 조건 설정
if ((findTypeCode == TOTAL_FIND_CODE)
|| (findTypeCode == EXTENSION_FIND_CODE && fileName
.substring(fileName.lastIndexOf(".") + 1,
fileName.length()).equals(findFileName))
|| (findTypeCode == FILENAME_FIND_CODE && fileName
.equals(findFileName))) {
br = new BufferedReader(new InputStreamReader(
new FileInputStream(filePath)));
// 라인수 추출
while (br.readLine() != null) {
fileLineCount++;
}
fileSize = file.length(); // 파일 크기 추출
FileDTO fdto = new FileDTO();
fdto.setFileSize(fileSize);
fdto.setFileName(file.getName());
fdto.setFilePath(filePath.substring(0, filePath
.lastIndexOf(File.separator) + 1));
fdto.setFileLineCount(fileLineCount);
fileList.add(fdto);
}
}
// 해당 폴더내의 모든 파일의 크기 추출을 위한 연산
totalFileSize += fileSize;
// 해당 폴더내의 모든 파일의 라인수 추출을 위한 연산
totalFileLineCount += fileLineCount;
// 하위 디렉토리가 있고, 옵션을 하위 디렉토리 검색을 지정했을 경우 재귀호출
if (file.isDirectory() && isFindUnderDir)
getSize(file.getPath() + File.separator);
}
}
/**
* ArrayList 에 담겨진 파일 정보 DTO를 배열로 전환하여 받아옴
*
* @return 파일 정보 목록
*/
public FileDTO[] getFileList() {
FileDTO[] result = new FileDTO[fileList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = new FileDTO();
result[i] = fileList.get(i);
}
return result;
}
/**
* 파일 사이즈 단위 변환
*
* @param size
* long 형 타입의 파일 사이즈
* @return KB, MB, GB 로 변환한 사이즈
*/
public static String byteTranslater(long size) {
NumberFormat nf = NumberFormat.getIntegerInstance();
java.text.DecimalFormat df = new java.text.DecimalFormat("#,##0.00");
int intSize = 0;
int kbyteSize = 1024;
double doubleSize = 0;
String returnSize = null;
// 파일 사이즈가 1000, 2000 형식이므로 기가는 1024 가 아닌 1000을 기준으로.
if (size >= (1000 * 1024 * 1024)) {
intSize = new Long(size / (1000 * 1024 * 1024)).intValue();
return nf.format(intSize) + "GB";
} else if (size > (kbyteSize * 1024)) {
intSize = (int) (((double) size) / ((double) (kbyteSize * 1024)) * 100);
doubleSize = (double) (((double) intSize) / 100);
returnSize = df.format(doubleSize);
if (returnSize.lastIndexOf(".") != -1) {
if ("00".equals(returnSize.substring(returnSize.length() - 2,
returnSize.length()))) {
returnSize = returnSize.substring(0, returnSize
.lastIndexOf("."));
}
}
return returnSize + "MB";
} else if (size > kbyteSize) {
intSize = new Long(size / kbyteSize).intValue();
return nf.format(intSize) + "KB";
} else {
// return nf.format(size) + "Byte";
return "1KB";
}
}
}
/**
* 파일 정보 저장 객체
*
* @version 1.0
* @author 김건호
*/
class FileDTO {
public int fileLineCount;
private long fileSize;
private String filePath;
private String fileName;
public FileDTO() {
fileSize = 0;
filePath = null;
}
/**
* @return the fileLineCount
*/
public int getFileLineCount() {
return fileLineCount;
}
/**
* @param fileLineCount
* the fileLineCount to set
*/
public void setFileLineCount(int fileLineCount) {
this.fileLineCount = fileLineCount;
}
/**
* @return the fileName
*/
public String getFileName() {
return fileName;
}
/**
* @param fileName
* the fileName to set
*/
public void setFileName(String fileName) {
this.fileName = fileName;
}
/**
* @return the filePath
*/
public String getFilePath() {
return filePath;
}
/**
* @param filePath
* the filePath to set
*/
public void setFilePath(String filePath) {
this.filePath = filePath;
}
/**
* @return the fileSize
*/
public long getFileSize() {
return fileSize;
}
/**
* @param fileSize
* the fileSize to set
*/
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
}
[출처] 파일 검색 및 총 라인수 구하기|작성자 건호랩
Other mirror sites are suggested below. Please use the backup mirrors only to download PGP and MD5 signatures to verify your downloads or if no other mirrors are working.
HTTP
FTP
Backup Sites
http://www.apache.org/dist/
http://www.eu.apache.org/dist/
The full listing of mirror sites is also available. The procedure for setting up new mirrors is described in How to become a mirror.
Verify the integrity of the files
It is essential that you verify the integrity of the downloaded files using the PGP or MD5 signatures. Please read Verifying Apache Software Foundation Releases for more information on why you should verify our releases.
The PGP signatures can be verified using PGP or GPG. First download the KEYS
as well as the asc
signature file for the relevant distribution. Make sure you get these files from the main distribution site, rather than from a mirror. Then verify the signatures using
% pgpk -a KEYS
or
% pgpv downloaded_file.asc% pgp -ka KEYS
or
% pgp downloaded_file.asc% gpg --import KEYS
% gpg --verify downloaded_file.asc
Alternatively, you can verify the MD5 signature on the files. A unix program called md5
or md5sum
is included in many unix distributions. It is also available as part of GNU Textutils. Windows users can get binary md5 programs from here, here, or here.
자바스크립트는 웹에서 사용하는 스크립트 언어 입니다!
자바스크립트는 수만 개의 웹 페이지에서 디자인을 향상 시키고, 폼을 검증하고, 브라우저를 인식하고, 쿠키를 생성하는데 사용하고 있습니다.
자바스크립트는 인터넷에서 가장 유명한 스크립트 언어입니다.
자바스크립트는 배우기 쉬워요! 즐겨보세요!
JS HOME(Whiteship's Note)
JS Introduction(Introduction to JavaScript)
JS How To(JavaScript How To ...)
JS Where To(JavaScript Where To ...)
JS Variables(JavaScript Variables)
JS If...Else(JavaScript If...Else와 Switch Statement)
JS Switch
JS Operators(JavaScript Operators)
JS Popup Boxes(JavaScript Popup Boxes)
JS Functions(JavaScript Functions)
JS For Loop(JavaScript For Loop와 While Loop)
JS While Loop
JS Break Loops
JS For...In
JS Events(JavaScript Events)
JS Try...Catch(JavaScript Try...Catch Statement)
JS Throw(JavaScript Throw Statement)
JS onerror(JavaScript The onerror Event)
JS Special Text(JavaScript Special Characters)
JS Guidelines(JavaScript Guidelines)
JS Objects
JS Objects Intro(JavaScript Objects Introduction)
JS String(avaScript String Object)
JS Date(JavaScript Date Object)
JS Array(JavaScript Array Object)
JS Boolean(JavaScript Boolean Object)
JS Math(JavaScript Math Object)
JS HTML DOM(JavaScript HTML DOM Objects)
JS Advanced
JS Browser(JavaScript Browser Detection)
JS Cookies(JavaScript Cookies)
JS Validation(JavaScript Form Validation)
JS Animation(JavaScript Animation)
JS Image Maps
JS Timing(JavaScript Timing Events)
JS Create Object(JavaScript Create Your Own Objects)
JS Summary
Object와 Advanced 부분은 거의 번역을 했습니다.
전부 살표보신 분들은 재미삼아 퀴즈도 보실 수 있습니다.
물론 다 보지 않고도 퀴즈만 볼 수도 있지요.ㅋ
문제 난이도는 매우 쉬운데(20문제 푸는데 3분 10초면..그냥 찍기 수준입니다.ㅋㅋ).. 저는 두 문제를 틀려버렸어요;;
출처 : http://whiteship.me/1004
anyframe(http://www.anyframejava.org)의 등장..
옆에서 기자분이 열심히 어디론가 전화를 하고 있다.
그런데 spring이 나오고 오픈 소스가 나온다..
그러더니 기사가 나오기 시작했다.
http://www.zdnet.co.kr/news/enterprise/si/0,39031197,39169880,00.htm
http://www.zdnet.co.kr/news/enterprise/si/0,39031197,39169940,00.htm
http://www.zdnet.co.kr/news/enterprise/si/0,39031197,39168226,00.htm
왠지 반가운 느낌이 더 많이 든다.
앞으로 SI들이 통일된 프레임웍을 통해서 개발될 확률이 많아 졌고,
그리고 오픈 소스라는 점에서 이 프레임웍이 많은 발전을 이룰것이며,,
또한 삼성 SDS 라는 점도 이를 더 뒷받침하지 않을까 한다.
이 프레임웍은 스프링을 기반으로 하기에 왠지 더 정감이 간당..ㅋㅋ (요즘 열공중..)
물론 앞으로 좀 더 지켜봐야겠지만...
이런 시도들이 좀 더 나왔으면 한다.
출처 : http://rrwr.tistory.com/76?srchid=BR1http%3A%2F%2Frrwr.tistory.com%2F76
cclskin.net |
start.com |
del.icio.us |
craigslist: san francisco bay area classifieds for jobs, apartments, personals, for sale, services, community, and events |
Rollyo: Roll Your Own Search Engine |
TechCrunch |
Etsy - Your place to buy and sell all things handmade |
Protopage v2 released - free AJAX start pages now with RSS news feeds, sticky notes and bookmarks |
meebo.com |
Windows Live Local |
43 Things |
Where do you want to go? | 43 Places |
Welcome to Flickr - Photo Sharing |
CEITON technologies |
야후! 허브 - 태그로 세상을 담는다! |
Kiko - A New Kind of Online Calendar |
Netvibes |
TagWorld |
Google Base |
Windows Live |
Google Local |
Google Maps API |
BlinkList | Your personal start page and social bookmarking engine |
Google Transit |
Ning | Home: Front Page |
smugmug - The ultimate in photo sharing. Online photo albums, photo sharing, photo hosting and photo storage. |
YouTube - Broadcast Yourself. |
?
Social Bookmarking/Search/Invitation:
Simpy
Goovite
Furl
Spurl
Rollyo
Squidoo
StumbleUpon
RawSugar
Kopikol
SurfTail
Content Filtering
Techtiki
ScoopGo
Filangy
To Do Lists
GooTodo
Listal
Online Calendars
HipCal
AirSet
zEvents
EventSniper
Web Site/Blog Analytics:
Measure Map
Google Analytics
Peer Production Content (News/Music/Listings)
Shoutwire
Millions of Games
Rojo
Last.fm
Pandora
WikiCompany
Glypho
Yazai
BlockRocker
Wists
SpinSpy
NowPublic
Odeo
WebJay
180 Degree News
Quimble
Riffs
ButterFly
Bandnews
Mash-Ups
Ning
FlickrMap
LivePlasma
CoverPop
Qube
Kayak
toEat
AlexaDex
Aggregators
Google Reader
SuprGlu
PBwiki
Attensa
fluctu8
NewsMob
Blummy
Fluxiom
MeFeedia
Start Pages
PageFlakes
Google Ig
Team Planning, Organization, Coordination, & Project Management
Planzo
Backpack
Zimbra
ProjectPlace
Doodle
ZohoPlanner
E-Mail and Communication
Meebo
GMail
myemail
Tempinbox
Citadel
Online Storage
Avvenu
SendSpace
eSnips
StreamLoad
Image Storage, Search, & Sharing
Fotolia
iStockPhoto
Riya
PhotoBucket
Mapping
Google Maps
Yahoo! Maps
MSN Maps
Wayfaring
Word Processing & Note Taking
JotSpot Live
Webnote
Web 2.0 Parts
TinyMCE
RSS2PDF
ZohoChallenge
Grassroots Web 2.0
Knowmore.org
Online Business Software
2ndSite
NetWorthIQ
ThinkFree
CampaignMonitor
Web 2.0 Social Communities
MySpace
Orkut
LinkedIn
Web 2.0 Command Line
YubNub
Ambedo
Web 2.0 Humor
Web 2.0 Validator
?
?
?
부록2. 시맨틱웹(웹2.0) 관련 사이트
시맨틱웹 또는 웹2.0을 좀더 잘 이해하려면 관련 사이트를 직접 둘러보는 것이 좋다. 이 책에서 미처 소개하지 못한 곳을 포함해 관련 사이트를 정리해봤다. 시간이 나는대로 차례대로 방문해보거나 검색엔진을 통해 아래 소개된 사이트에 대한 정보를 찾아보기 바란다.
(2006.01.25 최종 수정. 사이트 주소는 수시로 바뀝니다.)
43things(www.43things.com) : 꼬리표 기술을 적극 활용하는 소셜 네트워크 기반의 블로그 커뮤니티
A9(www.a9.com) : 아마존의 검색엔진으로 Ajax를 도입한 것이 특징이다. 일단 일반 검색이 아닌 전자상거래 검색 분야로 좁혀 전문적인 검색시장부터 노리고 있다.
Browsr : social directory manager 사이트. 쉽게 설명하자면 웹사이트를 주제별로 구분했던 야후 디렉토리 서비스를 사용자들이 구분하는 사이트다. 사회적책갈피(소셜북마크)의 한 종류로 볼 수 있는데, 각종 사이트 링크를 사용자들이 평가하고 분류한다는 점이 특징이다. 물론 꼬리표 적용은 필수.
BudgetTracker(http://budgettracker.com/login.php) : 무료로 사용할 수 있는 웹 회계, 일정관리 서비스.
Bunchball(www.bunchball.com) : 플래시 기반의 온라인 게임 서비스. 개발자들이 직접 게임 개발에 참여할 수 있는 것이 특징이다.
DrawSWF(http://drawswf.sourceforge.net/) : 웹 상에서 그림을 그릴 수 있다. Java2를 이용한 것이 특징이며 SVG 형식을 활용해 그린 그림을 플래시 애니메이션 파일로 저장할 수 있는 점이 독특하다.
Flock(www.flock.com) : 불여우 기반의 오픈소스 소셜 브라우저 공식 사이트. 즐겨찾기, 방문기록, 블로깅 등의 활동을 브라우저 차원에서 제공해준다.
?
JotSpot(www.jotspot.com) : 개인용 위키 응용프로그램 제공 사이트
KnowNow(www.knownow.com) : RSS 알리미(alert) 시스템 사이트로 기업에서 필요한 정보를 모아서 제공하는 솔류션을 발표했다.
MS 라이브로컬(http://local.live.com) : 미국 주요 지역의 정밀항공사진 지도서비스를 포함한 지역정보 종합서비스
MS 라이브닷컴(www.live.com) : 마이크로소프트가 선보인 라이브 소프트웨어를 제공하는 사이트
MS 스타트닷컴(www.start.com) : 마이크로소프트의 개인화 서비스 사이트
MSN 버추얼 어스(virtualearth.msn.com) : 마이크로소프트의 위성지도 서비스
MSN 샌드박스(sandbox.msn.com) : 마이크로소프트가 진행 중인 프로젝트를 보여주는 사이트
MusicBrainz(http://musicbrainz.org) : 음악 관련 자료를 RDF 문법을 이용해 제공하는 사이트
Oddpost(www.oddpost.com) : 웹기반 이메일 업체로 DHTML을 이용하여 브라우저에서 아웃룩과 거의 같은 인터페이스를 구현하여 주목받은 회사. 야후가 인수했다.
Orb(www.orb.com) : 웹과 연동해 동영상 사진 화상캠 등을 통해 집안을 관리하거나 각종 알리미 기능을 이용할 수 있는 홈관리 시스템 사이트.
Podscope(www.podscope.com) : 파드캐스팅 자료를 검색해주는 검색엔진으로 숨은자료(meta data)를 활용한 검색엔진이라는 특징이 있다.
Pubsub(www.pubsub.com) : RSS와 블로그 전문 검색엔진. 구조화된 블로깅(Structured Blogging) 기술을 선보였다.
Real Travel(http://realtravel.com/) : 여행을 주제로 한 소셜 네트워크. 블로그 형식과 지도 연계 정보가 특징이다.
Rico(www.openrico.org) : 자바스크립트를 이용한 RIA기술 사이트. Ajax 기술을 사용한 개발 사이트.
SAGE(sage.mozdev.org) : 불여우 브라우저의 탭브라우징 기능과 접목해 사용하는 불여우 브라우저용 RSS 구독기 확장기능 사이트
W3C(www.w3.org) : 웹표준을 만들고 웹을 주관하는 공식기관. 시맨틱웹에 관한 자료도 이곳에 있다.
ZDNET RSS 공급 페이지(http://www.zdnet.co.kr/etc/feeds/xml/) : 다양한 형식의 RSS를 주제별로 제공해주고 있는 사례를 볼 수 있다.
Zvents(www.zvents.com) : 지역의 각종 행사(이벤트) 검색 서비스. 현재 샌프란시스코 지역의 행사를 검색해주며, 구글맵과 연동되어 장소를 소개한다.
개버(http://www.gabbr.com/) : 사용자가 덧글을 다는 것을 주요 특징으로 내세우는 뉴스 사이트. 덧글 수가 대문의 주요 뉴스에 표시됨으로써 사용자들의 관심도를 측정할 수 있다.
구글 개인화 홈페이지(http://www.google.co.kr/ig) : 구글의 개인화 홈페이지 사이트. 아작스를 도입해 옮기려는 영역을 마우스로 끌어다놓으면 원하는 위치로 바로 재배치되는 것을 볼 수 있다.
구글 라이드파인더(http://labs.google.com/ridefinder) : 구글의 Ride Finder는 검색 지역의 수송수단을 찾아주는 로컬 서비스로, 지도 서비스와 연동되는 서비스다.
구글 리더(http://www.google.com/reader/) : 구글의 RSS 웹구독 서비스. 지메일과 비슷한 화면을 가지고 있으며 검색과 연동된 점이 특징이다.
구글 베이스(http://base.google.com) : 구글이 내놓은 무료 알맹이(content) 검색 서비스
구글 비디오검색(http://video.google.com/) : 구글의 멀티미디어 검색 서비스
구글 야후 교통 날씨 지도(traffic.poly9.com) : '구글맵 + 야후 교통정보 + 월드웨더(worldweather) 날씨정보'를 결합하여 지도를 통해 교통상황과 날씨를 함께 확인할 수 있는 서비스. 그레그 새더츠키(Greg Sadetsky)가 개발했다.
구글 오컷(www.orkut.com) : 사회적 네트워크(Social Network)의 대명사처럼 인식되는 사이트로 평판 시스템과 검색 기능이 특징이다.
구글 지메일(www.gmail.com) : 구글의 웹메일 서비스. 기존의 폴더 방식이 아닌 레이블(lable, 찌종이) 방식으로 편지를 관리하고 있으며 아작스 등을 도입한 점, 2기가바이트가 넘는 용량이 특징이다.
구글 트랜지트 여행 플래너(Google Transit Trip Planner, http://www.google.com/transit) : 구글이 선보인 교통 안내 서비스. 미국 포틀랜드(Portland) 지역에 한정적으로 공개되었다.
구글(www.google.com) : 상장 1년 만에 미국 20대 기업에 들고 100조가 넘는 기업으로 성장한 세계 최고의 검색엔진 기업. 웹2.0 기술을 가장 잘 활용하는 곳이다.
구글 어스(Google Earth, http://earth.google.com) : 구글의 위성지도 서비스
구글 지도(http://maps.google.com/) : 아작스를 도입한 구글의 지도 서비스 사이트
그리스몽키(Greasemonkey, http://greasemonkey.mozdev.org/) : 아론 부드맨이 2004년 12월에 친구를 위해 개발한 불여우 브라우저용 확장 기능의 하나로 자신이 보는 페이지를 재정의해서 볼 수 있다.
나우퍼블릭(http://www.nowpublic.com/) : 사용자들이 기사를 작성할 수 있는 뉴스 사이트로 꼬리표를 적용하고 있다.
넘섬(http://www.numsum.com) : Ajax로 구현한 웹스프레드시트 사이트.
넷바이브스(http://www.netvibes.com/) : Ajax로 구현한 개인이 설정할 수 있는 개인화 페이지.
넷플릭스(www.netflix.com) : 미국의 DVD 대여 사이트로 아작스를 도입해 마우스를 올려놓기만 해도 상자가 뜨면서 DVD 요약 내용이 나온다.
뉴스게이터(www.newsgator.com) : 사용자가 좋아하는 뉴스, 사이트, 블로그를 한 자리에서 볼 수 있게 해주는 서비스. 아웃룩이나 피드데몬을 이용할 수도 있다.
다음 RSS넷(rss.daum.net) : 국내 포탈로는 처음 선보인 RSS웹구독기.
닷지볼(www.dodgeball.com) : 휴대전화 소셜 네트워킹 애플리케이션. 구글이 인수했다.
델리셔스(http://del.icio.us) : 조슈아 샤흐터(Joshua Schachter)가 만든 소셜 북마크 공유 서비스. 웹2.0 시대에 플릭커와 함께 양대 스타로 떠오른 사이트로 야후에 인수되었다. 30만 사용자들이 1000만개 즐겨찾기(북마크)를 공유했다.
디그(www.digg.com) : 슬래시(slashdot.org)와 같은 뉴스 포럼 사이트. 2006년 초부터 슬래시의 트래픽을 따라잡을만큼 급성장했다. 슬래시는 편집진에 의해 주제가 선정되지만 디그는 사용자의 투표(digg it)를 통해 선정되는 점이 다르다. 네티즌의 자발적 참여가 성장에 어떤 역할을 하는지 보여주는 사례.
라에드는 어디에(http://dear_raed.blogspot.com) : 블로그의 매체성을 가장 잘 보여준 살람팍스의 블로그
라이브마크스(http://sandbox.sourcelabs.com/livemarks/) : Ajax로 구현한, 델리셔스(del.icio.us)의 새로 추가된 북마크 실시간 보기 사이트.
라이트리(www.writely.com) : 웹 기반의 워드프로세서. 웹에서 문서를 작성한 후 컴퓨터에 Word, HTML, ZIP 형식으로 저장할 수 있고 공유도 가능한 점이 특징이다. 어디서나 사용할 수 있다는 점 때문에 최근 주목받는 사이트.
로조닷컴(www.rojo.com) : 블로그라인스와 같은 웹 기반의 RSS 구독기. 포크소노미 기술로 꼬리표에 가중치를 부여해 구성원들이 체계화시키고 있다.
롤요(www.rollyo.com) : 사용자가 원하는 사이트를 묶어두면 해당 사이트만을 대상으로 검색해주는 개인화 검색엔진. 데이브 펠이 만들었다.
리멤버더밀크(http://www.rememberthemilk.com) : Ajax를 적용한 할일 목록 관리 사이트. 메신저로 수신이 가능한 점이 특징이다.
리야닷컴(http://riya.com) : 인공지능 사진 검색엔진
마요미(www.mayomi.com) : 브라우저 상에서 사용 가능한 웹 마인드맵 서비스.
마이스페이스(www.myspace.com) : 미국 10대들이 주로 사용하는 커뮤니티 사이트
마이웹2.0(http://myweb.yahoo.com) : 야후가 내세우는 소셜 검색엔진(social search engine)
모든블로그(www.modenblog.com) : 휴대전화를 이용해 RSS를 구독할 수 있는 한국 사이트
모질라(www.mozilla.org) : 불여우(Firefox) 브라우저와 천둥새 편지 프로그램을 등을 배포하는 사이트. 오픈소스와 플랫폼 기반의 프로그램 흐름을 파악할 수 있다.
미보(http://www.meebo.com) : Ajax로 구현한 웹메신저. 당연히 프로그램 설치 없이 웹에서 바로 사용할 수 있는 메신저다. MSN 메신저 외에 야후, ICQ, 구글토크 등과도 연결된다.
믹시(www.mixi.co.jp) : 일본의 사회적 네트워크 사이트로 한국의 싸이월드와 구글을 섞은 것 같은 사이트다.
백베이스(www.backbase.com) : 아작스 기반의 응용 프로그램 개발 사이트
보잉보잉(http://boingboing.net) : 해외의 블로그 사이트. 방문객들의 불여우 브라우저 사용자가 IE 사용자를 추월하는 일이 나타나 화제를 모았다.
블로거닷컴(www.blogger.com) : 가입형 블로그 서비스. 구글이 인수했다.
블로그라인스(www.bloglines.com) : 전문 RSS웹서비스로 가장 유명한 곳. 해외 사이트지만 사용하기 편리하다는 이유로 한국 네티즌도 많이 사용한다. 애스크지브스에 인수된 후 IAC로 넘어갔다.
블로그펄스(www.blogpulse.com) : 블로그 검색엔진
샤프리더(www.sharpreader.net) : RSS구독기인 샤프리더 배포 사이트
세이바로직(www.ceiva.com) : 디지털액자 판매 기업으로 가족들이 사진을 인터넷에 올려놓기만 하면 다음 날 액자를 통해 새롭게 올라온 가족사진을 감상할 수 있는 서비스를 제공한다.
소셜텍스트(www.socialtext.com) : 기업용 위키 제품 사이트
스카이프(www.skype.com) : VoIP 서비스의 대표 사이트로 이베이(eBay)에 최대 41억 달러라는 천문학적인 돈을 받고 인수되었다.
스퀘어프리 HTML에디트(http://www.squarefree.com/htmledit/) : Ajax로 구현한 실시간 HTML 편집기
시맨틱웹 커뮤니티 포탈(www.semanticweb.org) : 시맨틱웹 관련 정보를 얻을 수 있는 포탈. 시맨틱웹에 관한 행사나 다양한 정보가 올라오며 시맨틱웹 컨퍼런스인 ISWC 정보도 여기에 올라온다.
싱잉피시(www.singingfish.com) : AOL 검색기에서 선보인 멀티미디어 검색 사이트
썸원뉴(www.someonenew.com) : 스카이프를 플랫폼으로 이용하고 있는 데이트 사이트
아이스로켓(www.icerocket.com) : 블로그 검색엔진
애스크지브스(www.ask.com) : 검색 엔진. 블로그라인스를 인수했으나 애스크지브스 자체가 IAC로 인수되었다.
애플 아이튠즈(http://www.apple.com/itunes/) : 애플의 온라인 뮤직 스토어인 아이튠즈는 고객이 자신의 마음에 들도록 RSS 공급 내용을 설정할 수 있다.
야후 360(http://360.yahoo.com) : 야후에서 만든 블로그와 소셜 네트워크를 혼합한 서비스
야후 앤서즈(Yahoo Answers, http://answers.yahoo.com) : 네이버 지식인과 비슷한 문답형 커뮤니티
야후 위젯(http://kr.widget.yahoo.com) : 야후가 인수한 콘파뷸레이터를 위젯이라는 이름으로 배포하는 사이트
야후 피플링(http://kr.ring.yahoo.com) : 구독하는 RSS를 테마별로 공유하는 커뮤니티 성격의 사이트
어댑티브패스(www.adaptivepath.com) : 웹 디자인 회사로 Ajax라는 이름을 만든 Jesse James Garrett의 에세이를 볼 수 있다.
업커밍(www.upcoming.org) : 트래킹 서비스 사이트. 야후가 인수했다.
에트시(http://www.etsy.com) : 다양한 기술을 적용한 쇼핑몰. 색깔 별 재질 별로 상품을 볼 수 있고, 상품 색을 바꿔볼 수 있고, RSS로 상품 목록 지원에 꼬리표를 사용한 꼬리표구름 목록까지. 그외 다양한 웹2.0 기술을 사용하는 쇼핑몰.
엑스파이더(www.xpyder.co.kr) : RSS구독기인 엑스파이더 배포 사이트
오데오(http://odeo.com/) : 파드캐스팅 포털 사이트.
오디오블로그닷컴(www.audioblog.com) : 파드캐스팅과 비디오 블로그 서비스 사이트.
오라일리 미디어(www.oreilly.com) : 미국의 미디어기업으로 국내에는 IT전문 출판사로 더 유명하다. 웹2.0 컨퍼런스를 주최하며 웹2.0이라는 낱말을 만들고 전파시켰다.
오버추어(www.overture.com) : 한국에서도 검색광고의 절반 정도를 차지하는 세계 검색광고 시장의 강자. 야후에 인수되었다.
올블로그(www.allblog.net) : 한국의 대표적인 메타사이트로 등록된 블로그 사이트의 RSS를 모아서 보여준다.
워크스팟(www.workspot.com) : 브라우저 상에서 리눅스를 사용할 수 있다. 현재 설치된 것은 Red Hat 8 & Mandrake 9.1 remote desktops.
웨이백머신(www.archive.org) : 인터넷의 과거 정보를 저장하고 검색할 수 있는 사이트로 웹사이트 문서 저장에서 텔레비젼 프로그램 저장까지 다양한 정보를 기록하고 있다.
웹2.0컨퍼런스(www.web2con.com) : 오라일리가 주최해 2004년 10월 5일부터 일주일 동안 미국 샌프란시스코에서 열린 웹2.0 컨퍼런스의 공식 사이트
위키피디아(www.wikipedia.org) : 전세계 네티즌이 참여해 만드는 공용백과사전
윙크(www.wink.com) : 마이클 태니(Michael Tanne)의 태그 기반 검색엔진. 태그랭크(TagRank)을 이용한 필터링을 통해 최고의 검색 결과를 제공하고 검색 결과를 발행하는 기능이 특징이다. 스팸이 없는 깨끗한 검색결과도 특징이다.
이글루스(www.egloos.com) : 한국의 블로그 전문 사이트. '이글루스 가든'이라는 꼬리표를 적용한 새로운 커뮤니티를 선보였다.
잉키보드(http://www.cfcassidy.com/InkyBoard/) : 태블릿PC(Tablet PC)를 위한 칠판(Whiteboard). 인터넷 상에서 칠판 대용으로 사용할 수 있다는 것이 특징이다.
인트라V뉴스(www.intravnews.com) : 아웃룩 플러그인 방식의 구독기 배포 사이트
자쿠바(www.jacuba.com) : 철자 검사 사이트. 브라우저나 사용환경에 상관 없이 동작한다는 점이 특징이다. 윈도 사용 환경이 아닌 경우 유용.
조이엔트(Joyent, www.joyent.com) : 개인의 편지나 일정, 주소록 등을 관리하는 PIMS 서비스로 기존 서비스와 다른 점은 꼬리표를 이용해 분류를 하고, 아작스, 주소록의 구글지도 연동과 같은 시맨틱웹 기술을 이용하는 점이다.
지오뉴스(Geonews, http://www.wereporters.com/geonews.htm) : 구글 뉴스와 구글 맵을 혼합한 서비스로 하우징맵, 지오블로거와 함께 혼합(mash-up) 서비스의 한 종류로 주목받고 있다.
지오블로거(www.geobloggers.com) : 세계 주요 도시에서 찍은 사진들을 구글 지도에 표시해주는 사이트. 네티즌이 플릭커에 올린 해당 도시 사진에 지오블로거를 이용해 도시이름 꼬리표를 붙여주면 구글의 지도를 선택할 경우 관련 사진이 뜨는 서비스다.
짐브라(Zimbra, www.zimbra.com) : 개인일정 서비스로 아작스와 RSS, 스카이프, 구글지도 연동이라는 특징을 가지고 있다.
칼렌다허브(http://www.calendarhub.com) : Ajax로 구현된 일정관리 사이트.
콘파뷸레이터(www.konfabulator.com) : 콘파뷸레이터라는 대시보드 프로그램 개발사. 콘파뷸레이터도 XML과 자바스크립트를 이용하기 때문에 위젯이라는 확장 프로그램을 사용자들이 개발하기 쉽다. 야후에 인수된 후 야후 위젯(http://kr.widget.yahoo.com)으로 다시 태어났다.
클립마크스(www.clipmarks.com) : 신문 잡지의 일부를 찢어서 보관하는 것처럼 웹에서도 일부분을 보관할 수 있도록 하라는 사이트. 웹페이지 전체가 아니라 부분만 찢어서 보관할 수 있도록 해주는 사이트로, 웹 상의 페이지 일부 클립(스크랩)은 물론 소셜클립마크를 지향하고 있는 사이트다.
클립폴리오(klipfolio, www.serence.com) : 작은 크기의 RSS 구독기 프로그램인 클립폴리오 배포 사이트
키코(http://www.kiko.com) : Ajax로 구현된 일정관리 사이트. 드래그 앤 드롭 인터페이스와 찌종이(레이블)를 지원한다.
타이프테스터(http://typetester.maratz.com) : Ajax로 구현한 글꼴(font) 비교하기 사이트
태그클라우드(www.tagcloud.com) : 꼬리표 낱말의 크기가 모두 달라 꼬리표가 구름모양으로 표시된다는 꼬리표구름. 꼬리표 기술을 알아보려면 들러야 할 곳이다.
태터센터(www.tattertools.com) : 블로그 프로그램인 태터툴즈를 만들어 제공하는 곳. 최근 꼬리표 기술을 적용해 커뮤니티 사이트로 변화중이다.
테일랭크(http://www.tailrank.com/) : 수 천 개 블로그 중에서 최고의 알맹이만을 골라서 보여준다는 사이트. 사용자들이 직접 기사를 수정하는 것이 특징이다.
테크노라티(www.technorati.com) : 2천만 개의 블로그가 등록된 꼬리표(tag) 기반의 블로그 전문 검색엔진. 구글보다 빨리 블로그를 검색해준다는 이유로 스타가 되었다.
토크디거(www.talkdigger.com) : 메타링크 검색엔진. 자신이 알고 있는 URL을 입력하면 해당 URL을 인용한 사이트를 찾아준다. 즉 특정 URL을 화제로 삼은 사이트를 찾아주는 검색엔진.
토픽스넷(www.topix.net) : 우편번호를 입력하면 30만 주제의 뉴스를 찾아주는 서비스
트라이루비(http://tryruby.hobix.com/) : 아작스로 구현한 루비 사이트. ruby 인터프리터쉘을 웹에서 사용 할 수가 있다.
파드캐스트(www.podcast.co.kr) : 파드캐스팅을 지원하는 국내 사이트
파인도리(http://www.findory.com/) : 뉴스와 블로그를 결합시켜 뉴스를 읽고 배우고 개인화시키는 서비스. 인공지능형 뉴스 사이트라는 점이 특징이다.
판도(www.pando.com/) : 누구나 무료로 어떤 크기의 파일이나 폴더라도 이메일로 전송하는 응용 프로그램.
패닉닷컴 쇼핑몰(http://panic.com/goods/) : Ajax를 이용한 쇼핑카트의 예를 볼 수 있다.
페이스북(http://facebook.com/) : 미국 대학생들이 많이 사용하는 커뮤니티 사이트
프로토페이지(www.protopage.com) : 개인화된 뉴스, 쪽지(sticky notes), 즐겨 찾기, 그외 각종 웹페이지를 하나의 페이지에서 볼 수 있게 만든 개인화 홈페이지 서비스 중 하나. 아작스(Ajax)를 이용하는 것이 특징이다.
플란조(http://www.planzo.com) : 일정관리 사이트로 다른 사람들과 일정 공유로 커뮤니티 일정 관리 가능. Ajax를 이용하여 드래그 앤 드롭 인터페이스 지원. RSS 공급 지원.
플릭커(www.flickr.com) : 꼬리표 기반의 사진 사이트. 웹2.0을 대표하는 사이트로 각종 상을 휩쓸다가 야후에 인수되었다.
피드데몬(http://www.bradsoft.com/feeddemon) : 가장 대표적인 RSS 구독기 프로그램인 피드데몬 배포 사이트
피드버너(www.feedburner.com) : 개인 블로그의 트래픽 부담을 덜기 위해 RSS 트래픽을 대신 떠안는 서비스.
피드스터(http://feedster.com) : 미국 샌프란시스코에 위치한 검색 엔진과 XML 웹 컨텐트 신디케이션 기업.
피카사(http://picasa.google.com/) : 웹 기반의 사진 관리 편집 사이트. 구글에 인수되었다.
하우징맵(www.housingmaps.com) : 폴 레이드매처(Paul Rademacher)라는 디자이너가 개발한 부동산 서비스로 구글지도에 크레이그리스트(craigslist)의 부동산 정보를 결합했다.
<!-- //포스팅 -->출처 : [기타] 인터넷 : http://webperse.com
블로그를 보다 zzony님의 포스팅을 찾았다.
「웹페이지를 하나의 그림이나 파일로 저장해줍니다」라는 글이다.
서비스를 제공하는 사이트는 thumbalizr.com인데 네이버로 테스트 해봤다.
홈페이지에 접속하여 이미지로 만들 사이트의 주소를 적으면 다음과 같이 간단한 섬네일과 해상도를 표시한다.
해상도를 선택하면 그 해상도에 맞는 페이지를 깔끔하게 이미지로 저장하여 보여준다.
다음은 800 해상도를 선택했을 때의 그림이다.
이 서비스를 사용해보면서 블로그에서의 문제가 되는 스크랩기능을 이렇게 이미지로 제공하면 어떨까 라는 생각을 해본다.
컨텐츠의 스크랩에 있어서 문제가 되는 것이 대부분 스크랩을 지원하는 사이트의 경우 스크랩 후에 그 컨텐츠의 내용을 수정할 수 있다는 점이다.
즉 양질의 컨텐츠라해도 복사&붙여넣기나 스크랩 버튼 클릭하나로 다른 사람의 것으로 쉽게 보여질 수 있는 것이다.
물론 이렇게 이미지로 제공하는 것이 스크린 캡쳐나 내용을 다시 작성하는 것 등의 방법으로 컨텐츠의 불법스크랩을 할 수 있다고 해도 지금처럼의 무분별한 펌질이나 수정을 어느정도 막을 수 있지 않을까 생각한다.
그리고 스크랩을 수행할때 이미지를 배경에 저작자와 서비스 제공자의 워터마크를 추가하면 본 저작자의 저작권 보호와 불법 스크랩을 근절한다는 서비스 업체의 이미지에도 도움이 될 것 같다.
[출처] 홈페이지를 찍는 홈페이지!?|작성자 롬비
<HTML>
<HEAD>
<TITLE>TextArea </TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function CheckStrLength()
{
var temp;
var f = document.form.write_text.value.length;
var msglen = 256; //최대 길이
var tmpstr = "";
var enter = 0;
var strlen;
// 초기 최대길이를 텍스트 박스에 뿌려준다.
if(f == 0)
document.form.remain.value = msglen;
else
{
for(k=0;k<f;k++)
{
temp = document.form.write_text.value.charAt(k);
if(temp == '\n')// 입력 라인 제한을 위해 엔터키 횟수 증가
{
enter++;
}
if(escape(temp).length > 4)
msglen -= 2;
else
msglen--;
if(msglen < 0)
{
alert("총 영문 512자 한글 256자 까지 쓰실 수 있습니다.");
document.form.write_text.value = tmpstr;
break;
}
else if(enter > 3)
{
alert("라인수 4라인을 넘을수 없습니다.");
enter = 0;
strlen = tmpstr.length - 1;
//alert(strlen);
document.form.write_text.value = tmpstr.substring(0,strlen);
break;
}
else
{
document.form.remain.value = msglen;
tmpstr += temp;
}
}
}
}
//-->
</SCRIPT>
</HEAD>
<BODY>
아는 후배 한테 받은건데 잘써먹고 있어요
<FORM name="form" METHOD="POST" ACTION="" ID="Form1">
<table border="0" cellspacing="0" cellpadding="0" ID="Table1">
<tr>
<td width="200" style="FONT-FAMILY: 굴림; FONT-SIZE: 12pt">⊙ 내용입력 남은 글자수 :
</td>
<td align="left" width="50"><input type="text" name="remain" size="3" value="" style="background-color:#ffffff;border:1 solid #33333; FONT-FAMILY: 굴림; FONT-SIZE: 10pt"
readonly ID="Text1">
</td>
<td align="" valign="bottom" width="360">(4줄까지만 작성 가능합니다.)
</td>
</tr>
<tr>
<td colspan="3" height="1"></td>
</tr>
<tr>
<td colspan="3"><img src="http://okjsp.pe.kr/images/okjsp_top.gif" width="1" height="3" border="0"><br>
<textarea name="write_text" cols="75" rows="10" WRAP="SOFT" onChange="CheckStrLength()" onKeyUp="CheckStrLength()"
ID="Textarea1"></textarea>
</td>
</tr>
</table>
</FORM>
</BODY>
</HTML>
[출처] [펌] textarea의 글자수와 라인수 제한 |작성자 제로스엘
<!--
// 최상위 체크 로직(chars로 넘긴 값이 있다면 true)
function containsCharsOnly(input,chars) {
for (var inx = 0; inx < input.value.length; inx++) {
if (chars.indexOf(input.value.charAt(inx)) == -1)
return false;
}
return true;
}
// 최상위 체크 로직(chars로 넘긴 값이 있다면 false)
function containsChars(input,chars) {
for (var inx = 0; inx < input.value.length; inx++) {
if (chars.indexOf(input.value.charAt(inx)) != -1)
return true;
}
return false;
}
// 숫자 체크
function isNum(input) {
var chars = "0123456789";
return containsCharsOnly(input,chars);
}
// 이름체크
function nameCheck(input){
var chars = '0123456789~!@#$%^&*()_-+=|{}[]<>,./?';
return containsChars(input,chars);
}
// 전화 번호 Check
function isPhoneCheck(input) {
var chars = "0123456789( ).-,<>{}[]_~";
return containsCharsOnly(input,chars);
}
// 영문 판별
function isPhoneCheck(input) {
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
return containsCharsOnly(input,chars);
}
// 영숫자 판별
function isPhoneCheck(input) {
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return containsCharsOnly(input,chars);
}
// 입력값이 숫자,대시(-)로 되어있는지 체크
function isNumDash(input) {
var chars = "-0123456789";
return containsCharsOnly(input,chars);
}
// 입력값이 숫자,콤마(,)로 되어있는지 체크
function isNumComma(input) {
var chars = ",0123456789";
return containsCharsOnly(input,chars);
}
// 입력값이 사용자가 정의한 포맷 형식인지 체크
// 자세한 format 형식은 자바스크립트의 ''regular expression''을 참조
function isValidFormat(input,format) {
if (input.value.search(format) != -1) {
return true; file://올바른 포맷 형식
}
return false;
}
/**
* 입력값이 이메일 형식인지 체크
* ex) if (!isValidEmail(form.email)) {
* alert("올바른 이메일 주소가 아닙니다.");
* }
*/
function isValidEmail(input) {
// var format = /^(\S+)@(\S+)\.([A-Za-z]+)$/;
var format = /^((\w|[\-\.])+)@((\w|[\-\.])+)\.([A-Za-z]+)$/;
return isValidFormat(input,format);
}
/**
* 입력값이 전화번호 형식(숫자-숫자-숫자)인지 체크
*/
function isValidPhone(input) {
var format = /^(\d+)-(\d+)-(\d+)$/;
return isValidFormat(input,format);
}
// 콤마 없애기
function removeComma(input) {
return input.value.replace(/,/gi,"");
}
// 문자 변환 함수
function alterString(str,before,after) {
var returnStr = "";
for(i = 0; i < str.length; i++) {
value = str.charAt(i);
index = before.indexOf(value);
if(index >= 0) value = after.charAt(index);
returnStr += value;
}
return returnStr;
}
// 소 --> 대문자 변환 함수
function ToUpper(arg) {
var str1 = "abcdefghijklmnopqrstuvwxyz";
var str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return alterString(arg,str1,str2);
}
// 대 --> 소문자 변환 함수
function ToLower(arg){
var str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var str2 = "abcdefghijklmnopqrstuvwxyz";
return alterString(arg,str1,str2);
}
// 반각 문자를 전각문자로
function convert2ByteChar(x_char) {
var x_2byteChar = ""; //컨버트된 문자
var c = x_char.charCodeAt(0);
if(32 <= c && c <= 126) { //전각으로 변환될수 있는 문자의 범위
if(c == 32) { //스페이스인경우 ascii 코드 32
x_2byteChar = unescape("%uFFFC");
} else {
x_2byteChar = unescape("%u"+gf_DecToHex(c+65248));
}
}
return x_2byteChar;
}
// 10진수를 16진수로
function gf_DecToHex(x_dec) {
var x_Hex = new Array();
var x_serial = 0;
var x_over16 = x_dec;
var x_tempNum = 0;
while(x_dec > 15) {
var x_h = x_dec % 16; //나머지
x_dec = parseInt(x_dec/16); //몫
x_Hex[x_serial++] = (x_h > 9 ? String.fromCharCode(x_h + 55) : x_h); //16진수코드변환
}
//마지막은 몫의 값을 가짐
x_Hex[x_serial++] = (x_dec > 9 ? String.fromCharCode(x_dec + 55) : x_dec); //16진수코드변환
//몫,나머지,나머지,.....
var retValue = "";
for(var i=x_Hex.length ; i>0 ;i--) {
retValue += x_Hex[i-1];
}
return retValue;
}
// input box에 space, 등 만으로 넣고 장난 칠때 이들 문자 뺀 길이를 통해 유효성 체크한다...
function CheckStr(strOriginal, strFind, strChange){
var position, strOri_Length;
position = strOriginal.indexOf(strFind);
while (position != -1){
strOriginal = strOriginal.replace(strFind, strChange);
position = strOriginal.indexOf(strFind);
}
strOri_Length = strOriginal.length;
return strOri_Length;
}
// 체크 박스에 체크가 되어 있으면 true
function checkValidator(str) {
if(str.checked) return true;
else return false;
}
// 비밀번호는 4자 등 최대 최소 길이를 파람으로 주고 처리...
function checkLength(str,minLng,maxLng){
var ckstr = str.value.length;
if (parseInt(ckstr) < parseInt(minLng) || parseInt(ckstr) > parseInt(maxLng)) return false;
return true;
}
// 숫자만 받아서 아니면 메세지 보여 주는
function onlyNumber(objEv) {
if(!isNum(objEv)){
alert("숫자만 입력가능합니다.");
objEv.value = "";
objEv.focus();
return;
}
}
// 숫자를 체크하다가 6자 등 원하는 만큼 이동후 다음 input 박스로 이동 시키는...
function goJump(fname, len, goname){
onlyNumber(fname);
if (document.all[fname].value.length == len) document.all[goname].focus();
}
// 주민등록번호 체크 로직
function check_ResidentNO(str_f_num,str_l_num){
var i3=0
for (var i=0;i<str_f_num.length;i++){
var ch1 = str_f_num.substring(i,i+1);
if (ch1<'0' || ch1>'9') i3=i3+1;
}
if ((str_f_num == '') || ( i3 != 0 )) return false;
var i4=0;
for (var i=0;i<str_l_num.length;i++){
var ch1 = str_l_num.substring(i,i+1);
if (ch1<'0' || ch1>'9') i4=i4+1;
}
if ((str_l_num == '') || ( i4 != 0 )) return false;
if(str_f_num.substring(0,1) < 4) return false;
if(str_l_num.substring(0,1) > 2) return false;
if((str_f_num.length > 7) || (str_l_num.length > 8)) return false;
if ((str_f_num == '72') || ( str_l_num == '18')) return false;
var f1=str_f_num.substring(0,1)
var f2=str_f_num.substring(1,2)
var f3=str_f_num.substring(2,3)
var f4=str_f_num.substring(3,4)
var f5=str_f_num.substring(4,5)
var f6=str_f_num.substring(5,6)
var hap=f1*2+f2*3+f3*4+f4*5+f5*6+f6*7
var l1=str_l_num.substring(0,1)
var l2=str_l_num.substring(1,2)
var l3=str_l_num.substring(2,3)
var l4=str_l_num.substring(3,4)
var l5=str_l_num.substring(4,5)
var l6=str_l_num.substring(5,6)
var l7=str_l_num.substring(6,7)
hap=hap+l1*8+l2*9+l3*2+l4*3+l5*4+l6*5
hap=hap%11
hap=11-hap
hap=hap%10
if (hap != l7) return false;
return true;
}
// 바이트 구하기
function getByteLen(str){
return(str.length+(escape(str)+"%u").match(/%u/g).length-1);
}
// url 가져오기
function getUrlAddress(){
var pageUrl = document.location;
pageUrl = new String(pageUrl);
return pageUrl.substring(0,pageUrl.lastIndexOf("/"));
}
// 오른마우스 금지, 나중에 해당 주석 풀고 사용
function rightbutton(e){
if (navigator.appName == 'Netscape' && (e.which == 3 || e.which == 2))
return false;
else if (navigator.appName == 'Microsoft Internet Explorer' && (event.button == 2 || event.button == 3))
{
alert("죄송합니다!! 정보무단복제를 막기 위하여 오른쪽 마우스 사용을 허용하지 않습니다.");
return false;
}
return true;
}
//document.onmousedown=rightbutton;
// 컨트롤 키 금지, 나중에 해당 주석 풀고 사용
function checkCtl(){
if (document.all){
if(event.keyCode==17) {
alert("죄송합니다!! 컨트롤키 사용을 허용하지 않습니다.");
return false;
}
}
}
//document.onkeydown = checkCtl;
function setCookie(name,value) {
document.cookie = name+"="+escape(value)+";path=/;domain=.kkaok.pe.kr;";
}
function setCookie(name,value, expires) {
document.cookie = name + "=" + escape(value) +
"; path=/; expires=" + expires.toGMTString();
}
function getCookie(Name) {
var search = Name + "="
if (document.cookie.length > 0) { // 쿠키가 설정되어 있다면
offset = document.cookie.indexOf(search)
if (offset != -1) { // 쿠키가 존재하면
offset += search.length
// set index of beginning of value
end = document.cookie.indexOf(";", offset)
// 쿠키 값의 마지막 위치 인덱스 번호 설정
if (end == -1)
end = document.cookie.length
return unescape(document.cookie.substring(offset, end));
}
}
}
String.prototype.trim = function(){
return this.replace(/(^\s*)|(\s*$)/gi, "");
}
//문자 바꾸기, 사용법 var str = 문자열.replaceAll("a", "1");
String.prototype.replaceAll = function(str1, str2) {
var temp_str = "";
if (this.trim() != "" && str1 != str2) {
temp_str = this.trim();
while (temp_str.indexOf(str1) > -1){
temp_str = temp_str.replace(str1, str2);
}
}
return temp_str;
}
//-->
[출처] [펌] 자주 쓰이는 JavaScript|작성자 제로스엘
<!--
//---------------------------------------------------------------------------//
// StringUtil //
//---------------------------------------------------------------------------//
/**----------------------------------------------------------------------------
함수명 : removeWhiteSpace()
설 명 : 문자열에 포함된 공백, 개행문자 제거
인자값 : String strTarget - 문자열에 포함된
공백, 개행문자를 제거하고자하는 문자열
리 턴 : String - 좌우 공백이 제거된 문자열
사용법 : var strResult = trim(' 문 자 열 ');
return '문자열'
-----------------------------------------------------------------------------*/
function removeWhiteSpace(strTarget)
{
var strEliminate = /\s+/g;
if(strTarget)
{
return strTarget.replace(strEliminate,"");
}
else
{
return strTarget;
}
}
/**----------------------------------------------------------------------------
함수명 : trim()
설 명 : 좌우 공백 제거
인자값 : String strTarget - 좌우 공백을 없애고자하는 문자열
리 턴 : String - 좌우 공백이 제거된 문자열
사용법 : var strResult = trim(' 문 자 열 ');
return '문 자 열'
-----------------------------------------------------------------------------*/
function trim(strTarget)
{
var strEliminate = /(^\s*)|(\s*$)/gi;
if(strTarget)
{
return strTarget.replace(strEliminate,"");
}
else
{
return strTarget;
}
}
/**----------------------------------------------------------------------------
함수명 : ltrim()
설 명 : 좌측 공백 제거
인자값 : String strTarget - 좌측 공백을 없애고자하는 문자열
리 턴 : String - 좌측 공백이 제거된 문자열
사용법 : var strResult = ltrim(' 문 자 열 ');
return '문 자 열 '
-----------------------------------------------------------------------------*/
function ltrim(strTarget)
{
while(strTarget.substring(0,1)==" ")
{
strTarget = strTarget.substring(1);
}
return strTarget;
}
/**----------------------------------------------------------------------------
함수명 : rtrim()
설 명 : 우측 공백 제거
인자값 : String strTarget - 우측 공백을 없애고자하는 문자열
리 턴 : String - 우측 공백이 제거된 문자열
사용법 : var strResult = rtrim(' 문 자 열 ');
return ' 문 자 열'
-----------------------------------------------------------------------------*/
function rtrim(strTarget)
{
var len = strTarget.length;
while(strTarget.substring(len-1,len)==" ")
{
strTarget = strTarget.substring(0,len-1);
len = strTarget.length;
}
return strTarget;
}
/**----------------------------------------------------------------------------
함수명 : replaceAll()
설 명 : 소스문자열에 포함된 문자를 원하는 문자로 변환
공백 또는 '0'을 자리수만큼 채운 문자열
인자값 : String strSrc - 소스 문자열
String strOld - 총 자릿수
String strNew - 숫자인가? (옵션 default : false)
리 턴 : String - 소스 문자열을 포함해 원하는 위치에
공백 또는 '0'을 자리수만큼 채운 문자열
사용법 : var strResult = packValue('1234', 8, true, true);
return '00001234'
-----------------------------------------------------------------------------*/
function replaceAll(strSrc, strOld, strNew)
{
var retValue = "";
if(strOld == null)
{
return strSrc;
}
if (strSrc != "" && strOld != strNew)
{
retValue = strSrc;
while (retValue.indexOf(strOld) > -1)
{
retValue = retValue.replace(strOld, strNew);
}
}
return retValue;
}
// 문자 변환 함수 (=replaceAll() 함수와 동일)----------------------------------
function alterString(strSrc, strOld, strNew)
{
var retValue = "";
for(i = 0; i < strSrc.length; i++)
{
var value = strSrc.charAt(i);
var index = strOld.indexOf(value);
if(index >= 0)
{
value = strNew.charAt(index);
}
retValue += value;
}
return retValue;
}
/**----------------------------------------------------------------------------
함수명 : formatString()
설 명 : 포멧 문자열 변환
인자값 : String strSrc - 변환하고자 하는 문자열
String strFormat - 포멧형식
String strDelim - 포멧 구분자 문자
리 턴 : String - 원하고자 하는 포멧으로 변환된 문자열
사용법 : var strResult = formatString('20050512', '9999/99/99');
return ' 문 자 열'
-----------------------------------------------------------------------------*/
function formatString(strSrc,strFormat)
{
var retValue = "";
var j = 0;
var strSrc = strSrc.replace(/(\$|\^|\*|\(|\)|\+|\.|\?|\\|\{|\}|\||\[|\]|\-|\/|\:)/g, "");
for (var i=0; i< strSrc.length; i++)
{
retValue += strSrc.charAt(i);
j++;
if ( (j < strSrc.length && j < strFormat.length)
&& (strFormat.charAt(j) != "9"
&& strFormat.charAt(j).toLower != "x"
&& strFormat.charAt(j) != "#") )
{
retValue += strFormat.charAt(j++);
}
}
return retValue;
}
/**----------------------------------------------------------------------------
함수명 : packValue()
설 명 : 소스 문자열을 포함해 원하는 위치에
공백 또는 '0'을 자리수만큼 채운 문자열
인자값 : String strSrc - 소스 문자열
Int nSize - 총 자릿수
bool bNum - 숫자인가? (옵션 default : false)
bool bLeft - 왼쪽에 위치할 것인지? (옵션 default : true )
리 턴 : String - 소스 문자열을 포함해 원하는 위치에
공백 또는 '0'을 자리수만큼 채운 문자열
사용법 : var strResult = packValue('1234', 8, true, true);
return '00001234'
-----------------------------------------------------------------------------*/
function packValue(strSrc, nSize, bNum, bLeft)
{
var retValue = "";
var preValue = "";
var postValue = "";
var nLen = 0;
var i = 0;
if(bNum == null)
{
bNum = false;
}
if(bLeft == null)
{
bLeft = true;
}
strSrc = "" + strSrc;
nLen = strSrc.length;
retValue = strSrc;
if(bNum)
{
for(i = nLen; i < nSize; i++)
{
if(bLeft)
{
preValue += "0";
}
else
{
postValue += "0";
}
}
}
else
{
for(i = nLen; i < nSize; i++)
{
if(bLeft)
{
preValue += " ";
}
else
{
postValue += " ";
}
}
}
retValue = preValue + retValue + postValue;
return retValue;
}
/**----------------------------------------------------------------------------
함수명 : getByte()
설 명 : 문자열의 바이트수 구하기
인자값 : String strSrc - 소스 문자열
리 턴 : Int - 문자열 바이트수
사용법 : var nResult = getByte('가나다1234');
return 10
-----------------------------------------------------------------------------*/
function getByte(strSrc)
{
// var nByte = 0;
// for(var i=0; i < strSrc.length; i++)
// {
// if(!((strSrc.charCodeAt(i) > 0x3130 && strSrc.charCodeAt(i) < 0x318F)
// || (strSrc.charCodeAt(i) >= 0xAC00 && strSrc.charCodeAt(i) <= 0xD7A3)))
// {
// nByte += 1;
// }
// else
// {
// nByte += 2;
// }
// }
// return nByte;
return (strSrc.length+(escape(strSrc)+"%u").match(/%u/g).length - 1);
}
/**----------------------------------------------------------------------------
함수명 : toUpper()
설 명 : 소문자를 대문자로 변환
인자값 : String strSrc - 소스 문자열
리 턴 : String - 대문자로 변환된 문자열
사용법 : var strResult = toUpper('abc');
return 'ABC'
-----------------------------------------------------------------------------*/
function toUpper(strSrc)
{
var str1 = "abcdefghijklmnopqrstuvwxyz";
var str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return alterString(strSrc, str1, str2);
}
/**----------------------------------------------------------------------------
함수명 : toLower()
설 명 : 대문자를 소문자로 변환
인자값 : String strSrc - 소스 문자열
리 턴 : String - 소문자로 변환된 문자열
사용법 : var strResult = toLower('ABC');
return 'abc'
-----------------------------------------------------------------------------*/
function toLower(strSrc)
{
var str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var str2 = "abcdefghijklmnopqrstuvwxyz";
return alterString(strSrc, str1, str2);
}
/**----------------------------------------------------------------------------
함수명 : removeComma()
설 명 : 문자열에 포함된 ','를 제거
인자값 : String strSrc - 소스 문자열
리 턴 : String - ','가 제거된 문자열
사용법 : var nResult = removeComma('123,456,789');
return '123456789'
-----------------------------------------------------------------------------*/
function removeComma(strSrc)
{
return strSrc.replace(/,/gi,"");
}
/**----------------------------------------------------------------------------
함수명 : removeFormat()
설 명 : 문자열에 포함된 포멧문자 ", . - / :"를 제거
인자값 : String strSrc - 소스 문자열
리 턴 : String - ", . - / :"가 제거된 문자열
사용법 : var nResult = removeComma('2005/03/12 12:24:00');
return '20050312 122400'
-----------------------------------------------------------------------------*/
function removeFormat(strSrc)
{
return strSrc.replace(/(\,|\.|\-|\/|\:)/g,"");
}
/**----------------------------------------------------------------------------
함수명 : addComma()
설 명 : 문자열에 포함된 ','를 제거
인자값 : String strSrc - 소스 문자열
bool bSymbol - '+' 부호일때 보일것인가?
리 턴 : String - ','가 제거된 문자열
사용법 : var nResult = addComma('1234567.12', true);
return '+1,234,567.12'
-----------------------------------------------------------------------------*/
function addComma(strSrc, bSymbol)
{
var strSymbol = '';
var retValue = '';
var strTempSymbol = '';
var strTempDotValue = '';
var nLen = 0;
try
{
if(bSymbol == null)
{
bSymbol = false;
}
strSrc = strSrc.trim();
if(strSrc.indexOf('.') != 0)
{
var nIndex = strSrc.indexOf('.');
strTempDotValue = strSrc.substring(nIndex);
strSrc = strSrc.substring(0, nIndex);
}
strTempSymbol = strSrc.substr(0,1);
if(strTempSymbol == '+')
{
strSymbol = '+';
strSrc = strSrc.substring(1);
}
if(strTempSymbol == '-')
{
strSymbol = '-';
strSrc = strSrc.substring(1);
}
nLen = strSrc.length;
for(var i=1; i <= nLen; i++)
{
retValue = strSrc.charAt(nLen - i) + retValue;
if((i % 3 == 0) && ((nLen - i) != 0))
{
retValue = "," + retValue;
}
}
if(bSymbol)
{
if(strSymbol == '')
{
strSymbol = '+';
}
}
else
{
if(strSymbol == '+')
{
strSymbol = '';
}
}
return strSymbol + retValue + strTempDotValue;
}
catch(e)
{
}
}
/**----------------------------------------------------------------------------
윗 함수 사용법 : trim('aaa'); -> 변수.trim(); 또는 문자열.trim();
-----------------------------------------------------------------------------*/
String.prototype.removeWhiteSpace = function()
{
return removeWhiteSpace(this);
}
String.prototype.trim = function()
{
return trim(this);
}
String.prototype.ltrim = function()
{
return ltrim(this);
}
String.prototype.rtrim = function()
{
return rtrim(this);
}
String.prototype.replaceAll = function(strOld, strNew)
{
return replaceAll(this, strOld, strNew);
}
String.prototype.formatString = function(strFormat)
{
return formatString(this, strFormat);
}
String.prototype.packValue = function(nSize, bNum, bLeft)
{
return packValue(this, nSize, bNum, bLeft);
}
String.prototype.getByte = function()
{
return getByte(this);
}
String.prototype.toUpper = function()
{
return toUpper(this);
}
String.prototype.toLower = function()
{
return toLower(this);
}
String.prototype.removeComma = function()
{
return removeComma(this);
}
String.prototype.removeFormat = function()
{
return removeFormat(this);
}
String.prototype.addComma = function(bSymbol)
{
return addComma(this, bSymbol);
}
-->
</script>
[출처] [펌] StringUtil ver 1.0|작성자 제로스엘
# 자바스크립트 라이브러리와 PHP함수 라이브러리를 같이 올립니다.
# 일부는 PHP스쿨에서 발췌하여 만든 소스입니다.
<!--
var n4 = (document.layers)?true:false;
var e4 = (document.all)?true:false;
//숫자만입력(onKeypress='return keyCheckdot(event)')
function keyCheck(e) {
if(n4) var keyValue = e.which
else if(e4) var keyValue = event.keyCode
if (((keyValue >= 48) && (keyValue <= 57)) || keyValue==13) return true;
else return false
}
//숫자및돗트입력(onKeypress='return keyCheckdot(event)')
function keyCheckDot(e) {
if(n4) var keyValue = e.which
else if(e4) var keyValue = event.keyCode
if (((keyValue >= 48) && (keyValue <= 57)) || keyValue==13 || keyValue==46) return true;
else return false
}
//공백제거
function Trim(string) {
for(;string.indexOf(" ")!= -1;){
string=string.replace(" ","")
}
return string;
}
//입력검사
function Exists(input,types) {
if(types) if(!Trim(input.value)) return false;
return true;
}
//영문검사+숫자검사(첫글자는 반드시영문)
function EngNum(input,types) {
if(types) if(!Trim(input.value)) return false;
var error_c=0, i, val;
for(i=0;i<Byte(input.value);i++) {
val = input.value.charAt(i);
if(i == 0) if(!((val>='a' && val<='z') || (val>='A' && val<='Z'))) return false;
else if(!((val>=0 && val<=9) || (val>='a' && val<='z') || (val>='A' && val<='Z'))) return false;
}
return true;
}
//영문검사+숫자검사
function EngNumAll(input,types) {
if(types) if(!Trim(input.value)) return false;
var error_c=0, i, val;
for(i=0;i<Byte(input.value);i++) {
val = input.value.charAt(i);
if(!((val>=0 && val<=9) || (val>='a' && val<='z') || (val>='A' && val<='Z'))) return false;
}
return true;
}
//영문검사+숫자검사+'_'
function EngNumAll2(input,types) {
if(types) if(!Trim(input.value)) return false;
var error_c=0, i, val;
for(i=0;i<Byte(input.value);i++) {
val = input.value.charAt(i);
if(!((val>=0 && val<=9) || (val>='a' && val<='z') || (val>='A' && val<='Z') || val=='_')) return false;
}
return true;
}
//영문검사
function Eng(input,types) {
if(types) if(!Trim(input.value)) return false;
var error_c=0, i, val;
for(i=0;i<Byte(input.value);i++) {
val = input.value.charAt(i);
if(!((val>='a' && val<='z') || (val>='A' && val<='Z'))) return false;
}
return true;
}
//숫자만입력
/*
function numberonlyinput() {
var ob = event.srcElement;
ob.value = noSplitAndNumberOnly(ob);
return false;
}
*/
//돈(3단위마다 컴마를 붙인다.)
function checkNumber() {
var ob=event.srcElement;
ob.value = filterNum(ob.value);
ob.value = commaSplitAndNumberOnly(ob);
return false;
}
//한정액(일정금액 이상이 되면 올라기지 않게 한다.)
function chkhando(money) {
var ob=event.srcElement;
ob.value = noSplitAndNumberOnly(ob);
if(ob.value > money) ob.value = money;
return false;
}
//이자율(소수점 사용가능)
function checkNumberDot(llen,rlen) {
if(llen == "") llen = 8;
if(rlen == "") rlen = 2;
var ob=event.srcElement;
ob.value = filterNum(ob.value);
spnumber = ob.value.split('.');
if( spnumber.length >= llen && (spnumber[0].length >llen || spnumber[1].length >llen)) {
ob.value = spnumber[0].substring(0,llen) + "." + spnumber[1].substring(0,rlen);
ob.focus();
return false;
}
else if( spnumber[0].length > llen ) {
ob.value = spnumber[0].substring(0,llen) + ".";
ob.focus();
return false;
}
else if(ob.value && spnumber[0].length == 0) {
ob.value = 0 + "." + spnumber[1].substring(0,rlen);
ob.focus();
return false;
}
ob.value = commaSplitAndAllowDot(ob);
return false;
}
//참조함수
function filterNum(str) {
re = /^\$|,/g;
return str.replace(re, "");
}
//참조함수(컴마불가)
function commaSplitAndNumberOnly(ob) {
var txtNumber = '' + ob.value;
if (isNaN(txtNumber) || txtNumber.indexOf('.') != -1 ) {
ob.value = ob.value.substring(0, ob.value.length-1 );
ob.value = commaSplitAndNumberOnly(ob);
ob.focus();
return ob.value;
}
else {
var rxSplit = new RegExp('([0-9])([0-9][0-9][0-9][,.])');
var arrNumber = txtNumber.split('.');
arrNumber[0] += '.';
do {
arrNumber[0] = arrNumber[0].replace(rxSplit, '$1,$2');
}
while (rxSplit.test(arrNumber[0]));
if (arrNumber.length > 1) {
return arrNumber.join('');
}
else {
return arrNumber[0].split('.')[0];
}
}
}
//참조함수(컴마가능)
function commaSplitAndAllowDot(ob) {
var txtNumber = '' + ob.value;
if (isNaN(txtNumber) ) {
ob.value = ob.value.substring(0, ob.value.length-1 );
ob.focus();
return ob.value;
}
else {
var rxSplit = new RegExp('([0-9])([0-9][0-9][0-9][,.])');
var arrNumber = txtNumber.split('.');
arrNumber[0] += '.';
do {
arrNumber[0] = arrNumber[0].replace(rxSplit, '$1,$2');
}
while (rxSplit.test(arrNumber[0]));
if (arrNumber.length > 1) {
return arrNumber.join('');
}
else {
return arrNumber[0].split('.')[0];
}
}
}
//숫자만가능
function noSplitAndNumberOnly(ob) {
var txtNumber = '' + ob.value;
if (isNaN(txtNumber) || txtNumber.indexOf('.') != -1 ) {
ob.value = ob.value.substring(0, ob.value.length-1 );
ob.focus();
return ob.value;
}
else return ob.value;
}
//바이트검사
function Byte(input) {
var i, j=0;
for(i=0;i<input.length;i++) {
val=escape(input.charAt(i)).length;
if(val== 6) j++;
j++;
}
return j;
}
//팝업메뉴
function popupmenu_show(layername, thislayer, thislayer2) {
thislayerfield.value = thislayer;
thislayerfield2.value = thislayer2;
var obj = document.all[layername];
var _tmpx,_tmpy, marginx, marginy;
_tmpx = event.clientX + parseInt(obj.offsetWidth);
_tmpy = event.clientY + parseInt(obj.offsetHeight);
_marginx = document.body.clientWidth - _tmpx;
_marginy = document.body.clientHeight - _tmpy ;
if(_marginx < 0) _tmpx = event.clientX + document.body.scrollLeft + _marginx ;
else _tmpx = event.clientX + document.body.scrollLeft ;
if(_marginy < 0) _tmpy = event.clientY + document.body.scrollTop + _marginy + 20;
else _tmpy = event.clientY + document.body.scrollTop ;
obj.style.posLeft = _tmpx - 5;
obj.style.posTop = _tmpy;
layer_set_visible(obj, true);
layer_set_pos(obj, event.clientX, event.clientY);
}
function layer_set_visible(obj, flag) {
if (navigator.appName.indexOf('Netscape', 0) != -1) obj.visibility = flag ? 'show' : 'hide';
else obj.style.visibility = flag ? 'visible' : 'hidden';
}
function layer_set_pos(obj, x, y) {
if (navigator.appName.indexOf('Netscape', 0) != -1) {
obj.left = x;
obj.top = y;
} else {
obj.style.pixelLeft = x + document.body.scrollLeft;
obj.style.pixelTop = y + document.body.scrollTop;
}
}
//페이지이동
function move(url) {
location.href = url;
}
//닫기
function toclose() {
self.close();
}
//위치변경
function winsize(w,h,l,t) {
if(window.opener) resizeTo(w,h);
}
//포커스위치
function formfocus(form) {
var len = form.elements.length;
for(i=0;i<len;i++) {
if((form.elements[i].type == "text" || form.elements[i].type == "password") && Trim(form.elements[i].value) == "") {
form.elements[i].value = "";
form.elements[i].focus();
break;
}
}
}
// 날짜,시간 format 함수 = php의 date()
function date(arg_format, arg_date) {
if(!arg_date) arg_date = new Date();
var M = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
var F = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
var K = new Array("일","월","화","수","목","금","토");
var k = new Array("日","月","火","水","木","金","土");
var D = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
var l = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
var o = new Array("전","후");
var O = new Array("오전","오후");
var a = new Array("am","pm");
var A = new Array("AM","PM");
var org_year = arg_date.getFullYear();
var org_month = arg_date.getMonth();
var org_date = arg_date.getDate();
var org_wday = arg_date.getDay();
var org_hour = arg_date.getHours();
var org_minute = arg_date.getMinutes();
var org_second = arg_date.getSeconds();
var hour = org_hour % 12; hour = (hour) ? hour : 12;
var ampm = Math.floor(org_hour / 12);
var value = new Array();
value["Y"] = org_year;
value["y"] = String(org_year).substr(2,2);
value["m"] = String(org_month+1).replace(/^([0-9])$/,"0$1");
value["n"] = org_month+1;
value["d"] = String(org_date).replace(/^([0-9])$/,"0$1");
value["j"] = org_date;
value["w"] = org_wday;
value["H"] = String(org_hour).replace(/^([0-9])$/,"0$1");
value["G"] = org_hour;
value["h"] = String(hour).replace(/^([0-9])$/,"0$1");
value["g"] = hour;
value["i"] = String(org_minute).replace(/^([0-9])$/,"0$1");
value["s"] = String(org_second).replace(/^([0-9])$/,"0$1");
value["t"] = (new Date(org_year, org_month+1, 1) - new Date(org_year, org_month, 1)) / 86400000;
value["z"] = (new Date(org_year, org_month, org_date) - new Date(org_year, 0, 1)) / 86400000;
value["L"] = ((new Date(org_year, 2, 1) - new Date(org_year, 1, 1)) / 86400000) - 28;
value["M"] = M[org_month];
value["F"] = F[org_month];
value["K"] = K[org_wday];
value["k"] = k[org_wday];
value["D"] = D[org_wday];
value["l"] = l[org_wday];
value["o"] = o[ampm];
value["O"] = O[ampm];
value["a"] = a[ampm];
value["A"] = A[ampm];
var str = "";
var tag = 0;
for(i=0;i<arg_format.length;i++) {
var chr = arg_format.charAt(i);
switch(chr) {
case "<" : tag++; break;
case ">" : tag--; break;
}
if(tag || value[chr]==null) str += chr; else str += value[chr];
}
return str;
}
// 해상도에 맞는 크기 사용
function screensize() {
self.moveTo(0,0);
self.resizeTo(screen.availWidth,screen.availHeight);
}
// 주민등록번호체크( 입력폼 1개)
function check_jumin(jumin) {
var weight = "234567892345"; // 자리수 weight 지정
var val = jumin.replace("-",""); // "-"(하이픈) 제거
var sum = 0;
if(val.length != 13) { return false; }
for(i=0;i<12;i++) {
sum += parseInt(val.charAt(i)) * parseInt(weight.charAt(i));
}
var result = (11 - (sum % 11)) % 10;
var check_val = parseInt(val.charAt(12));
if(result != check_val) { return false; }
return true;
}
// 주민등록번호체크( 입력폼 2개)
function check_jumin2(input, input2) {
input.value=Trim(input.value);
input2.value=Trim(input2.value);
var left_j=input.value;
var right_j=input2.value;
if(input.value.length != 6) {
alert('주민등록번호를 정확히 입력하세요.');
input.focus();
return true;
}
if(right_j.length != 7) {
alert('주민등록번호를 정확히 입력하세요.');
input2.focus();
return true;
}
var i2=0;
for(var i=0;i<left_j.length;i++) {
var temp=left_j.substring(i,i+1);
if(temp<0 || temp>9) i2++;
}
if((left_j== '') || (i2 != 0)) {
alert('주민등록번호가 잘못 입력되었습니다.');
j_left.focus();
return true;
}
var i3=0;
for(var i=0;i<right_j.length;i++) {
var temp=right_j.substring(i,i+1);
if (temp<0 || temp>9) i3++;
}
if((right_j== '') || (i3 != 0)) {
alert('주민등록번호가 잘못 입력되었습니다.');
input2.focus();
return true;
}
var l1=left_j.substring(0,1);
var l2=left_j.substring(1,2);
var l3=left_j.substring(2,3);
var l4=left_j.substring(3,4);
var l5=left_j.substring(4,5);
var l6=left_j.substring(5,6);
var hap=l1*2+l2*3+l3*4+l4*5+l5*6+l6*7;
var r1=right_j.substring(0,1);
var r2=right_j.substring(1,2);
var r3=right_j.substring(2,3);
var r4=right_j.substring(3,4);
var r5=right_j.substring(4,5);
var r6=right_j.substring(5,6);
var r7=right_j.substring(6,7);
hap=hap+r1*8+r2*9+r3*2+r4*3+r5*4+r6*5;
hap=hap%11;
hap=11-hap;
hap=hap%10;
if(hap != r7) {
alert('주민등록번호가 잘못 입력되었습니다.');
input2.focus();
return true;
}
return false;
}
// 비밀번호 체크
function check_passwd(input, input2, min) {
if(!input.value) {
alert('비밀번호를 입력해 주십시오.');
input.focus();
return false;
}
else if(BYTE(input.value) < min) {
alert('비밀번호의 길이가 너무 짧습니다.');
input.focus();
input.value='';
input2.value='';
return false;
}
else if(!input2.value) {
alert('확인비밀번호를 입력해 주십시오.');
input2.focus();
return false;
}
else if(input.value != input2.value) {
alert('비밀번호가 서로 다르게 입력되었습니다.');
input2.value='';
input2.focus();
return false;
}
else return true;
}
//콤마 넣기(정수만 해당)
function comma(val) {
val = get_number(val);
if(val.length <= 3) return val;
var loop = Math.ceil(val.length / 3);
var offset = val.length % 3;
if(offset==0) offset = 3;
var ret = val.substring(0, offset);
for(i=1;i<loop;i++) {
ret += "," + val.substring(offset, offset+3);
offset += 3;
}
return ret;
}
//문자열에서 숫자만 가져가기
function get_number(str) {
var val = str;
var temp = "";
var num = "";
for(i=0; i<val.length; i++) {
temp = val.charAt(i);
if(temp >= "0" && temp <= "9") num += temp;
}
return num;
}
//주민등록번호를 나이로 변환
function agechange(lno,rno) {
var refArray = new Array(18,19,19,20,20,16,16,17,17,18);
var refyy = rno.substring(0,1);
var refno = lno.substring(0,2);
var biryear = refArray[refyy] * 100 + eval(refno);
var nowDate = new Date();
var nowyear = nowDate.getYear();
return nowyear - biryear + 1;
}
//레디오박스 체크검사
function radio_chk(input, msg) {
var len = input.length;
for(var i=0;i<len;i++) if(input[i].checked == true && input[i].value) return true;
alert(msg);
return false;
}
//셀렉트박스 체크검사
function select_chk(input, msg) {
if(input[0].selected == true) {
alert(msg);
return false;
}
return true;
}
//새창띄우기
function open_window(url, target, w, h, s) {
if(s) s = 'yes';
else s = 'no';
var its = window.open(url,target,'width='+w+',height='+h+',top=0,left=0,scrollbars='+s);
its.focus();
}
//-->
<?
//셀렉트
function optionlist($optionlist, $getvalue="", $keyfield="key", $valuefield="value") {
foreach($optionlist as $key => $value) {
if($getvalue && $getvalue == ${$keyfield}) $chk = "selected";
else $chk = "";
echo "<option value='{${$keyfield}}' {$chk}>{${$valuefield}}</option>";
}
echo "\n";
}
//셀렉티드
function selected($checkkey, $getvalue="") {
echo "value='$checkkey'";
if($getvalue && $checkkey == $getvalue) echo " selected";
}
//체크드
function checked($checkkey, $getvalue="") {
echo "value='$getvalue'";
if($getvalue && $checkkey == $getvalue) echo " checked";
}
//주민번호 검사
function RegiNum($reginum) {
$weight = '234567892345'; // 자리수 weight 지정
$len = strlen($reginum);
$sum = 0;
if ($len <> 13) { return false; }
for ($i = 0; $i < 12; $i++) {
$sum = $sum + (substr($reginum,$i,1) * substr($weight,$i,1));
}
$rst = $sum%11;
$result = 11 - $rst;
if ($result == 10) {$result = 0;}
else if ($result == 11) {$result = 1;}
$jumin = substr($reginum,12,1);
if ($result <> $jumin) {return false;}
return true;
}
//사업자번호 검사
function comRegiNum($reginum) {
$weight = '137137135'; // 자리수 weight 지정
$len = strlen($reginum);
$sum = 0;
if ($len <> 10) { return false; }
for ($i = 0; $i < 9; $i++) {
$sum = $sum + (substr($reginum,$i,1) * substr($weight,$i,1));
}
$sum = $sum + ((substr($reginum,8,1)*5)/10);
$rst = $sum%10;
if ($rst == 0) {$result = 0;}
else {$result = 10 - $rst;}
$saub = substr($reginum,9,1);
if ($result <> $saub) {return false;}
return true;
}
//글자르기
function cut_str($msg,$cut_size,$tail="...") {
if($cut_size <= 0) return $msg;
$msg = strip_tags($msg);
$msg = str_replace("∓quot;","\"",$msg);
if(strlen($msg) <= $cut_size) return $msg;
for($i=0;$i<$cut_size;$i++) if(ord($msg[$i])>127) $han++; else $eng++;
if($han%2) $han--;
$cut_size = $han + $eng;
$tmp = substr($msg,0,$cut_size);
$tmp .= $tail;
return $tmp;
}
// 모든한글의 글자를 출력
function hangul_code() {
$count = 0;
for($i = 0x81; $i <= 0xC8; $i++) {
for($j = 0x00; $j <= 0xFE; $j++) {
if(($j >= 0x00 && $j <= 0x40) || ($j >= 0x5B && $j <= 0x60) || ($j >= 0x7B && $j <= 0x80) || ($j >= 0x00 && $j <= 0x40) ||
(($i >= 0xA1 && $i <=0xAF) && ($j >= 0xA1 && $j <= 0xFE)) || ($i == 0xC6 && ($j >= 0x53 && $j <= 0xA0)) ||
($i >= 0xC7 && ($j >= 0x41 && $j <= 0xA0))) continue;
echo chr($i).chr($j)." ";
$count++;
}
}
echo $count;
}
// 한글검사
function is_han($str) {
if(strlen($str) != 2) return false;
$i = ord ($str[0]);
$j = ord ($str[1]);
if($i < 0x81 || $i > 0xC8 || $j > 0xFE || ($j >= 0x00 && $j <= 0x40) || ($j >= 0x5B && $j <= 0x60) || ($j >= 0x7B && $j <= 0x80) ||
($j >= 0x00 && $j <= 0x40) || (($i >= 0xA1 && $i <=0xAF) && ($j >= 0xA1 && $j <= 0xFE)) ||
($i == 0xC6 && ($j >= 0x53 && $j <= 0xA0)) || ($i >= 0xC7 && ($j >= 0x41 && $j <= 0xA0))) return false;
else return true;
}
// 랜덤값 생성
function random_string($length) {
$randomcode = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'A', 'B', 'C', 'd', 'E', 'F', 'G', 'H', 'x', 'J',
'K', 'b', 'M', 'N', 'y', 'P', 'r', 'R', 'S', 'T',
'u', 'V', 'W', 'X', 'Y', 'Z');
mt_srand((double)microtime()*1000000);
for($i=1;$i<=$length;$i++) $Rstring .= $randomcode[mt_rand(1, 36)];
return $Rstring;
}
// 디렉토리 리스트
function DirList($path="./") {
$path = opendir($path);
while($list = readdir($path)) if($list != "." && $list != "..") $Arraydir[] = $list;
closedir($path);
return $Arraydir;
}
// 15자리의 유일한 숫자값 만들기
function uniquenumber() {
$temparray = explode(" ", microtime());
$temparray2 = substr($temparray[0],2,5);
$number =$temparray[1].$temparray2;
return $number;
}
// 파일이름과 확장자 분리
function ExplodeFile($filename) {
$filename = strtolower($filename);
$elements = explode('.',$filename);
$elemcnt = count($elements)-1;
if(count($elements)==1) $ext = '';
else $ext = $elements[$elemcnt];
unset($elements[$elemcnt]);
$fname = implode($elements,'');
$fileinfo["name"] = $fname;
$fileinfo["ext"] = $ext;
return $fileinfo;
}
// 그림확장자
function ImageType($filename) {
$webimg = explodefile($filename);
$webext = $webimg["ext"];
$defineexp = array("gif","jpg","png");
$count = count($defineexp);
for($i=0;$i<$count;$i++) {
if($defineexp[$i] == $webext) return true;
}
return false;
}
// 유닉스날짜 포맷
function date_format($unixtime,$format="Y.m.d",$empty=" ") {
if($unixtime) return date($format, $unixtime);
else return $empty;
}
//YYYY-MM-DD 형식을 유닉스 타임으로
function unix_format($times, $operator="-", $type=true) {
if($type == true) {
$times = trim($times);
$arry = explode($operator,$times);
if(count($arry) != 3) return date_format(0);
$mktime = mktime(0,0,0,$arry[1],$arry[2],$arry[0]);
return date("U", $mktime);
} else {
$formats = "Y{$operator}m{$operator}d";
return date($formats, $times);
}
}
// 주민등록번호 포맷
function jumin_format($juminno, $cutno=3, $des="x", $empty=" ") {
$juminno = str_replace("-","",$juminno);
if(strlen($juminno) != 13) return $empty;
for($i=0;$i<$cutno;$i++) $x .= $des;
$juminno = substr($juminno,0,13-$cutno).$x;
$juminno = substr($juminno,0,6)."-".substr($juminno,6);
return $juminno;
}
// 홈페이지 포맷
function url_format($url, $ltype=false, $title=false, $other="", $htype="http://", $empty=" ") {
$url = eregi_replace("http://","",trim($url));
if($url) $url = $htype.$url;
else return $empty;
if($title) $turl = $title;
else $turl = $url;
if($ltype) return "<a href='{$url}' {$other}>{$turl}</a>";
else return $url;
}
// 전송값 초기화
function post_format($str, $type) {
switch($type) {
case "url":
$str = trim($str);
$str = eregi_replace("http://","",$str);
break;
case "num":
$str = trim($str);
$str = str_replace(",","",$str);
break;
}
return $str;
}
// 이메일 포맷
function mail_format($email, $ltype=false, $title=false, $empty=" ") {
$email = trim($email);
$title = trim($title);
if(!$email && !$title) return $empty;
else if(!$email) return $title;
if($title) $temail = $title;
else $temail = $email;
if($ltype) return "<a href='mailto:{$email}'>{$temail}</a>";
else return $email;
}
// 전화번호 포맷
function tel_format($num1, $num2, $num3, $format="-", $empty=" ") {
$num1 = trim($num1);
$num2 = trim($num2);
$num3 = trim($num3);
if(!$num1) $num1 = "02";
if($num2 && $num3) return $num1.$format.$num2.$format.$num3;
else return $empty;
}
// 문자 포맷
function text_format($str, $empty=" ") {
$str = trim($str);
if($str) return $str;
else return $empty;
}
// 새창띄우기
function win_format($title, $url, $target, $width, $height, $scrollbars=1, $empty) {
$title = text_format($title, $empty);
return "<a href='#' onclick=\"open_window('{$url}', '{$target}', {$width}, {$height}, {$scrollbars})\">{$title}</a>";
}
// 나이(주민등록번호를 이용)
function AGE_jumin($lno,$rno) {
$refArray = Array(18,19,19,20,20,16,16,17,17,18);
$refyy = substr($rno,0,1);
$biryear = $refArray[$refyy] * 100 + substr($lno,0,2);
$nowyear = date("Y");
return $nowyear - $biryear + 1;
}
// URL 존재확인
function URL_exists($url) {
$url = str_replace("http://", "", $url);
list($domain, $file) = explode("/", $url, 2); // 도메인부분과 주소부분으로 나눕니다.
$fid = fsockopen($domain, 80); // 도메인을 오픈합니다.
fputs($fid, "GET /$file HTTP/1.0\r\nHost: $domain\r\n\r\n"); // 파일 정보를 얻습니다.
$gets = fgets($fid, 128);
fclose($fid);
if(ereg("200 OK", $gets)) return TRUE;
else return FALSE;
}
// 조사 꾸미기
$array = "뵤 벼 뱌 배 베 보 버 바 비 뷰 부 브 뱨 볘 봐 봬 붜 붸 뵈 뷔 븨 뾰 뼈 뺘 빼 뻬 뽀 뻐 빠 삐 쀼 뿌 쁘 뺴 뼤 뽜 뽸 뿨 쀄 뾔 쀠 쁴 죠 져 쟈 재 제 조 저 자 지 쥬 주 즈 쟤 졔 좌 좨 줘 줴 죄 쥐 즤 쬬 쪄 쨔 째 쩨 쪼 쩌 짜 찌 쮸 쭈 쯔 쪠 쪠 쫘 쫴 쭤 쮀 쬐 쮜 쯰 됴 뎌 댜 대 데 도 더 다 디 듀 두 드 댸 뎨 돠 돼 둬 뒈 되 뒤 듸 뚀 뗘 땨 때 떼 또 떠 따 띠 뜌 뚜 뜨 떄 뗴 똬 뙈 뚸 뛔 뙤 뛰 띄 교 겨 갸 개 게 고 거 가 기 규 구 그 걔 계 과 괘 궈 궤 괴 귀 긔 꾜 껴 꺄 깨 께 꼬 꺼 까 끼 뀨 꾸 끄 꺠 꼐 꽈 꽤 꿔 꿰 꾀 뀌 끠 쇼 셔 샤 새 세 소 서 사 시 슈 수 스 섀 셰 솨 쇄 숴 쉐 쇠 쉬 싀 쑈 쎠 쌰 쌔 쎄 쏘 써 싸 씨 쓔 쑤 쓰 썌 쎼 쏴 쐐 쒀 쒜 쐬 쒸 씌 묘 며 먀 매 메 모 머 마 미 뮤 무 므 먜 몌 뫄 뫠 뭐 뭬 뫼 뮈 믜 뇨 녀 냐 내 네 노 너 나 니 뉴 누 느 냬 녜 놔 놰 눠 눼 뇌 뉘 늬 요 여 야 애 에 오 어 아 이 유 우 으 얘 예 와 왜 워 웨 외 위 의 료 려 랴 래 레 로 러 라 리 류 루 르 럐 례 롸 뢔 뤄 뤠 뢰 뤼 릐 효 혀 햐 해 헤 호 허 하 히 휴 후 흐 햬 혜 화 홰 훠 훼 회 휘 희 쿄 켜 캬 캐 케 코 커 카 키 큐 쿠 크 컈 켸 콰 쾌 쿼 퀘 쾨 퀴 킈 툐 텨 탸 태 테 토 터 타 티 튜 투 트 턔 톄 톼 퇘 퉈 퉤 퇴 튀 틔 쵸 쳐 챠 채 체 초 처 차 치 츄 추 츠 챼 쳬 촤 쵀 춰 췌 최 취 츼 표 펴 퍄 패 페 포 퍼 파 피 퓨 푸 프 퍠 폐 퐈 퐤 풔 풰 푀 퓌 픠";
function lastCon($str) {
global $array;
if(ord($str[strlen($str)-1]) < 128) return false;
$str = substr($str, strlen($str)-2);
if(strstr($array, $str)) return false;
return true;
}
function ul_rul($str) {
return $str.(lastCon($str) ? "을" : "를");
}
function gwa_wa($str) {
return $str.(lastCon($str) ? "과" : "와");
}
function un_num($str) {
return $str.(lastCon($str) ? "은" : "는");
}
function i_ga($str) {
return $str.(lastCon($str) ? "이" : "가");
}
// 도메인 또는 문서가 존재하는지 검사
function exists_url($url, $port="80") {
$fp = @fsockopen($url, $port);
if($fp) return true;
else return false;
}
// 숫자를 한글로 바꾸기
function numtokor($num) {
$text ='';
$d_symbol = array('4' => "만", '8' => "억", '12' => "조", '16' => "경", '20' => "해", '24' => "시", '28' => "양", '32' => "구", '36' => "간", '40' => "정", '44' => "재", '48' => "극", '52' => "항하사", '56' => "아승지", '60' => "나유타", '64' => "불가사의", '68' => "무량대수");
$p_symbol = array('0' => "", '1' => "십", '2' => "백", '3' => "천");
$t_symbol = array('0' => "", '1' => "일", '2' => "이", '3' => "삼", '4' => "사", '5' => "오", '6' => "육", '7' => "칠", '8' => "팔", '9' => "구");
if(substr($num,0,1) == '-') {
$num = substr($num ,1);
$text .= '마이너스';
}
$length_of_num = strlen($num);
if($length_of_num > 72) {
$text = "존재할 수 없는 수치 입니다.";
} else {
//실행
for ($k=0; $k< $length_of_num; $k++) {
$striped_value = substr($num, $k, 1);
$text .= $t_symbol[$striped_value];
$power_value = ($length_of_num - $k -1) % 4;
if ($striped_value <> 0) $text .= $p_symbol[$power_value];
if ($power_value == 0) $text .= $d_symbol[$length_of_num - $k -1];
}
}
return $text;
}
//검색쿼리작성
function querystring($query) {
if($query) {
$queryarray = explode("&", $query);
$count = count($queryarray);
foreach($queryarray as $key => $value) {
$array2st = explode("=", $value);
if($array2st[1]) {
if($querystring) $querystring .= "&".$value;
else $querystring = $value;
}
}
return $querystring;
}
else return "";
}
//페이징
function pagelist($tables, $nowpage, $primarykey , $chartline, $chartpage, $wheres="", $findquery="", $others="", $orders="", $urlquery="", $lastopt=true, $allopt=true, $firstbutton="[처음]", $prebutton="[이전]", $nextbutton="[다음]",$lastbutton="[끝]") {
if($wheres) $wheres = " where {$wheres} ";
if($others) $wheres .= " and {$others} ";
if(!$chartline) $chartline = 10;
if(!$chartpage) $chartpage = 10;
if(intval($nowpage) == 0) $nowpage = 1;
if(intval($nowstep) == 0) $nowstep = 1;
##마지막버튼 유무 체크
if($lastopt) {
$query = "select count(*) count from {$tables} {$wheres} {$others} {$findquery}";
$result = mysql_query($query);
$total = mysql_fetch_object($result);
#총카운트 $total->count;
}
##총검색수
if($allopt) {
$query = "select count(*) count from {$tables} {$wheres}";
$result = mysql_query($query);
$all = mysql_fetch_object($result);
#총검색수 $all->count;
}
##설정값계산
$nowstep = ceil($nowpage/$chartpage);
if($lastopt) {
$allstep = ceil($total->count/($chartpage*$chartline));
$allpage = ceil($total->count/$chartline);
}
$startpage = 1 + ($nowstep-1) * $chartpage;
$endpage = $startpage + $chartpage - 1;
if($lastopt && $endpage > $allpage) $endpage = $allpage;
##다음버튼 유무 체크
$nextline = $nowstep * $chartline * $chartpage;
$nextlimitquery = " limit {$nextline}, 1";
$query = "select {$primarykey} from {$tables} {$wheres} {$others} {$findquery} {$nextlimitquery}";
$result = mysql_query($query);
$nextok = mysql_affected_rows();
##처음버튼 및 이전버튼
if($nowstep > 1) {
$fir = " <a href='$PHP_SELF?$urlquery&nowpage=1'>{$firstbutton}</a> ";
$prepage = $startpage - $chartpage;
$pre = " <a href='$PHP_SELF?$urlquery&nowpage=$prepage'>{$prebutton}</a> ";
} else {
$fir = " <font color='#C0C0C0'>{$firstbutton}</font> ";
$pre = " <font color='#C0C0C0'>{$prebutton}</font> ";
}
##NEXT 버튼 활성화
if($nextok) {
$nextpage = $endpage + 1;
$next = " <a href='$PHP_SELF?$urlquery&nowpage=$nextpage'>{$nextbutton}</a> ";
} else {
$next = " <font color='#C0C0C0'>{$nextbutton}</font> ";
}
##중간페이지
for($i=$startpage;$i<=$endpage;$i++) {
if($i == $nowpage) $pagelist .= " <font color='#6600FF'><b>$i</b></font> ";
else $pagelist .= " <a href='$PHP_SELF?$urlquery&nowpage=$i'>$i</a> ";
}
##끝페이지
if($lastopt && $allstep > $nowstep) {
$lastpage = $allpage;
$last = " <a href='$PHP_SELF?$urlquery&nowpage=$nextpage'>{$lastbutton}</a> ";
} else {
$last = " <font color='#C0C0C0'>{$lastbutton}</font> ";
}
$firstlimit = 0 + ($nowpage-1) * $chartline;
$limitquery = " limit {$firstlimit}, {$chartline}";
$query = "select * from {$tables} {$wheres} {$others} {$findquery} {$orders} {$limitquery}";
$result = mysql_query($query);
while($fetch = mysql_fetch_array($result)) $get[] = $fetch;
$get[0]["count"] = count($get);
$get[0]["page"] = $fir.$pre." [ ".$pagelist." ] ".$next.$last;
if($lastopt) $get[0]["total"] = $total->count;
if($allopt) $get[0]["allto"] = $all->count;
return $get;
}
//업로드
function file_upload($upfile,$upfile_name,$upfile_size,$dir,$newfilename) {
if($upfile_size) {
$is_file = is_file("{$dir}/{$newfilename}");
if($is_file) unlink("{$dir}/{$newfilename}");
move_uploaded_file($upfile, "{$dir}/{$newfilename}");
chmod("{$dir}/{$newfilename}", 0644);
return true;
} else return false;
}
//현재디렉토리
function nowdir() {
global $DOCUMENT_ROOT;
global $PHP_SELF;
$getdir = pathinfo($DOCUMENT_ROOT.$PHP_SELF);
return $getdir["dirname"];
}
음..자바스크립트에서 333,333,333 을 333333333으로 만드려고 asp처럼 단순히 replace 하면 333333,333 이런값을 반환한다.
따라서 정규 표현식 사용해야함...
var re = /,/g;
var txt = "333,333,333";
txt = txt.replace(re,"");
요렇게 한후 alert(txt) 찍어보면 333333333 나옴
*)
i(대/소문자를 구분하지 않음)
g(발생할 모든 패턴에 대한 전역 검색)
gi(전역 검색, 대/소문자를 구분하지 않음)
[출처] # 자바스크립트 // ora 오라클 실무 강좌|작성자 제로스엘