'03.HTML 4.X, HTML5, XML.../HTML/Css/Script'에 해당되는 글 196건

  1. 2009.04.07 현재페이지를 알아오는 방법
  2. 2009.04.07 쿠키정보를 확인하고 활용할수 있는 코드
  3. 2009.04.07 새창을 데이타 크기에 따라서 자동조절되는 프린트 화면
  4. 2009.04.07 javascript 디버깅 툴 - Companion.JS
  5. 2009.04.07 javascript 에서 html value 값을 버전관계없이 바꾸고 싶을때
  6. 2009.04.07 동적으로 테이블을 추가하는 방법과 Disable 처리 예제 1
  7. 2009.04.07 javascript 에서 input 값에 숫자이외의 글 입력막기
  8. 2009.04.07 Javascript 에서 알아야할 기초사항
  9. 2009.04.07 프로젝트 나가서 주로 공통으로 쓰는 javascript common.js 내용
  10. 2009.04.04 GET POST 방식 깔끔 정리
  11. 2009.04.04 HTML Codes
  12. 2009.04.03 location.replace() 와 location.href 의 차이
  13. 2009.03.18 jsp, 자바스크립트, 다음부터 이 창을 띄우지 않음
  14. 2009.03.10 XHTML/CSS를 이용한 구조화 및 개발방법론 2
  15. 2009.01.30 html 입력모드 : ime-mode 1
  16. 2009.01.29 div 모든것...
  17. 2009.01.28 Mysql 자동 백업 하기
  18. 2009.01.28 스크립트 태그의 CDATA 사용에 대해서
  19. 2009.01.28 input type="file"에서 찾아보기 버튼 바꾸기
  20. 2009.01.28 잘못된 Javascript의 사용에 대해서....
  21. 2009.01.28 팝업 또는 새창에 관한 정리
  22. 2009.01.28 XHTML 사용에 대한 정리
  23. 2009.01.28 제발 a href="#" 좀 쓰지 말자.... 1
  24. 2009.01.28 괜찮은 클라이언트사이드 IDE : aptana Studio 1
  25. 2009.01.28 외부 Javascript 파일 압축하기
  26. 2009.01.28 괜찮은 클라이언트사이드 IDE : aptana Studio
  27. 2009.01.28 script.aculo.us의 Sortable로 드래그앤드롭(DragNDrop) 사용하기
  28. 2009.01.28 jQuery로 작업하기, 3부: jQuery와 Ajax로 RIA 만들기
  29. 2009.01.23 도메인이 다른 경우 자바스크립트 연동
  30. 2009.01.23 cookie 정보 확인 스크립트
반응형

자바스크립트 객체의 종류와 설명이다
document : 현재 웹 페이지의 본문을 나타낸다. 이 객체를 사용하면 링크(link), 이미지, 앵커(anchor) 등과
                같은 웹 페이지의 모든 구성요소에 접근할 수 있다.

history : 웹 브라우저에서 현재 페이지를 열기 전까지의 사이트 기록을 같고있다. 이객체를 사용하면,
            히스토리(history) 목록을 통해 이전 페이지 또는 다음 페이지로 이동할 수 있다.

location : 현재 웹 페이지의 위치에 대한 URL, 도메인이름, 경로, 서버포트 등의 정보를 갖는다.

navigator : 실제로 브라우저 자체를 가리킨다. 이 객체를 사용하면, 사용중인 브라우저의 종류를 알아낼 수 있다.

window : 현재 브라우저 창을 가리키며, 여러가지 강력한 메소드들을 제공한다.
             Internet Explorer에서는 event라는 하위 객체를 사용하여 이벤트를 처리할 수 있다.

■ location 객체 프로퍼티

href 문서의 URL 주소 위 주소 전체
host 호스트 이름과 포트 http://www.codewiz.co.kr:80
hostname 호스트 컴퓨터이름 http://www.codewiz.co.kr
hash 앵커이름 #top
pathname 디렉토리 이하 경로 /column2/list.asp
port 포트번호 부분 80
protocol 프로토콜 종류 http:
search URL 조회부분 table=table30&page=2

location 객체 메서드
eval() 문자열을 숫자로 바꿈
toString() 오브젝트를 문자열로 바꿈
reload() 현재 문서를 다시 읽어옴
replace() 현재 문서를 다른 URL 문서로 바꿈
valueOf() 오브젝트 값을 표시
toSource() 오브젝트 값을 문자열로 표시

■ 활용예제

<script language="javascript">
// URL을 이동시킴
location.href= http://codewiz.com
//location.href= "login.html"
</script>
<script language="javascript">
alert("회원가입을 하시겠습니까?")
location.href= "member.html"
</script>
<script language="javascript">
// 연 창의 URL 이동
opener.location.href= "member.html"
</script>
<script language="javascript">
// 부모창 지정프레임의 URL 이동
parent .frame1.location.href= "member.html"
</script>
<script language="javascript">
// 전체창에 새 페이지 열기
top.location.href= "index.html"
</script>


활용예제이다.
// 역슬레쉬로 구분해서 배열을 만든다
var path = parent.frames["input"].location.pathname.split('/');
// 배열의 마지막 요소의 값을 저장한다
var temp = "";
temp = path[path.length - 1];


출처 : http://mainia.tistory.com/entry/현재페이지를-알아오는-방법

Posted by 1010
반응형

전체 쿠키 정보를 Text 로 출력한다 . 모든 쿠키에 대한 정보를 알아볼려면  document.cookie 를 호출하면 된다. 집어 넣는 곳은 cookieOut 이라는 DIV 내에 Text 를 출력하는  로직이다.
// 모든 쿠키출력
function viewCookie()
{
   if( document.cookie.length > 0 )
      cookieOut.innerText = document.cookie;
   else
      cookieOut.innerText = "저장된 쿠키가 없습니다.";
}
// 출력화면
<DIV id = "cookieOut"></DIV>


저장된 쿠키값을 쿠키명으로 검색해서 넘겨주는 함수이다.
// param : 쿠키명
// return : 쿠키값
function getCookie( cookieName )
{
   var search = cookieName + "=";
   var cookie = document.cookie;

   // 현재 쿠키가 존재할 경우
   if( cookie.length > 0 )
   {
       startIndex = cookie.indexOf( cookieName );// 해당 쿠키명이 존재하는지 검색후 위치정보를 리턴.

       if( startIndex != -1 ) // 존재한다
      {
         startIndex += cookieName.length;// 값을 얻어내기 위해 시작 인덱스 조절
         endIndex = cookie.indexOf( ";", startIndex );// 값을 얻어내기 위해 종료 인덱스 추출
         if( endIndex == -1) endIndex = cookie.length; // 만약 종료 인덱스 못찾으면 쿠키 전체길이로 설정

         return unescape( cookie.substring( startIndex + 1, endIndex ) );// 쿠키값을 추출하여 리턴
      } else {
         return false; // 존재하지 않을때
      }
   } else {
      return false; // 쿠키 아예없을때
   }
}

쿠키값을 설정한다. 파라미터로는 쿠키명, 쿠키값, 쿠키날짜를 넘긴다
function setCookie( cookieName, cookieValue, expireDate )
{
   var today = new Date();
   today.setDate( today.getDate() + parseInt( expireDate ) );
   document.cookie = cookieName + "=" + escape( cookieValue ) + "; path=/; expires=" +                
           today.toGMTString() + ";"
}


쿠키명을 넘겨 해당하는 쿠키를 삭제한다
function deleteCookie( cookieName )
{
   var expireDate = new Date();
 
   //어제 날짜를 쿠키 소멸 날짜로 설정한다.
   expireDate.setDate( expireDate.getDate() - 1 );
   document.cookie = cookieName + "= " + "; expires=" + expireDate.toGMTString() + "; path=/";
}



Posted by 1010
반응형
부모창에서 자식 새창으로 submit 데이타를 보낼때 자식창에선 그것을 데이타 크기에 맞게
늘렸다 줄였다 할수있다. 이것은 프린트 공통 화면을 만들때 유용하게 쓰인다.
내용은 화면이 시작되고 나서 밑쪽에 initWindow 함수가 실행되게 된다.

<html>
<head>
#parse("common/common_head.vm")
<link href="${rc.contextPath}/css/ord.css" rel="stylesheet" type="text/class" />
<script language="JavaScript">
<!--
 // submit 넘어오는 html 데이타를 화면 크기에 맞게 배치해준다.
 function initWindow(win){
    var winBody = win.document.body;
    // 새창의 사이즈에 더해줄 marginWidth 와 marginHeight
    var marginHeight = parseInt(winBody.topMargin)+parseInt(winBody.bottomMargin);
    var marginWidth = parseInt(winBody.leftMargin)+parseInt(winBody.rightMargin);
    // 새창의 사이즈 설정
    var wid = winBody.scrollWidth + (winBody.offsetWidth - winBody.clientWidth) + marginWidth - 5;
    var hei = winBody.scrollHeight + (winBody.offsetHeight - winBody.clientHeight) + marginHeight + 17;
    // 사이즈 재조정
    win.resizeTo(wid, hei);
 }
 
 var initBody; // 프린트 실행전 내용이 담기는 공간
 function beforePrint(){
    initBody = document.body.innerHTML;
    document.body.innerHTML = resultPrint.innerHTML;
 }
 function afterPrint(){
    document.body.innerHTML = initBody;
 }
 function printArea(){
    window.print();
 }
 window.onbeforeprint = beforePrint; // 프린트 하기 이전의 내용실행 해서  body 의 내용을 바꾼다.
 window.obafterprint = afterPrint; // 프린트 후 함수를 실행하여 이전에 저장해놨던 정보로 내용을 바꾼다.
//-->
</script>
</head>
<body>
 <table width="100%" border="0" cellspacing="0" cellpadding="10">
   <tr>
     <td valign="top">
     <DIV id="resultPrint">
      $!{print}
     </DIV>
     </td>
   </tr>
   <tr>
    <td><a href="javascript:printArea();"> 프린트 하기 </a></td>
     </tr>
 </table>
 <script language='javascript'>
 <!--
  initWindow(this);
 //-->
 </script>
</body>
</html>

Posted by 1010
반응형
javascript 가 복잡해지면 에러를 찾기가 만만치 않다. 그래서 브라우저에 포함된 디버깅툴이 있다면
상당히 프로그램하기에 편할뿐더라 생산성 또한 높일수 있을것이다.
파이어폭스 플러그인 Firebug 의 콘솔 API 와 유사한데 IE 사용할수 있다.
Companion.JS 이며 http://www.my-debugbar.com/wiki/CompanionJS/Homepage 에서 다운받을수있다.

이프로그램을 먼저 설치하기 전에 Microsoft Script Debugger 를 먼저설치한다.
http://www.microsoft.com/downloads/details.aspx?familyid=2f465be0-94fd-4569-b3c4-dffdf19ccd99&displaylang=en

다음은 스크립트 디버딩사용안함 을 체크해제한다.

사이트에 가서 다운로드 한다.

설치를 하게 되면 익스플로어에 다음과 같이 설치가 된다.

아래 그림과 같이 디버깅 창이 나오게 된다.
Posted by 1010
반응형

브라우저의 종류에 따라서 text 값을 바꾸는 방식이 모두다 적용되는것은아니다.
아래 내용은 IE6, Netscape 6.2 and 7, Firefox 1.04,  Opera 8 on the PC. 동일하게 적용되는
과정을 알아본다.

<input type="button"> 선언된 버튼의 value 값을 바꿔보는데
첫번째 예제는  getElementById("ID").value 변수로 값을 바꾸는 방식이다

<input type="button" value="Button Text" id="myButton1"></input>
document.getElementById("myButton1").value="New Button Text";

위의 방식은 IE6 에서는  "Unknown Runtime Error; Netscape 7 에서는  won't change the text
에러가 날것이다. 그래서 두번째는 innerHTML 을 사용해서 바꾸는 방식이다.

document.getElementById("myButton1").innerHTML="New Button Text";

다음은 버튼 태그 사이의 text  값을 바꿔본다.
innerHTML 을 사용해서 바꾸었다.

document.getElementById("myButton2").innnerHTML=  "New Button Text using innerHTML";
<button type="button" id="myButton2">Button Label</button>

위의 방식은 Netscape 6.2 and 7.02 에서 쓰레기 값을 가져오게 되어 에러가 발생한다.
그래서 childNodes  를 아래와 같이 사용한다.
이와 같이 값을 바꾸고자 할때 버전에 구애받지 않게 적용하고 싶을 것이다.
아래의 함수는 처음에 childNodes 바꿀수 있는지 체크해서 시도하고 그게 안된다면 value 로 적용한다
그리고 그것도 안된다면 innerHTML 을 사용하는 전천후 함수이다.

<SCRIPT LANGUAGE="JavaScript">

<!--

function replaceButtonText(buttonId, text)

{

  if (document.getElementById)

  {

    var button=document.getElementById(buttonId);

    if (button){

      if (button.childNodes[0]){

        button.childNodes[0].nodeValue=text;

      }

      else if (button.value){

        button.value=text;

      }

      else //if (button.innerHTML){

        button.innerHTML=text;

      }

    }

  }

}

//-->

</SCRIPT>

replaceButtonText('myButton1', 'new button text');

Posted by 1010
반응형

<script language="javascript">

<!--

function add(){

   var target = document.getElementById("dynamicTable");

   var currentRowIndex = target.rows.length;

   var row = target.insertRow(-1);

   var cell = row.insertCell(-1);

   cell.innerHTML = "<input type='text' name='point"+ currentRowIndex +

         "' size='5' maxlength=='5' value='20'>&nbsp;&nbsp;" +

         "<select name='scope" + currentRowIndex + "'>" +

         "<option>초과</option>" +

         "<option>이상</option>" +

         "<option>이하</option>" +

         "<option>미만</option>" +

         "</select>";

}

 

function checkToggle(form){

   var i=1;

   var isDisabled = (form.auto.checked) ? true : false;

   while(true){

      var scopeElement = form["scope" + i];

      var pointElement = form["point" + i++];

      if (scopeElement){

          scopeElement.disabled = isDisabled;

          pointElement.disabled = isDisabled;

      }else{

          break;

      }

   }

}

//-->

</script>

</head>

 

<body>

<form name="form">

   <input type="checkbox" name="auto" onclick="checkToggle(this.form)"> Disabled 된다

   <input type="button" value="add" onclick="add()">행추가

   <table id="dynamicTable" border="0" cellpadding="5" cellspacing="1" align="center">

     <thead>

       <tr align="center">

         <td width="130">점수</td>

       </tr>

     </thead>

     <tbody>

        <tr align="center">

           <td colspan="4">

      <input type="text" name="point1" size="5" maxlength="5" value="20">

      &nbsp;&nbsp;

              <select name="scope1">

                 <option>초과</option>

                 <option>이상</option>

                 <option>이하</option>

                 <option>미만</option>

              </select>

            </td>

        </tr>

     </tbody>

  </table>

</form>

</body>
Posted by 1010
반응형
javascript 에서 input 값에 숫자이외의 글을 넣었을때 더이상 입력이 되지 않도록 막는 소스이다.

<script language="JavaScript">
function checkForNumber() {
  var key = event.keyCode;
  if(!(key==8||key==9||key==13||key==46||key==144||
      (key>=48&&key<=57)||key==110||key==190)) {
      event.returnValue = false;
  }
}
</script>

javascript 함수는 위의 것을 쓰면되고 Input 에 key 입력시 event 객체가 가로채서 그 내용을
분석한후 event.returnValue = false 리턴하게 되면 더 이상 키의 값을 입력할수 없게 해준다.
이것을 활용하여 여러가지 입력형태의 제한을 만들어서 사용하면 유용할 것이다

<input type="text" name="aaa" style="ime-mode:disabled;" onkeypress="checkForNumber();">
Posted by 1010
반응형

DOM 객체의 기본 구조도를 알아야한다. 이객체들이 어디에 속해있는지 표를 보고 알아야할것이다


1.
내장함수

(1) 내장메시지 함수

alert("Hello."); confirm("정말로 삭제할껴?"); prompt(메시지, 초기값);

 

(2) 일반내장 함수

isFinite(number) : number한수이면 true, 아니면 false를 리턴

isNaN(value) : value가 순수한 문자이면 true, 숫자형태의 문자이면 false를 리턴

number(obj) : obj를 숫자로 변환하여 리턴

string(obj) : obj를 문자로 변환하여 리턴

eval(수식문자열 또는 Object 문자열) : 수식을 처리한 결과를 리턴, Object로 변환하여 리턴

parseInt(문자열, [진수]) : 문자열을 정수로 변환하여 리턴

parseFloat(문자열) : 문자열을 float-실수형으로 변환하여 리턴

escape(string) : ASCII 스트링을 URL로 인코딩

unescape(string) : ASCII 스트링을 URL로 디코딩

encodeURI(string) : 주어진 문자열을 URI encoding 한다.

decodeURI(string) : 주어진 문자열에서 encoding URI decoding 한다.

encodeURIComponent(string) : 주어진 문자열을 URI encoding 한다.

decodeURIComponent(string) :  주어진 문자열에서 encoding URI decoding 한다.

 

(3) 문자인코딩 함수

encodeURI() / decodeURI() : 다음문자만 인초딩한다  è  ; / ? : @ & = + $ , - _ . ! ~ * ' ( ) #

encodeURIComponent() / decodeURIComponent() :

알파벳과 숫자 Alphanumeric Characters 외의, 대부분의 문자를 모두 인코딩한다.

escape() / unescape() : encodeURI() encodeURIComponent() 의 중간 정도의 범위로 문자 인코딩

 

2. 내장 객체

(1) Object 객체

var book = new Object(); // empty Object --> var book = {};

book.title = "내장객체";

book.author = "kspark";

book.published_date = new Array('2006', '2007');

book.getInformation = function() { return this.title + ", " + this.author; }

 

function DisplayPropertyNames(obj){

             var names = "";

             for( var name in obj ) names += name + "\n";

             alert(names);

             alert(obj.getInformation());

}.

 

(2) Function 객체 : 함수 객체, 객체변수 = new Function([매개변수 리스트], 함수의 처리 내용)

var square = function(x) { return x*x }

var sports = new Object();

sports.soccer = new Function('var name = "soccer"; return name;');

var sum = new Function( "x", "y", "return x+y" );

function execute(){

   alert( "Sports name : " + sports.soccer() );

   alert( "sum : " + sum(5,10) );

}

 

(3) Array 배열 객체

length 속성, join(문자열),reverse(),sort(compareFunction),slice(시작위치,종료위치),concat(배열객체)

var list = new Array();

 

(4) Date 날짜 객체

var date = new Date();

 

getDate, getDay, getFullYear, getHours, getMilliseconds, getMinutes, getMonth,

getSeconds, getTime,  getTimezoneOffset, getUTCDate, getUTCDay,

getUTCFullYear, getUTCHours, getUTCMilliseconds, getUTCMinutes,

getUTCMonth, getUTCSeconds, getYear, parse, setDate, setFullYear, setHours,

setMilliseconds, setMinutes, setMonth, setSeconds, setTime, setUTCDate,

setUTCHours, setUTCMilliseconds, setUTCMinutes,  setUTCMonth, setUTCSeconds,

setYear, goGMTString, toLocaleString, toString, toUTCString, UTC, valueOf

 

(5) String 객체

문자열 조작 메소드

toLowerCase(), toUpperCase(), charAt(인덱스), substring(인덱스1, 인덱스2), slice(인덱스1, 인덱스2),

substr(시작인덱스, 길이), indexOf(문자열), lastIndexOf(문자열), concat(문자열), split(분리자, [개수]), charCodeAt([인덱스]), fromCharCode(숫자)

 

글자 모양을 변경하는 메소드

big(), small(), blink(), bold(), fixed(), italics(), strike(가운데줄), sub(아래첨자),sup(위첨자),

fontcolor(""), fontsize(크기)

 

위치 이동하는 메소드

anchor("책갈피명"), link("이동위치");

 

var str = "Hello! David";

str.slice(6, str.length);   str.link(#david);

 

(6) 수학관련 객체 Math : 각종 수학적 계산을 돕는 Math 객체

Math.PI, Math.sin(x), Math.abs(x), Math.max(x,y)

 

(7) 수치관련 객체 Number

수치 형태의 문자열을 수치 데이터로 변환하는 객체, new Number(수치 형태의 문자열);

var Ten = new Number("10");

 

(8) 논리형 객체 Blooean : 논리 객체, new Boolean(논리값);

 

(9) 스크린 화면 객체 Screen : Screen.availWidth, availHeight(화면의 실제 너비, 높이 ),

Screen.width, height(스크린 실제 너비, 높이), pixelDepth(익스플로워 지원안됨),

colorDepth(사용가능색상수)

 

(10) Event : 이벤트 객체

이벤트 함수의 종류

Abort (onAbort) : 문서를 읽다가 중단시켰을때(브라우저에서 멈춤을 눌렀을때)

Blur (onBlur) : 사용자가 입력을 포커스를 원도우나 입력양식 요소에서 제거했을때

Click (onClick) : 사용자가 입력 양식의 요소나 링크를 클릭 했을때

Change (onChange) : 사용자가 요소의 값을 바꾸었을 때

DblClick (onDblclk) : 사용자가 입력 양식의 요소나 링크를 더블 클릭 했을때

DragDrop (onDragDrop) : 마우스를 드래그 하는 순간 발생

Error (onError) : 문서나 이미지를 읽는 중에 강제로 중지하는 순간 발생

Focus (onFocus) : 사용자가 입력 포커스를 원도우나 입력 양식의 요소로 이동했을 때

KeyDown (onKeyDown) : 사용자가 키를 눌렀을때

KeyPress (onKeyPress) : 사용자가 키를 누르고 있을때

KeyUp( onKeyUp) : 사용자가 눌렀던 키를 놓았을때

Load(onLoad) : 브라우저에서 문서을 읽었을때

MouseDown(onMouseDown) : 마우스를 누르는 순간 발생함

MouseMove(onMouseMove) : 마우스가 움직일 때

MouseOver(onMouseOver) : 사용자가 link anchor위로 마우스로 옮겼을때

MouseOut(onMouseOut) : 마우스가 특정 영역 안에 있다가 나갔을때

MouseUp(onMouseUp) : 마우스 커서를 이미지 맵이나 링크 위에서 내려 놓을 때

Move(onMove) : 윈도우나 프레임의 위치가 이동되는 순간 발생

Reset (onReset) : 사용자가 입력 양식을 초기화 했을 때

 

이벤트에서 발생하는 객체들의 종류이며 , 네스케이프와 익스플로어의 경우를 따로 분리했다.

[네스케이프  에서의 이벤트 객체]

data : DragDrop 이벤트로 인해 드롭된 객체의 URL이 들어있는 스트링 배열

height, width : 윈도우나 프레인의 길이와 너비(픽셀표시)

pageX, pageY : 픽셀로 나타낸 커서의 수평/수직 위치(페이지에서의 상대적위치)

screenX, screenY : 픽셀로 나타낸 커서의 수평/수직 위치(화면에서의 상대적 위치)

layerX, layerY : 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 레이어에 대한 상대적 위치.

target : 이벤트가 전송된 원래 객체

type : 발생한 이벤트 유형

which : 눌려진 마우스 버튼(left:1, middle:2, right:3)이나 눌려진 키의 ASCII

modifiers : 마우스나 키 이벤트와 연관된 수정자 키

(ALT_MASK,CONTROL_MASK,SHIFT_MASK,META_MASK) 를 식별

 

[익스플로어 에서의 이벤트 객체]

screenX, screenY : 픽셀로 나타낸 커서의 수평/수직 위치(화면에서의 상대적 위치)

clientX, clientY : 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 웹페이지에서의 상대적 위치

offsetX, offsetY : 픽셀로 나타낸 커서의 수평/수직 위치,이벤트가 발생한 컨테이너에 대한 상대적 위치

X, Y : 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 문서에 대한 상대적 위치

srcElement : 이벤트가 전송된 원래 객체

type : 발생한 이벤트 유형

keyCode : 키 누름과 연관된 Unicode 키 코드를 식별

button : 이벤트가 발생했을 때 눌려진 마우스 버튼 식별(0:눌려진버튼없음, 1:, 2:, 4:)

altkey,ctrlkey,shiftkey : true false로 설정하여 이벤트가 발생했을 때 Alt키와 Control, Shift 키 중에 어떤 것이 눌려졌는지 알려준다.

cancelBubble : true false로 설정하여 이벤트 버블링을 취소하거나 활성화한다.

fromElement, toElement : 이동 중인 HTML 요소 지정

reason : 데이터 소스 객체에 대한 데이터 전송 상태를 나타내는데 사용

returnValue : true false로 설정하여 이벤트 핸들러의 리턴값을 나타낸다. 이벤트 핸들러에서 true false를 리턴하는 것과 같다.

 

위에서 열거한 이런 내용을 암기는 하지 못하더라도 모두 이해하고 어떤경우에 쓰이는지를

파악하고 있어야하겠다. 자바스크립트를 사용하는 사람들의 가장 기본적으로 갖추어야 하는 지식이다.



출처 : http://mainia.tistory.com/entry/Javascript-에서-알아야할-기초사항

Posted by 1010
반응형
프로젝트에 나가 주로 쓰이는 자바스크립트 함수를 모아 놓은것이다. 필요하다 싶으면 이 페이지에
업데이트하여 필요할때 복사해 쓸 작정이다.

 

/**

 * 입력값이  null 인지 체크한다

 */

function isNull(input){

       if (input.value == null || input.value == ""){

             return true;

       }else{

             return false;

       }

}

/**

 * 입력값이 스페이스 이외의 의미있는 값이 있는지 체크한다

 * if (isEmpty(form.keyword)){

 *       alert('값을 입력하여주세요');

 * }

 */

function isEmpty(input){

       if (input.value == null || input.value.replace(/ /gi,"") == ""){

             return true;

       }else{

             return false;

       }

}

/**

 * 입력값에 특정 문자가 있는지 체크하는 로직이며

 * 특정문자를 허용하고 싶지 않을때 사용할수도 있다

 * if (containsChars(form.name, "!,*&^%$#@~;")){

 *       alert("특수문자를 사용할수 없습니다");

 * }

 */

function containsChars(input, chars){

       for (var i=0; i < input.value.length; i++){

             if (chars.indexOf(input.value.charAt(i)) != -1){

                    return true;

             }

       }

       return false;

}

/**

 * 입력값이 특정 문자만으로 되어있는지 체크하며

 * 특정문자만을 허용하려 할때 사용한다.

 * if (containsChars(form.name, "ABO")){

 *    alert("혈액형 필드에는 A,B,O 문자만 사용할수 있습니다.");

 * }

 */

function containsCharsOnly(input, chars){

       for (var i=0; i < input.value.length; i++){

             if (chars.indexOf(input.value.charAt(i)) == -1){

                    return false;

             }

       }

       return true;

}

/**

 * 입력값이 알파벳인지 체크

 * 아래 isAlphabet() 부터 isNumComma()까지의 메소드가 자주 쓰이는 경우에는

 * var chars 변수를 global 변수로 선언하고 사용하도록 한다.

 * var uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

 * var lowercase = "abcdefghijklmnopqrstuvwxyz";

 * var number = "0123456789";

 * function isAlphaNum(input){

 *       var chars = uppercase + lowercase + number;

 *    return containsCharsOnly(input, chars);

 * }

 */

function isAlphabet(input){

       var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

       return containsCharsOnly(input, chars);

}

/**

 * 입력값이 알파벳 대문자인지 체크한다

 */

 function isUpperCase(input){

       var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

       return containsCharsOnly(input, chars);

 }

/**

 * 입력값이 알파벳 소문자인지 체크한다

 */

function isLowerCase(input){

       var chars = "abcdefghijklmnopqrstuvwxyz";

       return containsCharsOnly(input, chars);

}

/**

 * 입력값이 숫자만 있는지 체크한다.

 */

function isNumer(input){

       var chars = "0123456789";

       return containsCharsOnly(input, chars);

}

/**

 * 입려값이 알파벳, 숫자로 되어있는지 체크한다

 */

function isAlphaNum(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 형식은 자바스크립트의 'reqular expression' 참고한다

 */

function isValidFormat(input, format){

       if (input.value.search(format) != -1){

             return true; // 올바른 포멧형식

       }     

       return false;

}

/**

 * 입력값이 이메일 형식인지 체크한다

 * if (!isValidEmail(form.email)){

 *       alert("올바른 이메일 주소가 아닙니다");

 * }

 */

function isValidEmail(input){

       var format = /^((\w|[\-\.])+)@((\w|[\-\.])+)\.([A-Za-z]+)$/;

       return isValidFormat(input, format);

}

/**

 * 입력값이 전화번호 형식(숫자-숫자-숫자)인지 체크한다

 */

function isValidPhone(input){

       var format = /^(\d+)-(\d+)-(\d+)$/;

       return isValidFormat(input, format);

}

/**

 * 입력값의 바이트 길이를 리턴한다.

 * if (getByteLength(form.title) > 100){

 *    alert("제목은 한글 50 (영문 100) 이상 입력할수 없습니다");

 * }

 */

function getByteLength(input){

       var byteLength = 0;

       for (var inx = 0; inx < input.value.charAt(inx); inx++)     {

             var oneChar = escape(input.value.charAt(inx));

             if (oneChar.length == 1){

                    byteLength++;

             }else if (oneChar.indexOf("%u") != -1){

                    byteLength += 2;

             }else if (oneChar.indexOf("%") != -1){

                    byteLength += oneChar.length / 3;

             }

       }

       return byteLength;

}

/**

 * 입력값에서 콤마를 없앤다

 */

function removeComma(input){

       return input.value.replace(/,/gi,"");

}

/**

 * 선택된 라디오버튼이 있는지 체크한다

 */

function hasCheckedRadio(input){

       if (input.length > 1){

             for (var inx = 0; inx < input.length; inx++){

                    if (input[inx].checked) return true;

             }

       }else{

             if (input.checked) return true;

       }

       return false;

}

/**

 * 선택된 체크박스가 있는지 체크

 */

function hasCheckedBox(input){

       return hasCheckedRadio(input);

}



Posted by 1010
반응형

웹 문서에서 아이디나 비밀번호 또는 다른 데이터 들을 서버측 으로 보낸 다음 수행이 되는 경우가 있다. 이때 문서에서 서버측 으로 데이터가 전달되는 방법이 2가지가 있는데 GET 방식과 POST방식이다. 각각의 방식들은 나름대로의 장단점을 가지고 데이터를 전달하는 역할을 한다.


GET 방식

1.웹 브라우저의 주소 입력란에서 아래와 같이 직접 입력하여도 데이터를 서버로 전송한다.(클라이언트로 부터의 데이터를 이름과 값이 겨합된 스트링 형태로 전달 하므로 각각 이름과 값은 “&”를 이용하여 결합한다.

ex) (http://localhost/chs/book/Request.jsp?Name=Michael&Depy=Computer)

2.기본적으로 데이터베이스에 대한 질의어 데이터와 같은 요청을 위한 정보를 전송할 때 사용

3.GET방식으로 보낼때는 같이 딸려가는 글자수에 제한이 있다(255자).

4.GET 방식을 사용하면 이를 초과하는 데이터가 절단된다.

5.GET 방식을 사용하면 데이터가 주소 입력란에 표시되므로 최소한의 보안도 유지되지 않는다.

6.GET 방식은 정보를 URL의 끝에 질의 문자열로서 서버로

Posted by 1010
반응형

HTML Codes
Again, nothing to do with ASCII really, but has been requested by a number of you out there. To get special characters to show on an HTML web page, special codes can be used (ascii code or word) and are interpretted by the web browser.
Posted by 1010
반응형

1번페이지에서 2번페이지로와서 2번 페이지에서 링크를 클릭했다고 하자 링크는 2개이다.

location.replace("www.naver.com")과

location.href="www.naver.com"

이다.

replace의 경우 네이버에서 뒤로가기를 눌렀을경우 뒤로가는페이지는 1번페이지가 된다.

href의 경우 2번페이지이다.

replace는 히스토리를 덮어버리는 기능을 하는것이다.

history.length를 참조해보자.



----------  테스트 -------

<a href="#" onclick='document.location.replace("http://www.naver.com");return false;'> replcae</a>

<a href="#" onclick='document.location.href="http://www.naver.com";return false;'> href</a>


위에걸 html 페이지를 생성해서

넣은후 각각 클릭해보자

href는 누른후에 뒤로가기가 활성화돼지만

replace는 활성화가 돼지 않는다.

Posted by 1010
반응형

다음부터 이 창을 띄우지 않음

2001. 4. 9.

개 요

어느 정도 규모가 있는 사이트에서는(심지어는 개인 홈페이지에서도) 중요한 공지사항이 있을 때에는 별도의 작은 창을 띄워서 해당 내용을 표시하는 경우가 많다. 이러한 별도의 창은 처음 접속하는 사용자인 경우에는 필요한 경우가 많지만, 같은 내용을 여러 번 보는 것을 방지하기 위하여 자체적으로 "다음부터 이 창을 띄우지 않음"과 같은 선택 옵션을 제공하는 경우가 많다. 이러한 기능을 구현하기 위하여 CGI와 DB를 사용하는 경우도 있지만, 쿠키와 자바스크립트만을 이용해서도 같은 효과를 거둘 수 있다.

쿠키 다루기

쿠키를 제어하는 함수를 제작하기 전에, 쿠키의 구조부터 살펴보도록 하겠다. 쿠키는 일반적으로 다음과 같은 형태를 가지는 일련의 문자열로 구성되어 있다.

쿠키변수=쿠키값; path=유효한디렉토리; expires=만료일

쿠키를 참조하는 객체는 자바스크립트에서 document.cookie 객체이며, 이를 이용하여 쿠키를 설정하고 값을 참조하는 함수를 다음과 같이 범용적인 용도로 작성할 수 있다.

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))
    }
  }
}

쿠키로 제어하는 공지창 호출

이제, 특정 쿠키의 값에 따라서 새 창을 열 것인지의 여부를 결정하여 수행하는 함수를 작성해보자. 쿠키변수의 이름은 notice로 하고, 이 notice의 값이 deny이면 공지 창을 띄우지 않는 기능을 가진 openNotice() 함수를 만든다.

function openNotice() {
  if (getCookie("notice") != "deny") {
    window.open("notice.htm","notice",
      "width=320,height=240,resizable=yes");
  }
}

위의 함수는 첫 페이지에서 onLoad 이벤트 핸들러에 연결하여 사용할 수 있다. 이제 열리는 대상 창에서 사용자가 앞으로 이 창을 띄우지 않는 것을 선택하는 폼을 구성한다.

<form name="notice">
<input type="checkbox" name="neveropen">
다음부터 이 창을 열지 않음
<input type="submit" value="확 인" onClick="Setting(document.notice)">
</form>

Setting() 함수의 용도는 쿠키변수인 notice에 deny라는 값을 대입시켜서 쿠키를 설정하는 기능이며, 쿠키가 설정된 다음에는 해당 창을 닫는다.

function Setting(form) {
  var expdate = new Date();
  expdate.setTime(expdate.getTime() + 1000 * 3600 * 24 * 365); // 365일
  if (form.neveropen.checked) {
    setCookie('notice', "deny", expdate);
  }
  window.close();
}

만료일의 경우에는 현재 시각을 기준으로 하여 1년 이후까지를 유효일로 설정하였다. 이 수치를 조정하여 공지사항을 띄우지 않을 기간을 마음대로 조정할 수 있다. 또한, 새로운 공지사항인 경우에는 deny가 아닌 새로운 값이나 새로운 쿠키 변수명을 사용하여 활용할 수도 있으므로, 실제로 이 코드를 참조하여 적용할 때에는 쿠키변수명과 쿠키의 값을 용도에 맞게 변경해서 사용해야 할 것이다.

최종 소스파일

지금까지 설명한 메인화면 코드와 공지창 코드 전체를 정리하면 다음과 같다.

메인 화면

<html>
<head>
<title>쿠키를 이용한 새창 제어</title>
<script language="javascript">
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))
    }
  }
}

function openNotice() {
  if (getCookie("notice") != "deny") {
    window.open("notice.htm","notice",
      "width=320,height=240,resizable=yes");
  }
}
</script>
</head>
<body onLoad="openNotice()">
<h1>쿠키를 이용한 새창 제어</h1>

</body>
</html>

공지사항 화면

<html>
<head>
<title>공지사항</title>
<script language="JavaScript">
function setCookie (name, value, expires) {
  document.cookie = name + "=" + escape (value) +
    "; path=/; expires=" + expires.toGMTString();
}

function Setting(form) {
  var expdate = new Date();
  expdate.setTime(expdate.getTime() + 1000 * 3600 * 24 * 365); // 365일
  if (form.neveropen.checked) {
    setCookie('notice', "deny", expdate);
  }
  window.close();
}
</script>
</head>
<body>
<h1>공지사항</h1>
<form name="notice">
<input type="checkbox" name="neveropen">
다음부터 이 창을 열지 않음
<input type="submit" value="확 인" onClick="Setting(document.notice)">
</form>
</body>
</html>
Posted by 1010
반응형




XHTML/CSS를 이용한 구조화 및

개발방법론








이성노 (eouia0819@gmail.com)





1. 들어가며


이 강연은 청중들이 XHTML 및 CSS에 대 한 기본적인 선행학습이 된 상태임을 전제로 진행된다.

접근성, 웹표준화, CSS 기법 등은 다른 시간에 다루게 될 것이므로 이 시간은 실제 XHTML과 CSS를 이용한 웹사이트 개발을 위한 개발 방법론에 중점을 둘 예정이다.


Ref . 1 .


XHTML

현재 HTML은 4.01까지만 완성되어 있으며, XHTML이 HTML을 대신할 표준으로 권고되고 있다. XHTML은 1.1까지 나와있으며, 현재 2.0이 Working Draft상태에 있다.

http://www.w3.org/TR/REC-html40

http://www.w3.o rg/TR/2001/REC-xhtml11-20010531


CSS

CSS는 HTML/XHTML의 디자인 부분을 독립시켜 의미론적 웹 을 유지하는데 도움을 주고, 비전문가도 쉽게 웹문서를 디자인할 수 있도록 템플릿 개념으로 되어있다. CSS2가 현재표준안이며 CSS3가 Working Draft상태에 있다.

http://www.w3.org/TR/REC-CSS2


DOM

DOM은 Document Object Model의 약자로, 웹문서의 구성요소들을 객체화하여 접근할 수 있도록 문서의 물리적 구조를 제어할 수 있게 도와준다. 표준인 W3C DOM과 비표준인 MS DOM이 있으며, 이 때문에 JavaScript 사용시 주의해야한다.

http://www.w3.org/TR/REC-DOM-Level-1


JavaScript

JavaScript는 표준이 아니지만, 정적인 웹문서를 다양하게 활용하기 위한 기술을 제공한다. ECMA-262 3 rd Script를 기준으로 삼는다. DOM문제와 더불어, IE전용 스크립트(VBS, JS)의 문제가 있으며, 지원하지 않는 환경이 있기 때문에 반드시 규정에 맞게 사용해야 한다.

http://www. ecma-international.org/publications/standards/Ecma-262.htm



2. 구조화


CSS를 이용한 디자인의 장점은 다음과 같다.

          * 간결하고 읽고 이해하기 쉬운 코드의 생성

          * 수정, 유지보수의 용이

          * 디자인과 분리된 개발 가능

          * 트래픽 절감효과

          * 크로스 브라우저/크로스 플랫폼

          * 접근성 확보

          * 기타 (스킨시스템 구축 용이,

DHTML 기법 사용 용이, JavaScript와의 궁합,

빠른 개발-agile방법론 가능 등.. 기타등등..)


그러나 이러한 CSS의 장점은 엄밀히 말하자면 구조화된 XHTML의 장점이라고 말할 수도 있다. CSS에 대해 피상적으로 이해하고 처음 입문하는 사람들이 흔히 범하는 오류가, CSS에 대해서만 알면, 위와 같은 장점들을 맘껏 누릴 수 있다고 착각하는 점이다. 이것은 매우 흔히 일어나는 일이며 상당히 우려스러운 점으로써, 구조화된 XHTML(혹은 HTML)에 대한 이해가 없을 경우, 오히려 어렵거나 불필요한 CSS 기법을 사용함으로써 위에서 예로 들은 여러가지 장점을 십분 발휘할 수 없게 된다.

따라서, quirk모드에서 IE의 box모델 오류를 해결하기 위한 CSS hack 같은 실질적인 기법들보다 (이런 것은 검색해보면 다 알 수 있다.) 먼저 구조화된 XHTML 성방법에 대해 충분히 익혀둘 필요가 있다.


구조화 란 용어는 임의로 붙인 용어이며, 보다 널리 알려진 표현은 well-formed document 라고 할 수 있다.

well-f ormed document 의 필수조건은 다음과 같다.

  1. 의미론적이며 용도에 맞는 태그를 사용한다.

  2. 문서의 물리적/논리적 구조가 체계적이다.


2-1. XHTML의 태그 사용법

XHTML은 HTML과 크게 다르지 않지만, HTML의 XML버전이므로 XML의 규격에 준하여 몇 가지 주의 사항이 있다.

  1. 모든 태그들은 반드시 완벽하게 중첩되어야 한다.

<b><i>틀린 경우</b></i>

<b><i>맞는 경우</i></b>

  1. 모든 태그와 속성 예약어/지시어에는 소문자를 사용한다.

<A HREF= http://sample.com >틀린 경우</A>

<a href= http://sample.com >맞는 경우</a>

  1. E mpty tag들도 반드시 닫겨야 한다.

<img src= http://sample.com/wrong.jpg >

<img src= http://sample.com/right.jpg />

  1. 속성값은 반드시 겹따옴표( )를 사용해야한다.

<div class= wrong >틀린 경우</div>

<div class=wrong>틀린 경우</div>

<div class= right >맞는 경우</div>

  1. 단축형 속성값을 사용할 수 없다.

<option value= wrong selected>틀린 경우</option>

<option value= right selected= selected >맞는 경우</option>

  1. name대신 id속성을 사용한다.

<input type= text name= field1 value= 틀린 경우 />

<input type = text id= field1 value= 맞지만 문제있음 />

<input type= text id= field1 name= field1 value= 유효한 대안 />

  1. lang 속성을 사용한다.

<div lang="no" xml:lang="no">Heia Norge!</div>

  1. Doctype을 명시한다.

    Strict :
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http:// www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    Transitional :
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    Frameset :
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">


    이 밖에 XHTML이 HTML과 다른 점으로 다음 사항들도 주의해야한다.

    1. presentational tag들을 사용하지 않는다.

    <basefont>, <center>, <font>, <s>, <strike>, <u>

    1. 폐기된 tag들을 사용하지 않는다.

    <applet>, <dir>, <isindex>, <menu>, <xmp>

    1. DTD에 맞는 tag를 사용한다.

    <frame>, <frameset>, <iframe>


    이러한 부분들은 명확히 스펙에 명시되어 있으므로 조금만 숙달되면 준수하기 쉽다 . 그러나 이렇게 문법 지키는 코딩이 XHTML문서의 충분조건은 아니 다. 이러한 하드코딩 문법규칙이 숙달되었다면, 의미론적인 태깅을 익혀야한다. 이 과정은 딱히 정해진 가이드라인이 존재한다기보다는, 개인의 역량과 이해도에 따라 달라지므로, 여기에서는 가장 기본적인 부분들만 짚도록 한다.


    1. 잘못 사용하고 있는 태그들

    <br>은 문단 구분을 위한 태그가 아니다. (<p>를 사용)

    <quote>는 들여쓰기/박스처리를 위한 태그가 아니다.

    <table>은 웹페이지 레이아웃을 잡는데 사용하는 태그가 아니다.

    <b>는 중요한 어휘 를 표현하는데 사용하는 태그가 아니다.

    <h1>은 굵은 글씨 를 표현하는데 사용하는 태그가 아니다.

    기타등등 잘못 사용되고 있는 태그들이 많다.


    1. 의미와 목적에 맞는 태그

    중요한 어휘 를 표현하고 싶다면 <strong>또는 <em>을 사용하고 , 중요도와는 상관없는 굵은 글씨 를 표현하고 싶다면 <b>를 사용한다. 이 차이는 무엇인가?

    가장 기본적인 질문이지만, 이것이 구조화된 XHTML 을 이해하는 가장 근본적인 질문이다.

    예를 들어 텍스트 배너광고 안에 표시된 어떠한 문자열(예를 들어 가습기 총출동! 같은)이 굵은 글씨 로 표현되어 있다고 가정하자. 이것이 이 페이지 내에서 어떠한 중요도를 가지는가?

    만약 중요하지 않다면 <b>로 표현하는 것이 맞다. 그러나 이 문자열이 중요한 어휘라면, <strong>이나 <em>을 사용하도록 한다. 이것이 중요한지, 중요하지 않은지를 판단하는 것은 차후 설명할 개발방법론의 기획/분석 단계에서 이루어져야 하며, 이 판단을 올바르게 할 수 있어야 진정한 XHTML 구조화 역량을 갖출 수 있다. 실제로, 위의 이미지 같은 경우라면, <b>를 사용하는 것마저도 아깝다(?). 더 좋은 방법은 적당한 class를 부여한 후, CSS에서 font-weight:bold;를 사용하는 것이다. <b>는 문자그대로 굵은글씨 를 표현하는 것이지만, 위의 예에서는 굵은글씨 표현해야만 하는 당위성마저도 없기 때문이다.


    Q. <em>을 사용했더니 기울어진 글씨체로 나와요. 그냥 <b>로 쓸래요.

    A. <em>을 사용하고, 대신 표현은 CSS를 사용하세요. 그것이 올바른 XHTML/CSS 사용법입니다.


    이러한 판단은 지금까지 낡은 방식의 HTML 코딩 스타일에 익숙해져있던 사람들에게는 거의 모든 부분에서 걸림돌이 될 것이다.

    게시판의 게시물 리스트는 순서가 없는 리스트(<ul><li>) 인가, 순서가 있는 리스트(<ol><li>) 인가, 아니면 표의 일부분(<table><tr><td>) 인가, 이도저도 아닌 독립된 여러 줄들의 모임(<p>또는<br>) 인가?

    이미지를 이용한 테두리나 박스는 컨텐트 (<img>) 인가, 아니면 의미없는 단순한 장식요소(CSS::backgrund-image) 인가?

    입력 폼에서 사용된 비밀번호 문자열 인가, 테이블의 한 셀의 내부텍스트 인가, form control의 label 인가?

    소소한 예 몇가지만으로도 충분히 머리아플 것이다. 더 골치아픈 것은, 이러한 문제에 정답 혹은 모범답안은 없다는 점이다. 처음 예에서 가습기 총출동! 중요한 어휘 인지, 그저 굵은 글씨 인지는 문서 전체를 놓고 파악해야만 알 수 있다. 심지어 어떤 문서에서는 저 문자열이 소제목 일 수도 있다. 이런 경우에는 이것, 저런 경우에는 저것.이라고 딱 떨어지는 답이 없고 문서 전체의 문맥과 목적에 따라 그때그때 맞는 태깅을 해야한다는 점이다.


    너무 막연하게 들릴 수 있으므로 몇가지 일반적인 가이드라인을 제시해본다.

    1. 아주 특별한 경우를 제외하고, 모든 문서에는 제목 이 존재한다. 제목에는 <h1>태그를 사용한다.

    2. 아주 특별한 경우를 제외하고, 모든 문서는 한 페이지 안에서 좀더 작은 단위의 컨텐트 들로 분할될 수 있다. 이렇게 분할된 컨텐트 들은 의미상 chapter 라고 부를 수 있으며, 따라서 <h2>~<h6>까지의 태그를 사용하여 chapter단계별 소제목 을 붙일 수 있다. (chapter대신 content block, content region.. 어떤 용어를 쓰던간에. 이해가 쉽다면 자신만의 용어를 만들어 붙여도 좋다.)

    3. 어떤 컨텐트(들) 범위/영역 을 분리할 수 있다면 이를 둘러싸기 위해 <div>를 사용할 수 있다. 이것은 시각적 디자인과는 아무 관계없으며, 임의로 어떠한 컨텐트(들)과 다른 컨텐트(들)을 의미적으로 분리할 필요가 있을 때(그리고 분리 가능할 때) 사용한다.

    4. 이미지가 컨텐트 일 경우에만 <img>태그를 사용한다. 장식적인 요소일 경우에는 CSS의 background-image로 돌린다.

    어떤 이미지가 컨텐트 인지 아닌지 알아보는 가장 쉬운 방법은, 해당 이미지가 삭제되어도 정보전달 및 이용에 영향이 있는지 없는지를 살펴보는 것이다. 대체로 다음과 같은 것들은 컨텐트인 이미지 일 가능성이 높다. .

    신문기사의 사진 / 프로필에 포함된 개인사진 / 링크가 걸린 이미지 배너 / 이미지로 표현된 도표, 수식 등 / 의미를 전달하는 그림문자, 심볼 / 이미지 자체가 목적인 것들(갤러리 등)

    대체로 다음과 같은 것들은 컨텐트인 이미지 가 아닐 가능성이 높다.

    박스테두리 / 배경패턴 / 장식이미지 / 뷸릿 이미지 / 버튼(예외있음) / 정보와는 상관없는 장식성 심볼 등 / spacer 이미지

    버튼과 이미지링크는 헷갈리기 쉽다. 간단히 구별하는 방법은, 이미지링크는 URL을 이용한 GET방식을 통해 값을 전달한다. 버튼은 form의 일부분으로써, form을 컨트롤할 때 쓴다. 다음은 상당히 안 좋은 코딩 예이다.

                        <form id= formA method= post >

                       

    <im g src= img/button1.jpg onclick= doSubmit(); />

    </form>

    javascript 의존적인 코드를 만들었으므로 좋지 않고, form의 제어를 버튼이 아닌 이미지링크로 하려한다. (DOM을 무시하는 스크립트 코드는 말할 것도 없다.)

    다음과 같은 코드를 권장한다.

                        <form id= formA method= post action= logic.asp >

                       

                                  <input type= submit class= img_button1 value= ok />

                                  또는

                                  <input type= image src= img/button1.jpg alt= ok />

                        </form>

    javascript binding을 통해 별도로 javascript와 tag를 묶어주고, 되도록이면 body내의 소스에서는 javascript 사용을 자제한다. 아주 특별한 경우를 제외하고는 body내에 javascript가 사용될 필요는 없다.

    1. 비슷한 성격의 아이템이 반복되어 나열되거나 나열될 가능성이 있는 경우 리스트를 사용한다. 이때, 순서가 중요하다면 <ol>을, 순서가 중요하지 않다면 <ul>을 사용한다. 대체로 다음과 같은 것들을 리스트로 표현한다.

    메뉴 (일단 혹은 다단 메뉴) / 무언가의 목록

    게시물 목록 은 약간 애매하다. 예를 들어 인덱스 페이지에서 보이는 XX게시판의 최근 등록글 X개의 모음 같은 경우 리스트 로 표현하는 것이 적당하다. 그러나, 게시판 목록 페이지에서 보이는 게시물 목록 의 경우 , 리스트 로 볼 수도 있지만, 라고 해석할 수도 있다. 왜냐하면, 대개의 경우 목록 제목/작성자/조회수 따위의 헤더 를 포함하고, 그밖의 네비게이션링크, form버튼 들을 포함한 하나의 컨텐트 단위라고 볼 수 있기 때문이다. 따라서 <li>로 표현하는 것은 부적절할 수도 있다. 이 역시 그때그때 다른 것이므로, 문서 전체에서 해당 부분의 성격에 따라 결정해야할 문제이다.

    1. 무조건 <table>을 배척할 필요는 없다. 표현하고자 하는 것이 인지 아닌지만 판단할 수 있으면 된다.

    이런 것은 다. 공연히 <table>을 자제한다고 이런 것마저 <div>로 어떻게 해보려고 하지 말자. J

    어떤 것이 인가? 대개의 경우, 헤더 가 존재하면 다. 게시판을 예로 든다면 번호/제목/작성자/작성일/조회수/추천수 의 column header가 될 것이고,

    게시물번호 의 row header가 될 것이다. H eader는 생략될 수도 있다. 그러므로 그러한 점도 감안해야 한다. 위의 일기예보 표에서 column header는 생략되어있다.(아마도 항목 / 내용 일 것이다. 중첩된 로 표시할 경우, 3일예보/주간예보 가 가장 상위 테이블의 column header일테고, row header는 역시 생략되었다고 해석할 수 있다. )

    1. 그 결과 태그 사용량의 변화

    이렇게 의미와 용도에 맞게 태그를 사용하게 되면, 사용되는 태그 의 빈도가 이전 방식과 크게 달라지게 된다 .

    <div> 가장 많이 사용될 태그 중 한가지로, 컨텐트들의 그루핑, 분리를 위해 사용된다.

    <span> inline(줄바꿈 지 않은, 최소의 컨텐트 단위) 영역에서 컨텐트의 성격 을 부여하므로 많이 쓰인다. 이전에 <font>, <b>, <u>등등의 자리를 대체하게 될 것이다.

    <li> 생각보다 목록 이 컨텐트의 많은 부분을 차지한다는 것을 깨닫게 될 것이다.

    <h1>~<h6> 하나의 문서에서 6depth보다 더 잘게 분류된 컨텐트에는 제목이 필요할 가능성이 적다.

    <img> 그동안 생각보다 불필요한 img태그 가 많았음을 깨닫게 될 것이다.

    <table> 확실히 테이블의 개수가 준다. 하나도 없을 수도 있다. 당연히 table안에 table.. 같은 것도 없다. 코드를 알아보기 쉬우므로 개발자들은 기뻐한다.

    1. class와 id의 사용

    의미론적인 태깅을 했다면, 이제 CSS를 이용해 디자인을 표현할 수 있도록 해주어야 한다. 기껏 의미론적인 태깅을 했어도 다음과 같은 식이면 곤란하다.

    <div style= color:#FF0000;bord er-bottom:2px solid #EFEFEF;background-image: >

    <img border= 1 border-color= red onmouseover= showBorder() >

    이 경우 다음처럼 의미 를 부여한다.

    <div class= article_box >

    <img id= site_logo />

    class와 id의 용법에 대해서는 XHTML/CSS의 기본이므로 이 자리에서 따로 설명하지는 않는다. 바람직한 class/id의 selector naming에 대한 가이드라인은 이어지는 개발방법론 시간에 다루도록 한다.


    2-2. 문서의 구조화 를 시작하기 전에

    의미와 용도에 맞는 태깅이 숙달되면 이제 시야를 넓혀 문서 자체의 구조화를 생각해야 할 시간이다. 사실상, 문서의 구조화 자체는 위에 설명한 가이드라인을 제대로 준수했다면 거의 완성된 셈이다. 다만 미시적 관점에서는 간과하는 부분이 있을 수 있으므로 같은 목적을 거시적 관점에서 생각해보자.

    일반적인 웹 문서는 어떻게 생겼는가? 시간 관계상 거두절미하고 모범적인(?) XHTML 문서의 일례를 살펴보도록 하자.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml">

    <head>

    <!-- Meta Tags -->

    <meta http-equiv="content-t ype" content="application/xhtml+xml; charset=utf-8" />

    <meta name="robots" content="index, follow" />

    <meta name="description" content="" />

    <meta name="keywords" content="" />

    <meta name="author" content="" />

    <!-- Favicon -->

    <link rel="shortcut icon" href="" />

    <!-- CSS -->

    <link rel="stylesheet" href="" media="screen,projection" type="text/css" />

    <link rel="stylesheet" href="" media="print" type="text/css" />

    <!-- RSS -->

    <link rel="alternate" href="" title="RSS Feed" type="application/rss+xml" />

    <!-- JavaScript : Include and embedded version -->

    <script src="" type="text/javascript"></script>

    <title> 문서의 타이틀 </title>

    </head>

    <body>

    <div id="container">

    <div id="navigation">

    </div><!-- navigation -->

    <div id="primaryContent">

    </div><!-- primaryContent -- >

    <div id="secondaryContent">

    </div><!-- secondaryContent -->

    <div id="footer">

    </div><!-- footer -->

    </div><!-- container -->

    </body>

    </html>

    <body> 안쪽은 문서의 구조화에 따라 달라지므로 신경쓰지 말자. 여기에서는 전형적인 구조화된 XHTML문서의 형태를 보도록 한다.

    흔히들 <head>안쪽을 무성의하게 작성하는데, 본문만큼이나 중요하다. 절대로, 그냥 한번 만들어두고 다른 파일들에서 기계적으로 include해서 사용하지 않도록 하자. 모든 페이지마다 <head>는 각각의 페이지에 맞게 적절히 구성되어야 한다.

    되도록이면 CSS는 외부파일로 만들어두고 link해서 사용하는 것이 좋다. 필요하다면 @media같은 CSS 고급활용기법을 쓰는 것도 좋다. 가장 안 좋은 것은 <body>내의 태그에서 inline스타일로 사용하는 것이며(유연한 디자인을 불가능하게 한다.), <style>~</style>을 사용하는 것도 사이트 통일성을 유지하는 데 걸림돌이 된다.

    <script>는 가능한 한 <head>안에 위치하게 한다. 이는 자바스크립트를 해석할 수 없는 기계들을 위한 배려이다.

    잠깐 다른 주제로 빠져서, 절대로 스크립트 의존적인 기능에만 의지하지 말아야 한다. 예를 들어 주민등록번호 확인 같은 경우, javascript상에서만 체크하고 form을 submit하는 경우 javascript를 사용하지 않거나 막아둔 브라우저등에서 이용시 해당 기능을 무력화시킬 수 있다. 이러한 경우를 위해 서버사이드에서도 유효값체크를 해주어야만 한다.

    비슷한 의미로, 스크립트를 사용할 때에는 스크립트를 사용할 수 없는 경우를 위한 동등한 기능이나 정보를 fallback해주어야 한다. (<noscript> 참고)

    <title>의 경우 캐릭터셋의 영향을 받을 수 있으므로, 메타태그들이 끝난 후 선언해준다.

    <head>에 쓰이는 메타태그들은 위에 표시된 내용 외에도 더 있으므로, 문서의 목적과 필요에 따라 적절히 사용해준다.

    본격적인 <body>내에서의 구조화는 새로운 웹개발방법론과 밀접한 연관이 있으므로 이에 대해 먼저 설명 후 다시 살펴보도록 한다.


    3. 표준화를 위한 새로운 웹 개발 방법론

    실제 현장에서 웹표준화/접근성/XHTML/CSS(모두 같은 이야기라고 할 수 있다.)를 적용하는 데에는 초기에 많은 어려움이 있었다. 원인을 살펴보니, 개념 및 이해부족도 큰 문제였으며 그와 더불어 개발 공정 자체에 구조적인 문제가 있었다.

    1) 기존방식의 문제점

    화살표대로 순차 진행되며, 어느 한 단계에서 지연될 경우 병목현상이 발생하게 된다. 무엇보다도, 디자인까지 나온 후에야 코딩이 이루어지므로 인력의 효율적 관리가 어렵고, 구조화된 문서, CSS적용이 힘들다.

    이렇게 된 이유는 크게

    a) 과도한 스토리보드

    b) 디자이너의 역량부족

    을 들 수 있겠다.


    스토리보드라는 것은 계륵 같은 존재이다. 상세하면 상세한 대로, 부실하면 부실한 대로 짐이 된다.

    애초에 스토리보드란, use-case scenario의 한 표현방법 일 뿐이다. 동선의 흐름(스토리)을 기술하는 일종의 모델링 방법이다. 그런데 언제부터인가, 웹 개발의 필수 문서가 되어버렸다. 디자이너는 스토리보드가 없으면 페이지 한 장 그려낼 수 조차 없다. 개발자도 스토리보드가 없으면 비즈니스로직을 만들 수 없다.

    게다가 스토리보드는 상당히 이 많이 드는 작업이다. 그나마 쓸만한 스토리보드가 되기 위해서는 디자인 레이아웃 부터 사용자 액션에 이르기까지 모든 것을 전부 기술해야 한다. 좀 더 친절하려면 DB/프로그램설계에 도움이 될 수 있도록 내/외부에서 사용될 각종 들에 대한 정의도 포함되어야 한다. 가능한 일일까? 본인은 완벽한 스토리보드를 구경해본 적도, 만들어 본 적도 없다.( 시도는 했었으나 배보다 배꼽이 더 큰 작업이었고, 스토리보드의 구조적 한계를 깨달은 계기였다.)

    전형적인 스토리보드의 예 - 좀더 친절한(?) 기획자라면 각 영역의 사이즈, 색상, 사용되는 이미지에 대한 묘사, UI 전반에 대한 지시, 프로그래밍 지시사항 등을 꼼꼼하게 서술할 것이다.

    아울러, 불성실한(?) 디자이너, 개발자라면 스토리보드에는 그런 내용 없었는데요? 라는 발언을 달고 살 터이고, 자존심 센(?) 기획자라면 그런 발언이 안나오도록 스토리보드를 아주 상세히 작성할 것이다. 결국, 스토리보드가 완성될 사이트의 실연동영상 스틸컷 모음 수준이 되어야 완벽하다(?)는 평가를 받게 된다.

    스토리보드가 세세하면 세세할수록 작성에 들어가는 시간이 늘어나며, 세세하면 세세할수록 디자이너와 개발자는 스토리보드에 의존할 수 밖에 없으니 스토리보드가 완성되기 전까지는 하고 싶어도 별로 할 일이 없다. (물론.. 아마도 인력관리라는 명목으로 다른 프로젝트 작업을 열심히 하고 있겠지만.)

    문제는, 여러 개의 문서로 나뉘어져야 할 것을 하나의 스토리보드로 해결하려는 성향 및 기획자 절대 주의이다.


    개발자에게는 구구절절한 스토리보드보다 이런 깔끔한 비즈니스로직 프로세스 플로우 한 장이 더 필요하다. (물론, 스토리보드 를 보고 이러한 프로세스 플로우를 쳐내는 것이 skilled 개발자의 조건일 수도 있다. 그러나 애초에 이정도 기본적인 프로세스는 기획자가 작업하는 것이 더 효율적이다. 기획자의 머리에서 시나리오가 만들어지 므로.)

    디자이너 입장에서 보면 웹디자인이란 파워포인트로 된 그림 을 포토샵으로 옮긴 후, 드림위버에서 최종저장하는 것 이나 다름없다.

    천기누설을 하자면 이렇다. 기획자들은 디자이너들을 믿지 않는다. 그래서 일일이 위치나 크기나 색상이나 컨셉이나 지정해주지 않으면 제대로 된 디자인이 안나온다고 믿는다. 스토리보드대로의 디자인 이 아니면 분명히 귀찮게 굴 것이다. 왜냐하면, 기획자가 가장 사용자의 의도/접근/동선/행동 을 잘 알고 있다고 믿기 때문이다. UI 전문 기획자라면 모를까, 어불성설이다. User Interface는 디자이너가 가장 잘 안다.

    그러나, 현실적으로, 가장 잘 알아야 함에도 불구하고 현업 디자이너들은 솔직히 잘 모른다. 디자이너 일지언정 웹디자이너 는 아니기 때문이다. 별로 알고 싶어하는 것 같지도 않아보인다.

    예뻐보여서 로그인 박스를 여기에 두었어요. <- 이런 설명은 하나마나.

    이 페이지에 접속하면 사용자의 시선이 제일 처음 머무는 곳은 XX이며, 그에 따라 시선은 이러한 방향을 따라 흐르게 됩니다. 컨텐트는 컨셉과 무게에 따라 이러이러하게 배분되어 있으므로 마우스의 동선은 이러저러한 단계를 거치게 됩니다. 따라서 로그인 박스는 이 곳에 위치하는 것이 사용자 편의를 위해 바람직합니다. <- 예쁘기까지하니 금상첨화.

    반드시 이러한 잘난척하는 이론을 늘어놓으란 소리는 아니다. 적어도 웹디자이너라면 이론적인 뒷받침이 있든 없든 간에 이러한 요소가 고려된 디자인을 만들어낼 수 있어야 한다는 뜻이다. 그렇지 못한다면 5년차, 7년차등의 년차수는 의미없는 일이다. (더불어 포토샵 단축키와 타블렛으로 캐릭터그리기 스킬들도.)

    너무 이상적인 디자이너상인지도 모르겠다. 게다가 웹 UI란 단지 포토샵 작업물 이상의 것 (구조화된 문서/DHTML/기타등등) 이기 때문에 디자이너에게 너무 과중한 짐을 지우는 것일 수도 있다. 개인적인 소견으로는, 디자이너가 정말 뛰어난 디자인 만 산출해낸다면 다른 모든 짐은 덜어줘도 괜찮다고 본다.



    2) 새 방법론 제안

    그래서 새로운 방법론이 필요한 시점이다.


    앞의 도표에 비하면 상당히 복잡해보인다. 실제로는 가장 굵은 화살표만 따라보면 된다. 차례대로 따져보자.


    * 분석/기획은 공동작업

    물론, 이전에도 기획회의는 해왔다. 다른 점이 있다면, 이전에는 회의 후 결과물은 기획자가 알아서 스토리보드로 녹여내는 것이라는 암묵적 동의가 있었다면, 새로운 방법론에서는 각자 해야할 일들이 생겼다.

    우선 디자이너는 기획회의 결과 UI 스타일 가이드라인 을 산출해야한다. (위 표의 컨셉 가이드라인 은 오타입니다. -_-a) 어렵게 들리지만, 구식으로 표현하자면 시안작업 이다. 그런데 시안 이란 무엇인가? 클라이언트에게 보여줄 사지선다용 샘플 이미지 몇장?

    UI 스타일 가이드라인 이란 말 그대로 UI 디자인을 위한 스타일 및 그에 대한 가이드라인 이다. 여기에 들어갈 내용은 전체적인 레이아웃구조, 사이즈, 사용될 색상들, 텍스트 스타일, 링크 스타일, 박스 스타일, 버튼 스타일 등등을 미리 정의해 둔다. 나중에 실제 페이지 디자인 시에는 이렇게 미리 정의된 요소들을 조합/응용하기만 하면 자동으로 한 페이지가 완성될 수 있도록. 이 정의가 잘되어있다면 굳이 디자이너가 아니더라도, 이 요소들을 조합하기만 하면 별도의 디자인작업 없이도 디자인이 적용된 페이지를 만들 수 있다는 뜻이다.

    눈치 빠른 이들은 감잡았겠지만, 이 스타일 가이드라인이라는 물건이 바로 CSS다. (물론 CSS로 바로 작성해버리면 나중에 알아보기가 어려우니까 쉽게 볼 수 있는 문서형식으로 작성하는 것이 좋다.) 스타일 가이드라인만 잘 작성해도 전체 CSS 작업의 절반 이상이 완료되는 셈이다.


    기획자와 개발자는 기획회의 결과 프로세스 플로우를 먼저 뽑아낸다. 공동작업이래도 좋고, 어느 한쪽이 맡아해도 좋다. 그러나 대개의 경우 기획자 쪽이 좀더 용이할 것이다. 아무래도 전체적인 흐름을 잡고 있을 테니.

    역시 형식은 다양하겠지만 개인적으로는 UML내지 그 에 준하는 방법들을 추천한다. 잘 설계된 UML문서는 그 자체로 프로그램 코드를 대체할 수도 있다. 회의하는 동안 노트북 가져다 놓고 UML케이스툴로 슥슥 회의과정을 정리해놓으면 그자리에서 바로 프로그램 코드를 산출해주기도 한다. 개발자의 할 일이 반으로 준다.

    물론 그 정도는 아니더래도, 프로세스 플로우가 먼저 나오면, 팀 내/외부 인원들이 사이트의 흐름을 파악하기 쉽다. 또 개발자는 이를 바탕으로 비즈니스 로직을 분석해내거나, 프레임워크 에 적용 하거나, MVC모델 을 적용하는데 큰 도움이 된다. 즉, HTML코드가 직접 필요한 영역을 제외한 로직 모델링 작업을 먼저 마칠 수 있게 된다. (구조적 개발 스킬이 없는 저급개발자에게는 그림의 떡일수도..)


    * 기획자

    UML이니 하는 것들, 기획자들도 계속 공부해야 한다는 소리다.

    대신 스토리보드는 만들어도, 안만들어도 상관없다. 어차피 스타일가이드가 나오므로 굳이 모든 페이지에 시시콜콜 디자인 간섭할 이유도 없고, 프로세스 플로우에 페이지 및 로직 프로세스에 대한 선언도 되어있다. 필요한 것은 이렇게 선언된 각 페이지마다 출력되어야할 컨텐트들만 상세화하면 된다.

    예컨데, 이 페이지에는 이러저러한 메뉴가 있고, 이러저러한 내용 들이 보여야 하며 이러저러한 기능들이 있어야 한다 . 라는 것만 명확히 기술해주면 충분하다.


    * 구조화

    이 페이지에는 이러저러한 메뉴가 있고, 이러저러한 내용들이 보여야 하며, 이러저러한 기능들이 있어야 한다. 라는 컨텐트 명세서가 있다면, 이것을 깔끔하게 정리하는 과정이 구조화라 할 수 있다. 애초에, 컨텐트 명세서를 작성할 때 구조화시켜 작성한다면 별도의 구조화 과정마저도 필요없다.

    실제로 컨텐트 명세와 이에 따른 구조화를 연습해보자.


    페이지 명세서

    페이지 이름 : 영화 정보 서비스 공통 구성요소

    설명 :

    영화 정보 서비스의 모든 페이지에 대해 다음 요소들을 공통으로 포함한다.

    1. 사이트 메뉴 (메일/카페/플래닛/블로그/쇼핑/뉴스/검색/전체보기/로그인)

    2. 서비스 로고

    3. 서비스 메뉴 (영화홈/상영정보/예매/매거진/재밌는DB/커뮤니티/시사이벤트/마이무비)

    4. 검색 (영화검색, 인물검색, 통합검색), 인기검색어 4-5건, 재밌는DB 신규 등록내용 1-2건을 같이 보여준다.

    5. 영화 클릭 순위 : daily(default)/weekly 변경가능, 5건 정도 제목과 링크 제공. 상위 1건에 대해 이미지 썸네일 제공

    6. 영화기사목록 : 요즘뜨는이영화/Photo & Talk/뉴스매거진 각 5개씩 최근 등록 순서로, 상위 1건에 이미지가 있을 경우 이미지 썸네일 포함.

    7. P oll

    8. 서비스 크레딧

    9. 카피라이트

    10. 프로모션 배너 1

    11. 프로모션 배너 2

    12. 프로모션 배너 3

    13. 프로모션 배너 4

    페이지 이름 : 개별 영화 정보 보기

    URL : /movieinfo?mkey=영화id

    설명 :

    이 페이지는 개별 영화 정보 보기 페이지로 검색결과 및 개별 영화 정보의 기본 링크가 된다.

    전체 화면배치는 영화사이트 기본 레이아웃을 따른다 . ( 공통 구성요소 및 UI 스타일 가이드 참고)


    컨텐트 :

    1. 각 영화 정보 보기 페이지 및 그 서브 페이지에 공통으로

    전체보기/동영상,포토/영화지식/매거진/네티즌평

    의 서브메뉴를 제공한다.

    1. 영화 타이틀, 원제, 제작년도, 제작국가의 정보 제공

    2. 영화 정보 제공

    포스터 / 감독 / 출연 / 관람점수 / 장르 / 개봉일 / 상영시간 / 관람등급 / 관련정보 / 사이트 등

    1. 동영상 프리뷰 및 스틸컷 썸네일 4~5장 제공 -> 갤러리 페이지로 링크

    2. 평점

    3. 관람포인트 : 200자 내외의 텍스트 설명

    4. 줄거리 : 400자 내외의 텍스트로 된 줄거리

    5. 영화지식 : 해당 지식검색으로 연결되는 링크 모음

    6. 매거진 : 해당 뉴스 기사로 연결되는 링크 모음(종류, 기사제목, 출처, 날짜 등 부가 정보 필요)

    7. 네티즌리뷰 : 해당 네티즌 리뷰로 연결되는 링크 모음(제목, 작성자, 날짜등 부가 정보 필요)

    8. 400자평 보기 : 생략


간략하게 적은 것이고, 반드시 이런 형식이어야 한다는 것은 아니다. 각 회사의 사정에 따라 내부 문서 규격도 있을 터이고. 디자이너의 창의성과 퍼블리셔의 구조화를 저해하지 않는다면 기존의 스토리보드 형태의 파워포인트 문서래도 상관없다.


이제, 이 명세서를 기반으로 구조화를 해보자.

구조화의 요점은, 덩어리로 분할해서 나누어 공략한다. Divide & Conquer라는 오래된 그러나 확실한 전략이다. 효율적인 작업을 위해서 공통 레이아웃 등은 별도로 작업하는 것이 좋겠지만, 여기에서는 예시를 위해 한번에 다룬다.


명세서를 받은 퍼블리셔 (혹은 디자이너, 혹은 개발자, 혹은 기획자 ) 는 해당 페이지의 목적과 컨셉 과 스타일 에 맞게 내용을 묶어 분할하기 시작한다. 우선, 디자이너가 처음 잡은 스타일 가이드에 따르면 전형적인 2단 레이아웃 구조를 지시했으므로 크게 보아 이 문서는 다음과 같이 러프하게 구조화할 수 있을 것이다. (2단 레이아웃이 아니더라도 사실 대부분 1단계 분할은 다음 형태처럼 되기 마련이다.)

* Header 영역

* Content 영역

* Footer 영역

2단 레이아웃을 지시했으므로, Content영역은 좀 더 나눌 필요가 있겠다.

* Header

* Content

 * MainContent

 * SideContent

* Footer


퍼블리셔가 파악하기에, 위의 명세서에 들어간 내용 중 Header에 속하는 것은 다음과 같다.

* Header

          * SiteMenu

          * ServiceLogo

          * ServiceMenu

          * Search

          * Promotion_1

          * MovieRank

같은 방식으로 나머지들을 구조화한다.

* Header

          * SiteMenu

          * ServiceLogo

          * ServiceMenu

          * Search

          * Promotion_1

          * MovieRank

* Content

          * MainContent

          * SideContent

                    * Promotion_2

                    * ArticleBox

                    * Poll

                    * Promotion_3

* Footer

          * Credit

          * Copyright

이제 대략적인 공통 페이지 구조는 다 잡은 셈이다. MainContent에 들어갈 내용만 페이지 별로 상세화하면 된다.


이 페이지는 크게 제목 , 메뉴 내용 으로 나뉘어진다. 그러므로 그에 맞게 구조화하자.

* MainContent

          * ContentTitle

          * ContentMenu

          * ContentBody


ContentBody에 들어갈 내용은 다음과 같다.

* ContentBody

          * MovieInfo

                    * Poster

                    * Director

                    * Casting

                    * MovieField_1

                    * MovieField_2

                    * MovieField_3

                   

          * Score

          * Point

          * Synopsis

          * Knowhow

이 구조가 정답이라는 소리는 아니다. 이런 식으로 계층적으로 내용을 분할해 들어갈 수 있다면 다른 방식의 구조화도 가능하다.

어쨌거나, 보면 알겠지만, 결국 명세서에 써있는 내용을 잘 정리한 것 뿐이다. 애초에, 명세서에 내용을 이런 식으로 정리해놓았다면 별도의 구조화도 거의 필요없다.



이제 XHTML 코딩을 해보자.

<body>

<div id= header >

          <div id= sitemenu ></div>

          <div id= servicelogo ></div>

          <div id= servicemenu ></div>

          <div id= search ></div>

          <div id= promotion_1 ></div>

          <div id= movierank ></div>

</div>


<div id= content >

          <div id= maincontent >

                    <div id= contenttitle ></div>

                    <div id= contentmenu ></div>

                    <div id= contentbody>

                              <div id= movieinfo >

                                        <div id= poster ></div>

                                        <div id= director ></div>

                                        <div id= casting ></div>

                                        <div id= moviefield_1 ></div>

                                       

                              </div>

                              <div id= score ></div>

                              <div id= point ></div>

                              <div id= synopsis ></div>

                              <div id= knowhow ></div>

                    </div>

          </div>

          <div id= sidecontent >

                    <div id= promotion_2 ></div>

                    <div id= articlebox ></div>

                    <div id= poll ></div>

                    <div id= promotion_3 ></div>

          </div>

</div>


<div id= footer >

          <div id= credit ></div>

          <div id= copyright ></div>

</div>

</body>

</html>

이 정도 결과가 나오면 절반 이상 도달한 셈이다. 보면 알겠지만, 위에 구조화 의 결과를 그대로 HTML코드만 써서 붙인 셈이다.

이런 결과가 나올 것인데, 아예 기획자들이 파워포인트로 명세서를 쓰는 대신 처음부터 이런 HTML 코드를 짜주는 것이 바람직하겠으나 현실적으로 기획자들이 그런 수고를 해줄 것 같지 않다. 대개 기획자들의 직급이 대체로 높은 것도 한 몫 할지도. J


이제 남은 것은 아직도 비어있는 각 블록의 안쪽을 세세하게 컨텐트에 맞춰 채워넣는 것이다. 원리는 위와 상동.


예를 들어 sitemenu를 채워보자.

이 사이트 및 패밀리 사이트들이 공유하는 최상위 메뉴(메뉴라기보다는 링크모음이겠으나.)는 다음과 같다.

메일, 카페, 플래닛, 블로그, 쇼핑, 뉴스, 검색, 전체보기, 로그인


메일~뉴스까지는 패밀리사이트 링크들의 모음이므로 하나의 목록으로 묶을 수 있겠다.

검색은 form이 들어가므로 별도.

전체보기는 사이트맵으로 가는 링크이니 앞의 메일~뉴스 링크들과는 성격이 다르고,

로그인 역시 사용자 계정과 관련있는 링크이므로 별도로 분리하는 것이 낫겠다.


해서 대충 묶어보면 다음 같은 구조가 되는 것이다.

<div id= sitemenu >

<ul id= familysite>

                    <li><a href= ”” >메일</a></li>

                    <li><a href= ”” >카페</a></li>

                    <li><a href= ”” >플래닛</a></li>

                    <li><a href= ”” >블로그</a></li>

                    <li><a href= ”” >쇼핑</a></li>

                    <li><a href= ”” >뉴스</a></li>

</ul>

<form id= form_search action= ”” method= ”” >

                    <input type= text id= txt_search name= txt_search value= ”” />

                              <input type= image src= ”” alt= 검색 id= btn_search name= btn_search />

</form>

<div id= link_sitemap >

<a href= ”” >전체보기</a>

</div>

<div id= link_login >

<a href= ”” ><img src= ”” alt= 로그인 /></a>

</div>

</div>

믿기지 않겠지만, sitemenu 부분의 코딩은 이걸로 끝났다. 나머지 부분들도 이런 식으로 상세화해나가면 된다.


자, 여기까지 오는 동안 중요한 포인트가 있다면, 디자인된 화면 이 전혀 필요없다는 점이다. 즉, 디자인 과는 별개로 코드 가 완성된다. 이것이 가능한 이유는, 충분히 기획회의를 거쳤고, 대강의 디자인구조가 녹아있는 스타일가이드가 있으며, 페이지 명세서가 상세히 작성되었기 때문이다. 기획이 끝나자마자 바로 코드가 생산된다는 뜻이다.


이것은 어떤 이득을 가져다줄까?

사실, 프로그래머들에게는 코드 만 있으면 되지, 그것이 어떤 디자인 이냐는 전혀 중요하지 않다. 기획이 끝나자마자(기획자가 능숙하다면 기획단계부터 동시에 코드가 생산될 수도 있다.) 바로 생산되는 코드는 프로그래머 입장에서는 매우 반가운 일이다. 게다가 디자인 요소가 없으므로 인해 코드는 오죽 읽기 쉬운가. 또 한참 작업도중에 디자인 변경되었다고 코드 뜯어고칠 일도 없다. 웹 프로그래머, 비로소 할만한 직업이 되는 것 같다. :)

디자이너들도 코드 생산의 압박에 시달릴 필요없다. 그저 생산된 코드를 스윽 보고, 각 블록단위에 필요한 백그라운드용 이미지 들, 버튼 이미지들 만 그려내면 된다. 전반적인 건 이미 스타일가이드 작성 때 만들어두었으니까 할 일은 별로 많지도 않다. 또 디자인 변경 때문에 밤새 코드 뒤적거려가며 찾기/바꾸기 단축키를 연타할 필요도 없다. 좀 한가해졌으니 인터페이스공학 에 대해 연구 해 볼 시간이 생기리라 믿는다.

기획자들도 행복 하다. 적어도 몇백페이지짜리 스토리보드 편집은 안해도 되니까.

관리자들도 만족한다. 개발기간이 단축되었고, 유지보수,수정변경이 더 쉬워졌으며, 트래픽 절감효과로 서버 및 회선 비용을 아낄 수 있다.

사용자들도 마찬가지. 사이트가 빨리 열린다. Firefox사용자도, 매킨토시 사용자도 따로 구분할 필요없다. 심지어 핸드폰이나 PDA나 웹TV나 기타 등등 어떠한 장비-그것이 웹표준을 준수하기만 한다면 냉장고에 붙은 웹브라우저에서도 정상적인 이용이 가능하다. 시각장애인들도 불편없이 사용할 수 있다.

그밖에 검색엔진 친화성이라든가, 리팩토링, 머신피드용이 등의 부가효과들에 대해서는 더 이야기할 것도 없다.


잠깐, 중요한 것을 빼먹었다 고?

아까 만든 sitemenu, 이런 식으로 내버려두면 어쩌냐는 불안의 목소리가 있을 듯 하여 원래 강의 목표와는 상관없 지만, 완성된 XHTML에 CSS를 입히는 부분에 대한 보너스를 덧붙인다.


<div id="sitemenu">

          <ul id="familysite">

                    <li><a href="">메일</a></li>

                    <li><a href="">카페</a></li>

                    <li><a href="">플래닛</a></li>

                    <li><a href="">블로그</a></li>

                    <li><a href="">쇼핑</a></li>

                    <li><a href="">뉴스</a></li>

          </ul>

          <form id="form_search" action="" method="">

                    <input type="text" id="txt_search" name="txt_search" value="" />

                    <input type="image" src="http://image.hanmail.net/hanmail/temp/b_search.gif" alt="검색" id="btn_search" name="btn_search" />

          </form>

          <div id="link_sitemap">

                    <a href="">전체보기</a>

          </div>

          <div id="link_login">

                    <a href=""><img src="http://image.hanmail.net/hanmail/temp/b_login.gif" alt="로그인" /></a>

          </div>

</div>

아까와 같은 소스인데, 이미지 url만 붙였다. 여기에 아래의 CSS를 적용해보라.

* {

          font-family:tahoma, gulim, sans-serif;

          font-size:12px;

}

a {

          color:#333;

          text-decoration:none;

}

a:hover {text-decoration:underline;}

a img {

          border:none;

}

#sitemenu {

          float:right;

}

#familysite {

          float:left;

          margin:0px;

          padding:0px;

}

#familysite li {

          float:left;

          list-style-type:none;

          background-image:url("http://image.hanmail.net/hanmail/temp/dot.gif");

          background-position:center right;

          background-repeat:no-repeat;

          padding-left:5px;

          padding-right:5px;

          display:block;

}

#form_search {

          float:left;

          margin-left:5px;

}

#form_search input {

          float:left;

          height:11px;

          margin-right:5px;

}

#form_search input#btn_search {

          height:16px;

}

#link_sitemap {

          float:left;

}

#link_login {

          float:left;

          margin-left:5px;

}


그 결과는 놀랍게도 다음과 같을 것이다.


마무리를 해보자.

CSS가 대세 이긴 한데, CSS만 익히는 것은 아무런 소용이 없다. 구조화된 XHTML문서를 생성해낼 수 있어야만 비로소 CSS를 적용할 수 있게 된다.

웹표준화, 접근성의 확보에 CSS가 필수인 것만큼 당연히 XHTML에 대한 완벽한 이해가 선행되어야 한다.

XHTML문서의 구조화는 디자인과는 상관없이 온전히 내용만 가지고 이루어야하며, 나중에 CSS를 이용하여 디자인을 씌울 때에도 무리없이 적용되도록 잘 구조화되어야 한다.

그러나 이 과정은 기존의 개발공정으로는 제대로 담아낼 수 없어서 새 공정을 필요로 한다. 여기에서 든 내용들은 개인의 역량, 조직사정 등에 의해 유연하게 적용되어야겠지만, 중요한 것은 단지 어떤 기법을 쓸 것인가가 아니라, 왜 웹 표준화를 해야하는가, 왜 웹 접근성을 지켜야 하는가, 무엇이 의미론적인 웹을 만드는가 이러한 부분들을 확실히 이해한다면 XHTML의 구조화, CSS를 위한 디자인이 한결 현실감있게 다가올 것이다.


Ref. 2.

    1. Reference-Sites

W3C http://w3c.org

한국정보문화진흥원 http://kado.or.kr

한국소프트웨어진흥원 http://www.software.or.kr/kipahome/kipaweb


크로스 브라우징 가이드

http://www.mozilla.or.kr/docs/web-developer/standard/crossbrowsing.pdf

홈페이지 구축운영 표준 지침

http://www.mogaha.go.kr/warp/webapp/sys/dn_attach?id=1c0bdf783dc19fce1e2facc

웹접근성을 고려한 콘텐츠 제작기법

http://www.mozilla.or.kr/docs/web-developer/content_authoring_for_accessibility.pdf


웹사이트 가이드 (미국)

http://www.usability.gov/guidelines/Usability_guidelines.pdf


css ZenGarden http: //csszengarden.com

A List Apart http://alistapart.com

W3School http://www.w3school.com

C ross-browser http://www.cross-browser.com


한국 모질라 포럼 웹표준화 프로젝트 http://forums.mozilla.or.kr/viewforum.php?f=9

CSS 디자인 코리아 http://css.macple.com


신승식님 http://gregshin.pe.kr/bbs/zboard.php?id=ud

신현석님 http://hyeonseok.com

박민권 http://ani2life.egloos.com/

일모리 http://ilmol.com/wp/

Tabula Rasa http://eouia0.cafe24.com

박수만님 http://www.sumanpark.com/

윤석찬 http://channy.creation.net/blog/

김중태문화원 http://www.dal.co.kr

kukie.net http://kukie.net/resources/benefits/

hooney.net http://hooney.net/

hochan.net http://hochan.net/archives/cat_aii_aissa.html

daybreaker http://www.daybreaker.x-y.net

별주부뎐 http://blog.webservices.or.kr/hollobit/

소프트원트 http://www.softwant.com


    1. Reference-Books

Web Standard Solution : The Markup and Style Handbook / 댄 씨더홈

(8월중 번역 출간 by 박수만님)

Web Designer's Reference : An Integrated Approach to Web Design with XHTML and CSS / 크랙 그라넬

The CSS Anthology / 레이첼 앤드류

Bulletproof Web Design : Improving flexibility and protecting against worst-case scenarios with XHTML and CSS / 댄 씨더홈

Cascading Style Sheets: The Definitive Guide / 에릭 마이어 (번역판 있음)

HTML & XHTML : The Definitive Guide / 척 머스키아노 (번역판 있음)


    1. Tools

NVU

Rapid CSS Editor

Topstyle

PSPad

CSSedit

X-Edit

StyleMaster

Adobe Golive CS2

DreamWeaver 8


FF용 플러그인들. (CSS 셀렉터, 그리스몽키,  너무 많아 일일이 적을 수가 없네요. ^_^)


물론 XHTML, CSS 모두 텍스트 기반이므로 손에 익기만 하다면 아무 텍스트 에디터라도 상관없습니다. 저는 주구장창 VIM과 UltraEdit만 쓰고 있습니다.


평가/인증

W 3C HTML Validator : http://validator.w3.org/

W3C CSS Validator : http://jigsaw.w3.org/css-validator/

Webxact Accessibility Validator : http://webxact.watchfire.com

영국 시각장애인 단체 : http://www.rnib.org.uk/

미국 시각장애인 단체 : http://www.nfb.org/seal/certify.htm


Posted by 1010
반응형
한글만 입력받기


<script language='javascript'>
function hangul()
{
if((event.keyCode < 12592) || (event.keyCode > 12687))
event.returnValue = false
}
</script>

<input type="text" name="Name" size="10" maxlength="15" class=ad onKeyPress="hangul();">


-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------


input text 한영 한글/영문 입력 설정


<FORM>
<input style="ime-mode:active;">
<input style="ime-mode:inactive;">
</FORM>


ime-mode:active 이면 한글입력
ime-mode:inactive 이면 영문입력

익스플로러 6에서만 작동


-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------


한글 전환 모드 안 되게 하기
 
<input type="text"  style="ime-mode:disabled;">


-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------


한영 한글/영문 전환 버튼

<html>
<head>

<script language="javascript">
<!--
function Kren(form)
{
        if(form.test.style.imeMode == "active")
                form.test.style.imeMode = "inactive";
        else
                form.test.style.imeMode = "active";
}
//-->
</script>

</head>

<body>

<form name=form1 action="">
<input type="text" name="test">
<input type="button" onClick="Kren(this.form)" value="한/영전환">
</form>
익스플로러 6이상에서만 작동합니다.
</body>
</html>


-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------


숫자만 입력받기

<script>
function num_only(){
  if((event.keyCode<48) || (event.keyCode>57)){
    event.returnValue=false;
  }
}
</script>
<form name='test'>
<input type=text name='numInputField' OnKeyPress="num_only()" style="ime-mode:disabled">
</form> 


-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------


전화번호 포맷으로 숫자만 입력하면 (02)123-3423 이런식으로 바꿔줍니다

<SCRIPT LANGUAGE="JavaScript">
<!--
///
var n;
var p;
var p1;
function ValidatePhone(){
p=p1.value
if(p.length==3){
        pp=p;
        d4=p.indexOf('(')
        d5=p.indexOf(')')
        if(d4==-1){
                pp="("+pp;
        }
        if(d5==-1){
                pp=pp+")";
        }
        document.frmPhone.txtphone.value="";
        document.frmPhone.txtphone.value=pp;
}
if(p.length>3){
        d1=p.indexOf('(')
        d2=p.indexOf(')')
        if (d2==-1){
                l30=p.length;
                p30=p.substring(0,4);
                p30=p30+")"
                p31=p.substring(4,l30);
                pp=p30+p31;
                document.frmPhone.txtphone.value="";
                document.frmPhone.txtphone.value=pp;
        }
        }
if(p.length>5){
        p11=p.substring(d1+1,d2);
        if(p11.length>3){
        p12=p11;
        l12=p12.length;
        l15=p.length
        p13=p11.substring(0,3);
        p14=p11.substring(3,l12);
        p15=p.substring(d2+1,l15);
        document.frmPhone.txtphone.value="";
        pp="("+p13+")"+p14+p15;
        document.frmPhone.txtphone.value=pp;
        }
        l16=p.length;
        p16=p.substring(d2+1,l16);
        l17=p16.length;
        if(l17>3&&p16.indexOf('-')==-1){
                p17=p.substring(d2+1,d2+4);
                p18=p.substring(d2+4,l16);
                p19=p.substring(0,d2+1);
        pp=p19+p17+"-"+p18;
        document.frmPhone.txtphone.value="";
        document.frmPhone.txtphone.value=pp;
        }
}
setTimeout(ValidatePhone,100)
}
function getIt(m){
n=m.name;
p1=m
ValidatePhone()
}
function testphone(obj1){
p=obj1.value
p=p.replace("(","")
p=p.replace(")","")
p=p.replace("-","")
p=p.replace("-","")
if (isNaN(p)==true){
alert("Check phone");
return false;
}
}
//-->
</script>
전화번호보단 다른 데 응용하시면 좋을 듯..<br>태그인넷 tagin.net<br>
<form name=frmPhone>
<input type=text name=txtphone maxlength="13" onclick="javascript:getIt(this)" >
</form>


-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------


입력박스 폼안의 숫자 1000단위로 자동 ,콤마 찍어주기

<SCRIPT LANGUAGE="JavaScript">
<!--
function Number_Format(fn){
      var str = fn.value;
      var Re = /[^0-9]/g;
      var ReN = /(-?[0-9]+)([0-9]{3})/;
      str = str.replace(Re,'');             
      while (ReN.test(str)) {
              str = str.replace(ReN, "$1,$2");
              }
      fn.value = str;
}
//-->
</SCRIPT>

<FORM name=fm METHOD=POST ACTION="">
<INPUT TYPE="text" NAME="money" Onkeyup="Number_Format(this)";>
</FORM>


-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------


특수문자 입력금지

<center>
<form onSubmit="return false;">
<a href="http://tagin.net">특수문자를 입력 할 수 없습니다: (예 !@#$%^&* etc)<br>
<textarea rows=2 cols=20 name=comments onKeypress="if ((event.keyCode > 32 && event.keyCode < 48) || (event.keyCode > 57 && event.keyCode < 65) || (event.keyCode > 90 && event.keyCode < 97)) event.returnValue = false;"></textarea>
<br>
<br>
홋(겹)따옴표를 입력 할 수 없습니다:<br>
<input type=text name=txtEmail onKeypress="if (event.keyCode==34 || event.keyCode==39) event.returnValue = false;">
<br>
<br>
숫자만 입력가능합니다:<br>
<input type=text name=txtPostalCode onKeypress="if (event.keyCode < 45 || event.keyCode > 57) event.returnValue = false;">
</a></form>
</center>
Posted by 1010
반응형

DIV에 스크롤바 나타내기

overflow-x                     x축(가로)

overflow-y                     y축(세로)

overflow:visible             레이어 크기를 키워서 보여준다 (* 디폴트)

overflow:hidden             레이어 크기만큼만 보여준다

overflow:auto                내용에 따라 자동으로 스크롤을 만든다

overflow:scroll               무조건 스크롤바를 생성한다

 

스크롤바 꾸미기

<style type="text/css">

scrollbar-face-color:#FFFFFF;                      스크롤바 전체 색상
scrollbar-track-color: #FFFFFF;                    스크롤바가 없는 스크롤바 아래에 위치한 부분의 색상

scrollbar-arrow-color: #666666;                     위 아래 화살표 색상
scrollbar-highlight-color: #FFFFFF;               왼쪽과 위쪽의 하이라이트 색상
scrollbar-3dlight-color: #cfcfcf;                     입체감을 위한 왼쪽 위 색상
scrollbar-shadow-color: #FFFFFF;                오른쪽과 아래쪽의 그림자 색상
scrollbar-darkshadow-color: #cfcfcf;             바의 오른쪽, 밑쪽에 들어가는 얇은 색

</style>

 

==================================================================================================================

 

 

 

div Style속성

 

overflow: ######;

          visible : 레이어 크기를 키워서 출력.

          hidden : 레이어 크기만큼 출력.

          auto : 내용에 따라 자동 스크롤.

          scroll : 스크롤바 생성.

     ex) overflow-x:값; overflow-y:값; overflow:값;

 

position: ######;

          static : 기본값.

          relative : 하위에 div가 있을 경우엔 하위의 div를 absolute 배열.

          absolute : div에 top, right, bottom, left 값을 지정해서 원하는 위치에 고정.

          fixed : 스크롤에 상관없이 지정한 위치에 고정.

          inherit : 상위에서 지정한 값을 상속.

 

visibility: ######;

         visible : 보임.

          hidden : 감춤.

 

z-index: #;         :: #값에 따라 우선순위 정의.

 

left: ##px;

top: ##px;

width: ###px;

height: ###px;

text-align: center;

          center , left, right ...

background-color: #######;

border-style: ######;

          solid , dotted .....

border-color: ######;

border-width: ##px;

border: ###px;

 

==================================================================================================================

 

 

div 상하로 정렬 하기 (상단, 중앙, 하단)

 


   div가 상단, 중앙, 하단으로 있을 때 하단 div를 bottom으로 붙이는 방법

   







------------------------------------------------------------------------------------------


<style type="text/css">

#Box {position:relative; width:300px; height:300px;}
#head {float:left; width:300px; height:50px;}
#body {clear:left; float:left; width:300px;}
#foot {position:absolute; clear:left; float:left; width:300px; height:50px; left:0; bottom:0px;}

</style>


<div id="Box">
    <div id="head">상단</div>
    <div id="body">중앙<br />내용1<br />내용2</div>
    <div id="foot">하단</div>
</div>


------------------------------------------------------------------------------------------

겉에 감싸는 div에 position을 relative로 주고

하단으로 붙이고 싶은 div의 position을 absolute로 주면 하단 div는 겉의 div안에서 움직이게 된다.

하단 div에 left:0과 bottom:0으로 주어야 하단으로 딱 붙게 된다.

 

==================================================================================================================

 

 

div 가운데 정렬

 

테이블을 사용할 때는 td에 align을 center로 주면 그 안에 들어가는 내용이 딱딱 가운데 정렬이 됐었는데..

div를 가운데 정렬하려니 도통 안되는 것이다..

몇번의 검색과 이것 저것 찾다보니 알게 된 것이 margin:0 auto 를 사용하면 된다는 것..

align의 center가 되는 것은 block레벨이 아닌 것에만 적용이 된다고 한다.

div는 block 레벨이니 당연히 div 자체에는 align이 먹히지 않는 것..

------------------------------------------------------------------------------------------

<style type="text/css">
#BoxCenter {margin:0 auto; width:300px; height:100px; background-color:#33CCFF;}
</style>


<div id="BoxCenter">div 중앙 정렬</div>

------------------------------------------------------------------------------------------

 

==================================================================================================================

 

 

레이어 길이 능동적으로 변환하기(style.height)

 

body 레이어의 onresize 이벤트에서 처리 해주시면 됩니다..


간단하게 예제 올립니다.


스타일정의 - 레이어의 외곽선을 보이기 위해 정의 했습니다.

<style>

.Layer{

position:absolute;

BORDER-BOTTOM: 1px solid;

BORDER-LEFT: 1px solid;

BORDER-RIGHT: 1px solid;

BORDER-TOP: 1px solid;

FONT-FAMILY: "돋움"; FONT-SIZE: 20pt

}

</style>


자바스크립트 정의 - LayerBody 의 onresize 이벤트에서 처리 했습니다.

그리고 window.onload 이벤트에서 LayerBody의 Height를 변경하여

테스트 하였습니다.


<SCRIPT ID=clientEventHandlersJS LANGUAGE=javascript>

<!--

function LayerBody_onresize() {

              //LayerLeft 의 height 를 변경된 LayerBody의 height의 값을 대입

             document.getElementById("LayerLeft").style.height = document.getElementById("LayerBody").style.height;

              //LayerRight 의 height 를 변경된 LayerBody의 height의 값을 대입

             document.getElementById("LayerRight").style.height = document.getElementById("LayerBody").style.height;

             //LayerBottom의 top 을 LayerBody의 (top + height)을 대입하여 LayerBody의

             //끝부분에 위치하게 한다.

            document.getElementById("LayerBottom").style.top = document.getElementById("LayerBody").offsetTop + document.getElementById("LayerBody").offsetHeight;


}


function window_onload() {  //테스트를 위해 window객체의 onload 이벤트에서 LayerBody의 height를 1000px로 변경 하였다.

           document.getElementById("LayerBody").style.height = "1000px";

}

//-->

</SCRIPT>


body 부분 정의


<body onload="return window_onload()">

<div id="LayerLeft" class=Layer style="width:133px; height:325px; z-index:1"></div>

<div id="LayerBody" class=Layer style="width:301px; height:325px; z-index:2; left: 145px; top: 15px;" onresize="return LayerBody_onresize()"></div>

<div id="LayerRight" class=Layer style="width:188px; height:325px; z-index:3; left: 448px;"></div>

<div id="LayerBottom" class=Layer style="width:629px; height:115px; z-index:4; left: 9px; top: 341px;"></div>

</body>


 

==================================================================================================================

 

 

DIV를 이용하여 페이지의 특정 부분만 인쇄하는 방법

 

웹 페이지가 상당히 길 때 사용자로 하여금 특정 부분만 인쇄할 수 있는 인터페이스를 제공해 주고 싶은 경우들이 종종 있다. 하지만 일반 브라우저는 페이지의 특정 부분만을 인쇄할 수 있는 메쏘드를 제공하고 있지 않다. 물론, 브라우저의 인쇄 대화 상자에서 일부 페이지를 인쇄할 수 있기는 하지만 우리가 원하는 것은 그런 기능이 아니다.

백문이 불여일견! 아래 있는 "소스실행하기"버튼을 클릭한 후 나타난 화면에서 원하는 인쇄 영역을 선택한 다음 "특정 부분 인쇄" 버튼을 클릭해 보기 바란다.


<DIV> 태그를 잘 이용하면 특정 DIV 영역만 인쇄할 수가 있다.

인 터넷 익스플로러는 window.onbeforeprint와 window.onafterprint 이벤트 핸들러를 지원하는데, 이들은 인쇄 전과 후의 웹 페이지 내용을 변경할 수 있도록 도와준다. 이 기능을 이용하여 특정 DIV 영역은 보이게 하고 나머지 영역은 숨길 수가 있다. (불행히 넷스케이프는 이 이벤트 핸들러를 지원하지 않는다. 하지만 여기서는 약간의 제약이 있긴 하지만 넷스케이프에서도 약간의 보이기 속성을 조절하여 비슷하게 구현해 보기로 한다.)



<HTML>
<HEAD>
<STYLE>
DIV { position: relative; }
</STYLE>
<SCRIPT>
var div2print;
function printDiv (id) {
  if (document.all && window.print) {
    div2print = document.all[id];
    window.onbeforeprint = hideDivs;
    window.onafterprint = showDivs;
    window.print();
  }
  else if (document.layers) {
    div2print = document[id];
    hideDivs();
    window.print();
  }
}
function hideDivs () {
  if (document.all) {
    var divs = document.all.tags('DIV');
    for (var d = 0; d < divs.length; d++)
      if (divs[d] != div2print)
        divs[d].style.display = 'none';
  }
  else if (document.layers) {
    for (var l = 0; l < document.layers.length; l++)
      if (document.layers[l] != div2print)
        document.layers[l].visibility = 'hide';

  }
}
function showDivs () {
  var divs = document.all.tags('DIV');
  for (var d = 0; d < divs.length; d++)
    divs[d].style.display = 'block';
}
</SCRIPT>
</HEAD>
<BODY>
<DIV>
<FORM>
<SELECT NAME="divSelect">
<OPTION>첫 번째 영역만 인쇄
<OPTION>두 번째 영역만 인쇄
<OPTION>세 번째 영역만 인쇄
</SELECT>
<INPUT TYPE="button"
       ONCLICK="var s = this.form.divSelect;
                var divID = s.options[s.selectedIndex].text;
                printDiv(divID);"
       VALUE="특정 부분 인쇄"
>
</FORM>
</DIV>
<DIV ID="d1">
<b>[첫 번째 영역]</b><br>
첫 번째 영역입니다!<br><br>
</DIV>
<DIV ID="d2">
<b>[두 번째 영역]</b><br>
두 번째 영역입니다!<br>
두 번째 영역을 선택하여 인쇄해 보세요!<br><br>
</DIV>
<DIV ID="d3">
<b>[세 번째 영역]</b><br>
세 번째 영역입니다!<br>
세 번째 영역을 선택하여 인쇄해 보세요!<br>
From 코리아인터넷닷컴
</DIV>
</BODY>
</HTML>



출처 : 코리아인터넷닷컴

 

==================================================================================================================

 

 

div는 무엇일까? 어떻게 사용해야 할까?

 

HTML에서의 div는 Division Marker의 줄임말로서 영역을 구분짓거나 무리(구분)지어주는 엘리먼트이다.
div는 div를 열고 닫은 앞뒤로 줄바꿈이 되는 블럭 레벨 항목 block level element이다.
div의 앞 뒤에 있는 항목들이 가로줄로 흐르지 않고, 엔터값을 입력한 것 처럼 아래로 줄 지어진다는 말이다.

div로 레이아웃이나 박스를 구성하기 위해, CSS에서 가장 많이 쓰는 속성인 position 값으로는 static, relative, absolute, fixed, inherit가 있다.

Position 속성

static

CSS로 특별한 값을 지정해 주지 않아도 적용되는 기본값이다.
HTML 파일에서 중첩되지 않은 여러개의 div를 작성하면, 위에서 부터 차곡 차곡 쌓이는 기본적인 형태이다.
relative
한개의 div가 있고 relative로 설정할 경우엔 static과 큰 차이는 없다. 하위에 div가 있을 경우엔 하위의 div를 absolute 배열 할 수 있다.

absolute

흔히 레이어라는 개념으로 알고 있는 값이다. div에 top, right, bottom, left 값을 지정해서 원하는 위치에 고정되게 띄울 수 있다.

fixed

기본적으로 absolute와 같다. absolute는 canvas의 스크롤에 따라 올라가고 내려가지만 fixed의 경우는 스크롤에 상관없이 지정한 위치에 고정된다.

inherit

상위에서 지정한 값을 상속한다.

 

div를 설명하자면, 레이아웃layout 또는 박스모델 boxmodel을 빼놓고 말할 수 없다.
위에도 적었듯이 컨텐츠를 묶어주는 역할을 하는데, 컨텐츠를 묶어서 배열 하는 것이 곧 레이아웃layout이기 때문이다.

 

컨텐츠 안에서의 div는 사용자가 사용하기 나름일테고, 컨텐츠를 묶어주는 역할의 div는, 위치를 지정함(positioning)으로써 자신의 진정한 역할을 하게 된다.
여기서는 컨텐츠를 묶어주는 가장 크고 바깥의 영역을 담당하는 div에 대해 얘기하도록 하자.

 

positioning하는 것은 div를 float 시키거나 절대값으로 위치absolute positioning 하는 등 사용자가 원하는 위치에 위치시키는 것을 말한다.
positioning하기 위해서는 위에 나열한 position 속성을 사용하거나, float를 사용하여야 한다.

 

기본 적인 형태의 Layout


 

 

XHTML code
<!doctype html public "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" >
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
 <title> New Document </title>
 <link rel="stylesheet" type="text/css" href="css/left.css">
</head>

<body>
 <div id="header">헤더</div>
 
 <div id="container">
  <div id="contents">컨텐츠</div>
  <div id="sidebar">사이드바</div>
 </div>

 <div id="footer">푸터</div>
</body>
</html>

 


CSS code (float 사용)

body {
 margin: 0;
 padding: 10px;
 background-color: #FFF;
}
#container {
 width: 380px;
}
#header {
 background-color: #FF4A4D;
 height: 50px;
}
#contents {
 float: left;
 background-color: #FFC64A;
 width: 290px;
 height: 214px; /* 임의 지정 */
}
#sidebar {
 float: right;
 background-color: #85C69D;
 width: 90px;
 height: 214px; /* 임의 지정 */
}
#footer {
 clear: both;
 background-color: #3B83B1;
 height: 40px;
}

 

 


boxmodel의 예제는 Little Boxes에서 자세히 살펴볼 수 있다. 하단에 몇 개 더 소개하도록 하겠다.

절대값 위치absolute positioning에 대한 개념은 좌표를 지정하여 div를 배열하는 방식이기 때문에 기존의 레이어layer 개념을 알고 있다면 정확하게 익히는 것이 어렵지 않을 것이라고 본다.

그럼 float에 대해 좀 더 알아보자.
float의 값으로는 left, right, none, inherit가 있다.

float 속성
left
left로 설정된 엘리먼트가 HTML 코드에서 바로 다음 엘리먼트의 왼쪽에 위치하게 된다.
right
right로 설정된 엘리먼트는 바로 다음 엘리먼트의 우측에 위치하게 된다.
none
float 하지 않는다.static의 상태로 자연스럽게 박스가 쌓이는 형태라고 보면 된다.
inherit
상위에서 지정한 값을 상속한다.
float를 사용할 때는 clear에 대해서도 알아야 하겠다.
위에서 어떠한 항목에 대해 float:left; 혹은 float: right;를 설정하였을 경우 그 아래에 있는 것들도 영향을 받게 된다. 그것들에 대해 다시 초기화를 시켜주는 것이 clear이다.
left, right 각각 해당 정렬에 대한 영향을 없애주고 both는 둘 다 없애준다.

 

div의 width, height


특별히 width나 height를 정해주지 않으면 컨텐츠의 길이와 넓이에 따라 자동적으로 늘어나고 줄어든다.

만약에 width를 지정했는데, 끊기지 않는 텍스트나 커다란 이미지 혹은 링크로 인해 고정한 width보다 컨텐츠가 넓어질 경우에는 overflow 속성을 지정해서 해결 할 수 있다.
(FF에서는 박스는 고정되어 있고 컨텐츠만 삐져나오고, IE에서는 컨텐츠에 따라 박스가 함께 넓어 지기 때문에 레이아웃이 엄청 깨지는 것을 볼 수 있다. height를 고정한 경우에는 height에도 함께 적용 된다.)

overflow에 지정할 수 있는 속성으로는 visible, hidden, scroll, auto등이 있다.

visible
내용을 자르지 않고 블럭 밖까지 가도록 허용한다.
hidden
박스를 넘어갈 경우, 넘어가는 부분을 감추어 버린다. (잘림부분의 크기와 모양은 ‘clip’ 속성에 의하여 결정된다.)
scroll
박스에 기본적으로 scroll을 제공하게 된다. - print나 projection CSS에서 해당 div안의 넘치는 컨텐츠도 인쇄 해준다.
auto
박스는 고정해 두고, 박스보다 컨텐츠가 커질 경우 스크롤을 만들어 준다.
만약에 height를 지정했는데 FF에서 컨텐츠가 삐져나온다면, min-height를 이용하여 해결 할 수 있다.
고정된 값을 지정했다면, 컨텐츠가 많이 지더라도 div의 높이 값은 고정되어 있는 것이 맞다.
IE 는 자체지능적;으로 컨텐츠에 따라 높이를 마음대로 높혀 버리는데, IE처럼 컨텐츠에 따라 div의 높이가 변해주길 바란다면 min-height라는 속성을 지정해 주면 된다. IE에서는 적용되지 않으므로 * html #id { height: 200px; } 같은 hack도 함께 써주어야 한다.

결론적으로 layout을 위해 div를 사용할 때에는 position, float에 대해서는 기본적으로 알아야 하고, 부가적으로 overflow를 알아두면 더욱 적절히 사용할 수 있겠다.

 

 

 

Posted by 1010
반응형

Mysql 자동 백업 하기 - Rsync와 연계하면 좋음

/root아래에 backup.sh 이라는 파일을 만들어 놓고 백업 명령어를 다음과 같이 주었다.

#!/bin/bash
/usr/local/mysql/bin/mysqldump -uroot -p***** mysql > mysql_db_bak_$(date +%Y%m%d).sql
/usr/local/mysql/bin/mysqldump -uyanemone -p***** yanemone > yanemone_db_bak_$(date +%Y%m%d).sql
mv *.sql /backup
tar cvfpz /backup/html_bak.tar.gz /var/www/html
tar cvfpz /backup/yanemone_html_bak.tar.gz /home/yanemone/public_html
tar cvfpz /backup/dichang_html_bak.tar.gz /home/dichang/public_html

WEEKAGO=`date -d "-30 days" +%Y%m%d`

rm -f /backup/*${WEEKAGO}.sql

귀찮으니까 한달 지난건 지워버리죠.

백업할 내용이라던지 파일 이름은 자신의 상황에 맞게 주면 되겠다.

이렇게 하고 나면 backup.sh파일을 chmod 100 backup.sh로 단단히 무장하라.

그리고 crontab -e 명령으로 cron 작업을 명시하자
그럼 vi가 열리면서 편집이 가능하다

00 06 * * * /root/backup.sh

를 추가하고 :x 로 저장하고 나오자.
위의 작업은 매일 새벽 6시에 /root/backup.sh을 실행하라 라는 말이다.

그리고 /var/spool/cron/root가 있는지 확인해보자. 있다면 정상적으로 수행할 것이다.

Crontab 의 메일 안받기

/etc/crontab이라는 파일을 열어보자
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=ROOT
HOME=/

부분이 있다. MAILTO=ROOT를 다음과 같이 고쳐보자
MAILTO=""

크론에 등록시 아래와 같이 하면 메일이 날아오지 않는다.
위에꺼는 전체 메일이 다 날아오지 않으므로 주의 해야 한다.
그러므로 아래꺼 사용하믄 된당...
00 06 * * * /root/backup.sh >/dev/null 2>&1



저장할 파일의 크기가 클경우 분할하여 압축할수 있다.
백업을 하다보면 기가단위가 넘을때가 많습니다.
그때는 분할백업(CD 1장 단위가 좋겠죠...)
tar -zcvpf - /압축할dir | split -b 670mb - 압축파일.tar.gz

그러면 압축파일.tar.gzaa
압축파일.tar.gzab순으로 파일이 생깁니다.

-b 670mb는 압축파일을 670mb단위로 분할 하라는 옵션입니다.

압축풀라고 할때는 (쿠쿠 바로 답해 주셔서 캄솨함다.)
cat test.tar.gza* > test.tar.gz
로 하여 tar.gz파일로 만들어서 풀면 된다.

Posted by 1010
반응형

예전에 만들어진 페이지들을 보면 스크립트부분을

//<!--
//-->


로 묶어 놓은 것을 볼 수 있다. 솔직히 이게 필요하게 느껴본적은 전혀 없지만(그땐 개발도 안했긴 하지만..) 이건 오작동을 막는다는 개념으로 알고 있다. 스크립트가 안먹는 곳에서 스크립트 때문에 오작동을 막기 위해서 html태그로 묶어 놓은 것이다. 하지만 실제로 저게 필요한 경우가 이제는 거의 없는 것 같고 안해도 되기 때문에 요즘은 거의 쓰지 않는 것 같다.

대신 요즘에는

//<![CDATA[
     스크립트.....
//]]>


로 묶어준다. 먼가 있어 보여서 쓰긴 했는데 이것에 대해서 정확한 이해를 한지는 얼마 되지 않았다. 이건 DOCTYPE를 XHTML로 사용할 때 써주는 것이다. (내가 HTML 4.01 Tranditional을 거의 쓰지 않아서 그쪽은 잘 모르겠다.) CDATA... XML을 해본 사람은 많이 보던 거란걸 느낄것이다.

XHTML은 기본적으로 형식이다. 스크립트 부분을 CDATA 속성으로 넣어줌으로써 XHTML 파서가 스크립트 부분에 들어간 html부분을 파싱하지 않도록 막아주는 것이다. 물론 대개의 경우 없어도 되지만 이렇게 함으로써 완전히 차단하는 것이다.

유효성검사를 통과하려면 반드시 CDATA로 스크립트를 묶어 주어야 한다. 저 형식은 왠지 잘 외워지지가 않아서... ㅋㅋ CDATA로 묶어 주는데 이부분은 스크립트 문법에 맞지 않지 때문에 //로 주석표시를 해준 것이다.


ps. //<![CDATA[를 제목에 썼더니 리스트에서 깨져버려서 별수없이 제목을 수정 2008.7.28

ps2. 앞쪽에 //<!-- //-->에 대해서 약간은 추측형으로 작성했었는데 이건 쓸 필요가 없다. 이것은 자바스크립트가 생긴지 얼마되지 않았을 때 웹브라우저가 <script>태그를 이해하지 못했기 때문에 화면에 자바스크립트 코드 자체를 화면에 출력해 주기 때문에 이걸 막기위해서 스크립트 부분은 html주석인 <!-- -->로 가려준 것인데 이젠 쓸 필요가 없다.

Posted by 1010
반응형

웹에서 파일을 첨부하려면 <input type="file" />을 사용한다. 자동으로 찾아보기 버튼이 생기고 파일브라우징이 가능하다.

사용자 삽입 이미지

input type=file은 약간의 특징이 있다. 파일을 업로드하는 기능을 가진 특성때문에 다른 input타입과는 다르게 약간의 제약이 있다. 그건 스크립트를 이용해서 제어하는 것을 막고 있는 것인데 그것 때문에 다루기가 좀 쉽지 않다. 하지만 그것보다 문제되는게 저 "찾아보기..."버튼이다. 점점 디자인이 강조되고 있는 가운데 기본적으로 뜨는 찾아보기 버튼은 웹디자이너에게는 걸리적거리는 것 같다.

항상 디자인을 받을 때마다 찾아보기 버튼대신에 이미지버튼으로 된 디자인이 왔었는데 이번에 여러가지 테스트를 해보았다. 결론적으로 말하자면 찾아보기버튼은 바꿀수 없다.(적어도 내 지식 수준에서는...) 물론 이에대한 태클도 있을꺼라고 생각한다.



가장 쉽게 생각할 수 있는 것이 input type=file을 input type=text와 이미지버튼의 조합으로 대치하는 것이다.

  1. <input type="text" size="30" id="txt" /> 
  2. <img src="" onclick="document.getElementById('file').click();" /> 
  3. <input type="file" size="30" id="file" style="display:none;" onchange="document.getElementById('txt').value=this.value;" /> 

위와같은 모양이다. 인풋파일은 보기에는 인풋텍스트와 버튼의 조합형태이기 때문에 앞에 인풋텍스트를 넣어놓고 그옆에 디자인된 이미지 버튼을 넣은 뒤에 인풋파일은 스타일을 주어서 보이지 않게 하는 것이다. 이미지 버튼을 onclick했을 때 인풋타입의 객체에 click()이벤트를 주는 구조이다. 파일선택하는 창도 아주 잘 뜬다. 인풋파일에 onchange이벤트를 주어서 파일선택해서 값이 들어갈때 인풋텍스트로 값을 복사해서 넣어서 찾아보기버튼을 이미지로 교체한 듯한 효과를 주는 것이다.

실제적으로 인터넷을 찾아보면 찾아보기 버튼 교체에 대한 위의 소스가 엄청 많다. 잘못된 정보의 대표적인 예라고 할 수가 있다. 서버쪽은 제대로 돌려보지도 않고 클라이언트쪽만 테스트 해보고 잘된다고 올려진 소스를 서로 계속 퍼나르고 있는 상황이다. ㅡ..ㅡ

인풋파일은 보안문제상 Read Only이기 때문에 스트립트로 값을 입력하는 것을 허용하지 않는다. 소스상으로는 아주 잘 돌아가는 거서럼 보이지만 막상 submit버튼을 누르면 전송이 되는 것이 아니라 인풋파일의 값이 clear되어 버린다. 스크립트로 실행한 것은 초기화 시켜버리고 다시한번 submit버튼을 눌러야 POST전송이 일어난다.

쉽게 말하면 이구조로는 절대 파일 업로드를 받을 수가 없다.



그래서 다른 방법을 찾기 시작했다.

  1. <input type="text" size="30" id="txt" /> 
  2. <span style="overflow:hidden; width:61; height:20; background-image:url(/images/button.gif);"> 
  3.     <input  type='file' id="file" style="width:0; height:20; filter:alpha(opacity=0);" onchange='document.getElementById('txt').value=this.value;'> 
  4. </span>   

그래서 찾은 방법이 위의 방법이다. 방법은 앞에서 얘기했던것과 거의 비슷하다. 파일명을 보여줄 인풋텍스트를 하나 보여주고 그 뒤에 span을 둔다. span은 찾아보기 버튼을 대체해 주는 역할을 한다. 크기를 정해주고 배경색으로 버튼 이미지를 지정해 준다. 그리고 그 span안에 인풋파일을 넣어주는데 여기서 스타일로 width를 0px를 주고 alpha값으로 투명도를 0을 준 것이다.

이렇게 하면 인풋파일의 파일명이 나타나는 부분의 width가 0px가 되기 때문에 나타나지 않고 찾아보기 버튼의 크기는 조절할 수가 없기 때문에 앞에 넣은 인풋파일뒤에 바로 찾아보기 버튼이 위치한다. 하지만 투명도가 0이기 때문에 실제 위치하고 있기는 하지만 보이지가 않고 span의 배경인 버튼 이미지가 보이는 구조이다.

하지만 여기에 약간의 문제가 있다. 일단 여기서 중요한 역할인 투명도를 나타내는 alpha값은 IE에서만 유효한 스타일값이다. Firefox에서는 투명도를 -moz-opacity:0; 를 사용해야 하는데 이걸 사용해도 Firefox에서는 IE같은 효과가 나지 않는다. 배경으로 지정된 이미지버튼이 나오지 않는다. 머 이것만으로도 요즘같은 분위기에서는 의미가 없다고 본다. 그리고 눈에 보이는 버튼이 실제버튼이 아니고 실제버튼은 투명하게 있는 버튼이기 때문에 클릭을 하면 실제 버튼보다 작게 점선이 생겨서 보기에 별로이다. 또한 저 소스에서는 width가 61로 설정이 되어있는데 브라우저마다 다른지는 모르겠지만 IE7에서는 찾아보기 버튼이 103px이기 때문에 이미지버튼도 103에 맞추어 져야 크기에 맞출수 있을것 같다.

앞의 방법보다는 좀 낫긴 하지만 이 방법에도 확실히 문제가 있다.


하지만 이런 방식으로 실제 구현해서 사용하려고 하면 더 큰 문제에 부딪히게 된다. 인풋파일의 경우 파일을 선택했다가 올리기가 싫어지면 그냥 지워주면 되는데 여기서는 편법을 써서 인풋텍스트를 눈앞에 보여주었기 때문에 지워도 인풋텍스트만 지워질뿐 실제 인풋파일의 내용이 지워진것이 아니다. 결국은 아예 한번 선택하면 지우지 못하도록 막아주던가(이렇게 할수는 있지만 기존의 사용자경험을 깨버린다고 생각하기에 별로 하고싶지 않았다.) 인풋텍스트의 값을 지우면 인풋파일의 값도 지워줘야 한다. 

그럴려면 천상 스크립트로 값을 지워져야 하는데 보안문제 때문에 인풋파일은 스크립트가 값을 바꿔버리는 것을 허용하지 않는다. 다른거에 하던 식으로

document.getElementById("file").value = "";

는 아예 먹지도 않는다.  대신에...

  1. document.getElementById("file").select();  
  2. //document.execCommand('Delete');     
  3. document.selection.clear();  

위와 같은 자바스크립트 코드를 이용하면 해당 인풋파일의 값을 지워줄 수 있다. 2번줄에 주석처리한 부분은 3번줄 대신 2번줄을 사용해도 된다. 둘줄 하나로 하면 된다. 물론 이 소스

(어찌된 일인지 글을 여기까지만 작성된채 공개됐다. 그럴리가 없는데 약간의 문제가 있었던듯.. 기억을 더듬어 글을 마무리 한다. 2008.7.17)
도 돌아가지 않는다. 위에 말한대로 보안문제 때문에 submit()할 때 문제가 생긴다.

인터넷을 찾아보다 보면 CSS를 이용해서 수십줄로 바꾸는 것도 있긴 한데 해보진 않았다. 버튼 하나 바꿀려고 여러문제는 가지게 되거나 아니면 수십줄의 코드를 넣는게 과연 의미가 있을까 하는 생각이 든다.

차라리 그 노력이면 요즘 게시판 등에서 많이 하는 추세대로 플래시 컴포넌트를 이용해서 바로바로 파일을 올릴수 있게 만드는 것이 훨씬 좋은 선택이라고 생각된다. 찾아보기 버튼은 왠만하면 그냥 쓰자.
Posted by 1010
반응형

제목이 좀 거창하기는 한데(ㅡ..ㅡ) 을 아예 이해를 못한채 개발된 코드를 좀 보게 된다. 개발이라는 것이 순수 자기 머릿속에 있는 것만 가지고 처음부터 끝까지 개발하는 사람이 어디 있겠는가... 요즘 같으면 개발능력이 검색 능력이라고 농담할 정도로 소스가 인터넷에 널려있고 그걸 갔다가 잘 조합하다보면 그럭저럭 돌아간다. 또한 사수나 이전에 구축되어 있는 사이트들도 있고.... 근데 여기서 돌아가는 동작을 이해하지 못하면 결국 잘못된 소스가 나올 경우가 많다.

실용주의 프로그래머에 보면 "디버깅을 하지 못하는 것은 원래 어떻게 돌아갔는지 몰랐기 때문이다."라는 말이 있다. 철저히 공감한다.






최근에 본 소스에 대해서 얘기를 해보려고 한다. 머 그녀석이 작성한 소스는 아니었지만 이런 내용을 보면 프로젝트의 일원으로써 기분나쁠수도 있지만 머 잘못된 것은 잘못된거다. 약간 상황상 초기단계에도 그 프로젝트의 소스를 좀 보았었는데 초반에도 많이 잘못된 부분이 있었는데 내가 관여할 상황이 아니기 때문에 그냥 나뒀다. 몇달만에 다시 보았을때는 괜찮은 사이트의 모습을 갖추고 있었지만 내부는 영 부실했다. 로그인 체크가 이런식으로 되어 있었다.

  1. if (isLogin) {  
  2.     // 로그인되었을 때의 동작  
  3. } else {  
  4.     // 로그인 안되었을때의 동작     
  5.  }  


동작은 중요하지 않으므로 그냥 한글로 처리했다. 아이디/패스워드를 입력하면 서블릿을 호출해서 결과값을 xml로 가져와서 파싱한다. 그리고 결과값을 isLogin에 넣어서 로그인 여부를 보여준다. 아마 작성자는 로그인을 하지 않았을때 권한이 없는 메뉴에 대해서 페이지가 넘어갔다가 오는 것도 낭비라고 생각한것 같다. Ajax로 할때 많이 하듯이 로그인 처리도 현재 페이지에서 바로 처리했고 권한이 없는 메뉴에 대해서 isLogin이라는 자바스크립트 변수로 접근하지 못하게 막고 있다.


이건 완전히 잘못됐다. 이건 브라우저 주소창에 다음과 같은 한줄만 입력하면 isLogin의 값을 접속자 맘대로 바꿔버릴 수 있다.

javascript:isLogin=true;void 0;

정확히는 모르겠지만 내가 보기엔 이건 해킹도 아니고 XSS(크로스 사이트스크립팅)도 아니다. 그냥 잘못만든거다. 보안 문제는 서버쪽에서 체크해야지 클라이언트단이 자바스크립트에서 하겠다는 생각은 잘못 된것이다.(물론 자바스크립트에서도 신경써야하는 보안문제가 있지만...) 자바스크립트는 유저 편의성과 HTML강화를 위해서 제공하는 것이지 자바스크립트로 모든 걸 다 할 수는 없다. Ajax를 쓰다보면 자바스크립트에서 처리해야 하는 부분도 있지만 이부분은 UI를 위한 부분이지 검증을 위한 부분이 아니기 때문에 검정을 Javascript에 의존하지 말고 당연히 서버쪽에서도 재확인 해주어야 한다.





여기서 또하나를 보자

  1. <script type="text/javascript">  
  2. var usrId = "<% session.getAttribute("userId") %>";  
  3.  
  4. if (userid != null) {  
  5.       로그인에 대한 동작  
  6. } else {  
  7.       <% <STRONG>session</STRONG>.<EM><STRONG>remove</STRONG></EM>("userId"); %>  
  8.       <% <STRONG>session</STRONG>.<EM><STRONG>remove</STRONG></EM>("memberType"); %>  
  9. }  
  10. </script>  


위 코드가 로그인하고 메뉴에 들어간 페이지에 들어있던 자바스크립트 코드이다. 무엇이 잘못된지 알겠는가.... 해당부분만 잘라온 라서 약간 헷갈릴수도 있지만 이건 JSP와 자바스크립트의 동작을 전혀 이해하지 못한 것이다. 그냥 보면 뭘 하고 싶었는지 까지는 이해할 수 있다. 세션에 값이 있으면 로그인하고 세션에 값이 없으면 로그인에 문제가 있었다고 생각하고 세션을 초기화 해주겠다는 것이다. 결론적으로 이 코드는 돌아가지 않는다.

아주 단순한 원리인데 인터넷에서 사람들이 질문하는 것을 봐도 이걸 이해하지 못하는 사람들을 꽤 많이 볼 수 있다.

웹이라는 것은 서버가 있다. 서버에는 웹서버가 있고 WAS(컨테이너포함)라고 얘기하는 웹어플리케이션서버가 있다. 설정나름이지만 이렇게 존재하는 이유는 서버에서 컴파일등의 동작이 필요없는 html, javscript파일, css, 이미지등을 사용자가 요청이 오면 그냥 돌려준다. 그렇지 않고 jsp등 서버의 해석이 필요한 페이지는 WAS가 페이지를 해석해서 나온 결과값을 원래의 html파일에 넣어서 사용자에게 돌려준다. 그러면 사용자의 웹브라우저(IE, Firefox 등등)가 해당 페이지를 받아서 렌더링을 한다. 여기서 웹브라우저가 html을 렌더링해서 보여주고 javascript를 해석해서 해당 동작을 수행한다.



이게 간단히 요약한 동작방식이다. 위에서 보듯이 jsp코드와 자바스크립트는 그 수행시점과 장소가 완전히 다르다. 그 순서로 보면 저위의 코드는 if문의 참여부의 상관없이 무조건 session.remove()가 동작한다. WAS는 jsp의 <% %>안에 있는 스크립틀릿 코드만 수행하지 그 외의 부분은 전혀 신경쓰지 않기 때문에....

그렇기 때문에 저 사이트는 첫페이지에서 세션을 심고는 두번째 페이지에서 무조건 세션을 날려버린다. 이런 동작방식을 이해하고 있어야 개발할 때 헷갈리지 않고 많이 나오는 질문중에 하나인 자바스크립트의 변수에 있는 값을 jsp의 변수에 넣으려고 하는 것이 불가능한지를 이해할 수 있다. (물론 js와 jsp간에 서로 값을 주고 받을 수 있는 프레임워크는 존재하지만 여기선 그 얘기가 아니므로....)



항상 어디서나 기본적인 개념이 중요하다는 생각......

Posted by 1010
반응형
어렵지 않은 거라고 안적어놨더니만 맨날 할때마다 책꺼내봐야하고.... 아놔~

window.open(URL, 윈도우명, 옵션);

이라고 하면 팝업을 띄울 수 있다. 네번재 파라미터도 있는데 네번째 파라미터는 이미 존재하는 창의 이름을 지정할때만 사용하며 브라우저 열어본 페이지 목록에 덮어씌울 것인지 새로 추가할 것인지를 지정한다. 기본값인 false는 새로 추가하는 것이다.

ex) window.open("http://blog.outsider.ne.kr", "" , "width=800,height=600,toolba=no");

dependent   부모의 종속된 윈도우를 연다(부모 닫으면 같이 닫힌다.)(no)
directories   개인북마크 or 링크바를 표시(yes)
height          높이(Min 100px)
width            넓이(Min 100px)
top               팝업의 위쪽 위치
left                팝업의 왼쪽 위치
menubar      메뉴바 표시 여부
toolbar         툴바 표시여부
location       주소표시줄 표시 여부
status          하단 상태표시줄 표시여부
resizable     크기변경 여부
scrollbars    스크롤바 표시 여부(내용이 창보다 클 경우)
modal           모달윈도우를 연다
minimizable  윈도 최소화 버튼 추가


window.open()은 해당 윈도우 객체를 리턴한다. 그러므로 팝업을 열고 팝업창을 제어하려면 객체로 받아서 핸들링 해주면 된다.

var popup = window.open("http://blog.outsider.ne.kr", "" , "width=800,height=600,toolba=no");
popup.moveTo(0,0);

moveTo()    창의 좌측 상단 모서리를 지정된 좌표로 이동
moveBy()    창을 지정된 픽셀 수만큼 상하좌우로 이동
resizeTo()  창의 크기를 절대적인 크기로 조절
resizeBy()  창의 크기를 상대적인 크기로 조절
focus()       창을 활성화한다
blur()          포커를스를 잃게 한다.
close()        창을 닫는다.


자신을 닫을 때는 window.close()나 self.close()를 사용하면 된다. 팝업에서 부모창에 접근하려면 opener를 이용하면 된다. 또한 name프로퍼티를 이용해서 target으로 사용할 수 있다.

popup에 관련해서 몇가지 보안관련 사항들이 있는데 자바스크립트는 자신이 연 창만 다시 닫을수 있고 다른 창을 닫으려면 사용자의 승인이 필요하다. 보이지 않는 팝업을 띄워서 악의적인 사용을 막기 위해서 너무 작은 크기(보통은 100px미만)로 축소할 수 없고 화면밖으로 이동시킬 수 없다.

팝업에 대한 자세한 정보는 모질라의 Dom Reference 에 자세히 나와있다
Posted by 1010
반응형
나는 XHTML을 사용하기를 즐겨한다. 물론 난 퍼블리셔는 아니고 개발자이다. 큰 회사라면 퍼블리셔를 따로 두겠지만 작은 회사에서는 개발자가 이것저것 다 해야 한다. 그리고 나는 웹표준 옹호론자이다. 그리고 웹표준을 하는 것이 전체 웹에 도움이 된다고 믿고 있기 때문에 내가 참여하는 사이트라도 웹표준화에 일조하고자 한다.(현실은 머 만만치 않지만....)

퍼블리셔라는 영역이 생기면서 약간 애매해 진것은 사실이지만 퍼블리셔를 따로 두고 있는 회사는 그렇게 많아보이지 않는다. 일단 웹표준을 지키려고 하는 회사도 그리 많지 않지만...  어쨌든 이전의 방식과 호환성을 가지기 위해 사용하던 HTML 4.01이 지나 이제는 XHTML 1.0으로 가는게 맞다고 생각하고 있다. 논쟁을 하고자 하는 건 아니고 새기술이 좋다고 생각하는 전제를 깔고 있고 더 엄격한 규칙을 가지고 더 좋은 웹을 만들수 있는 것은 확실하다.





XHTML을 사용하기 위한 문서의 기본 구조는 전에 올린 XHTML 1.0 Transitional 문서 템플릿 포스트를 참고하고 여기에 적용되는 몇가지 XHTML의 규칙을 설명하고자 한다. 이 규칙들은 이전 HTML에서는 유효했지만 XHTML에서는 유효하지 않은 규칙들이다. 정의된 문서를 먼저 설명하면(위 템플릿 참고)

XHTML은 DOCTYPE을 무조건 선언해 준다. 이 문서가 어떤 문서인지를 정의 하는 것은 반드시 해야하는 것이고 DOCTYPE없으면 XHTML 유효성 검사를 할 수 없다.(HTML 4.01에서도 반드시 쓰라) 브라우저는 DOCTYPE이 있으면 표준모드로 없으면 호환모드로 돌아간다. XHTML은 Transitional, Strict, Frameset 3가지 DTD가 있는데 유연한 Transitional이 과도기인 현재로써는 가장 맞다고 생각한다. Strict는 상당히 쓰기가 어렵고 Frameset은 써본적도 없고 써보려고 해본적도 없다. 그리고 DOCTYPE은 HTML문서의 최상단에 있어야 한다.

XHTML 1.0 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

XHTML 1.0 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

XHTML 1.0 Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

XHTML 1.1 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
(DTD는 w3c의 Recommended list of DTDs 참고)

그 다음에는 네임스페이스를 선언해 주는데 그냥 위 템플릿이라는 포스팅에 써진대로 복사해서 쓰면 된다.





XHTML에서 지켜야 할 몇가지 규칙을 정리해보자.(W3C 문서 참고 )

모든 태그는 소문자로 적는다. 과거에는 대문자로 쓰는게 일반적이었지만 XHTML에서는 반드시 소문자로만 작성해야 한다. 단 속성값이나 내용은 대소문자에 상관없다.
<BODY></BODY> - (X)
<body><body>     - (O)


모든 속성값은 인용부호 안에 사용하고 속성들 사이에는 띄어쓰기를 해야한다.
<img src="banner.gif" alt=배너 />   - (X)
<img src="banner.gif" alt="배너" /> - (O)


모든 속성에는 값이 있어야 한다. 값을 지정안하고 선언하는 속성들이 있었지만 XHTML에서는 보기에는 어색하더라도 모두 속성을 지정해 주어야 한다.
<input type="text" readonly>                   - (X)
<input type="text" readonly="readonly" /> - (O)


모든 태그는 닫아준다. 이전에는 안닫아주었지만 모든 태극는 닫혀햐 한다. 여는 태그가 있으면 닫는 태그가 있어야 하고 단독적으로 쓰이는 태그(img, input, br 등등)도 반드시 닫아준다. 보통 단독태그에 닫아주는 표시를 할때는 슬래시(/)앞에 한칸을 띄워준다.
<p>내용        - (X)
<p>내용</p> - (O)
<br>   - (X)
<br /> - (O)


주석안에는 더블대시를 사용하지 않는다.
<!------------------------> - (X)
<!--====================--> - (O)


모든 <와 &는 변환을 해주어야 한다. 내용중에 <, &는 &lt; 와 &amp; 로 바꾸어 주어야 한다.
<div>you & me < test</div>           - (X)
<div>you &amp; me &lt; test</div> - (O)

id 사용 - 링크태그의 타겟으로 사용되던  name을 대체한다.(하위호환을 위해 name도 동시 사용)

모든 img태그에는 alt태그를 반드시 사용해 준다. alt는 이미지를 보여주지 못할때 이미지를 대체해서 보여줄 대체택스트로 이미지에 대한 설명을 뜻한다. 브라우저가 툴팁으로 보여주어서 잘못 사용하고 있기는 하지만 툴팁은 title속성을 사용하여야 한다.





좀 다른 얘기로 스크립트 얘기를 하자만 한 문서에는 여러 스트립트가 가능하므로 기본적인 사용 스크립트를 메타태그를 이용해서 지정할 수 있다.
<meta http-equiv="Content-Script-Type" content="text/javascript">
라고 작성하면 된다  보통 이 메타태그가 없으면 브라우저는 자바스크립트가 기본이라고 생각한다.
<script type="text/javascript"></script> 가 정상적이다. MIME타입으로 text/script가 많이 사용된다는 이유로 RFC 4329가 승인했다. application/javascript를 더 권장하고 있지만 실제 브라우저에서 잘 지원되지 않고 있다. 또한 스크립트 코드에 language="javascript"로 작성된 것을 많이 볼 수 있는데 이것은 type이 지원되지 않을 때의 잔재인데 하위 호환성을 위해서 사용할 수도 있다.

참고로 CSS의 경우는
<meta http-equiv="Content-Style-Type" content="text/css" />
코드를 통해서 문서의 CSS스타일을 정의할 수 있다.





아래 부분은 XHTML에 해당되는 내용은 아니지만 XHTML을 사용할 때 구조적인 HTML을 구성하려는 의도가 더 강하다고 생각했을 때나 웹접근성을 생각했을 때 고려해야 할 부분

  • <b>보다는 <strong>를, <i>보다는 <em>을 사용한다.
  • 텍스트의 경우는 div가 아닌 <p> 태그를 사용한다.
  • 해드라인의 경우 div에 적당한 클래스를 주는 것이 아니라 <h1>, <h2>태그 등을 사용한다.
  • table태그에는 summary 속성을 지정할 수 있다. 대부분의 브라우저는 summary를 보여주지 않지만 시각장애인용 스크린리더등에서는 summary를 읽어준다.
  • 태그에 accesskey 속성을 주면(ex: accesskey="1") 사용자가 단축키로 사용할 수 있게 해준다.(하지만 대부분의 브라우저는 이를 사용자에게 보여주지 않기 때문에 사용법에 대한 것을 따로 알려주어야 한다.)
  • tabindex를 사용하면(ex: tabindex="1", tabindex="2") 사용자가 탭을 눌렀을 때 옮겨지는 form 컨트롤를 지정할 수 있다. tabindex가 없으면 소스에 나와있는 순서로 옮겨진다.
Posted by 1010
반응형
웹이 점점 화려해 지고 인터넷속도가 빨라지면서 웹페이지들은 점점 빨라지고 있고 디자인은 갈수록 중요해지고 있기 때문에 웹사이트에는(특히 국내에서) 정말 많은 이미지가 들어가고 있다. 근데 HTML 코드를 보다보면 정말 흔히 볼 수 있는 이미지버튼의 형태가

<a href="#"><img src="경로" alt="" /></a>

이런 형태이다. 나도 회사처음 들어왔을때 내 바로 윗사람이 이렇게 쓰는것을 권고하기도 했었고 대부분의 사람들이 이런 형태로 이미지 버튼을 만들고 있는데 이건 정말 잘못된 형태의 html이다. 무엇보다 이렇게 써서 얹을 수 있는 잇점이 단 한개도 없다고 생각한다.

저렇게 허위 a태그를 거는 상황은 100% 이미지를 버튼으로, 즉 클릭용으로 사용하기 위함이다. 그래서 img에 onclick 속성을 사용하고 있다.

<a href="#"><img src="경로" alt="" onclick="clickBtn();" /></a>

이렇게 이벤트까지 추가된 형태가 일반적이다.(물론 onclick도 인라인으로 하지 않고 따로 빼는게 표현과 기능의 분리면에서 더 낫기는 하지만 이건 여기서 논할 얘기는 아니니...) IMG태그 만으로도 클릭은 되는데 굳이 이렇게 A태그를 걸어준 단하나의 이유는 다른이미지랑 다르게 버튼처럼 보이게 하기 위해서 이다. 즉 이미지위로 마우스 커서가 이동했을때 클릭이 가능하다는 걸 사용자에게 알려주기 위해서 마우스 커서가 화살표에서 손모양으로 바뀌게 하기 위함이다. 그냥 이미지태그만 있어도 되는걸 커서바꾸자고 a태그로 감싸버린 것이다.

그럼 이렇게 하면 끝이냐... 브라우저마다 특성이 있긴 하지만 기본적으로 이미지에 A태그를 걸면 IE에서는 보기싫은 파란색의 테두리가 생겨버린다. 하이퍼링크가 달렸다는 것을 알려주기 위해서인데 요즘은 이걸 쓰는 사람이 없기 때문에 대부분은 border="0"을 주어서 해결한다.

<a href="#"><img src="경로" alt="" onclick="clickBtn();" border="0" /></a>

그럼 코드가 이렇게 되어버린다. 이미지버튼하나인데 코드가 너무 길어져버렸다. 단지 커서 바꾸자고???

이건 CSS를 사용하면 금방 해결할 수 있다.

  1. <style> 
  2. .btn {cursor:pointer;}  
  3. </style> 
  4. <img src="경로" alt="" class="btn" onclick="clickBtn(); /> 


커서의 모양을 바꾸는 것은 스타일로 해버리면 된다. (보통은 img에도 border:0을 기본적으로 주기는 하지만 이 상황에서 꼭 필요한건 아니다.) 그리고 심플한 img태그만 사용하면 된다. CSS를 사용한게 훨씬 많아 보인다면 웹사이트에 버튼이 한 100개쯤 있다고 생각해봐라. CSS는 공통적으로 쓸수 있으니 이미지 태그부분만 작성하면 끝이다.





A태그를 이미지를 감싸줄 필요가 없음을 얘기했고 그냥 하던대로만 하기에도 A태그를 사용했을 때의 문제가 있다. 좀 원론적인 웹표준얘기대로 A태그는 하이퍼링크를 위한 것이기 때문에 A태그는 하이퍼링크만 사용해 주는 것이 좋다. 이건 머 웹표준을 동의하지 않는 사람들에게는 그리 통하지 않을 논리고....

A태그의 구조를 보면 Anchor를 사용한 것임을 할 수 있다. Anchor는 다들 알고 있을꺼라고 생각하지만 간단히 설명하자면

<a href="#title">제목으로 이동</a>
........중간내용.............
<h3 id="title">제목</h3>

과 같이 사용하는 것이 Anchor이다. #과 같이 사용하며 #이 있으면 해당경로로 페이지를 이동시키는 것이 아니라 현재페이지에서 해당 id를 가지고 있는 엘리먼트를 찾아서 이동한다. 이걸 이용해서 #은 주고 id는 null을 주어버린 것이다. 그래서 페이지는 다른페이지로 이동하지 않고 현재 페이지에서 Anchor를 찾지만 찾지 못하는 허위 Anchor를 사용한 것이다.

말했듯이 Anchor는 현재 페이지의 해당위치로 이동하는데 이건 스크롤이 있어도 이동된다. 여기서 문제가 발생하는데 href="#"을 해 놓으면 무조건 페이지 최상단으로 이동한다. 이미지 버튼이 윗쪽에 있을 경우에는 상관없지만 스크롤 내려서 아래에 있다고 생각하면 버튼을 누를때마다 페이지 스크롤은 맨위로 올라가고 다시 스크롤 내려서 다른걸 해야하는 사용자의 편의성을 무진장 해친다...

거기에다가 Anchor도 URL에 포함되기 때문에 저 버튼을 누르면 주소맨뒤에 #가 붙게 된다. 크게 문제가 있다고 할 수는 없지만 보기에 좋지 않은건 사실이다. 그리고 자바스크립트 펑션을 호출해서 location.href로 페이지 이동만 할꺼라면 그냥 A태그에 경로를 주자!!




별거 아닌 내용으로 은근 길게 작성해 버렸다. 그냥 작업하는데 버튼마다 계속 A태그 달려있는거 보다가 짜증나서.. ㅎㄷㄷ

덧) 약간은 도전적인 제목이었는데 역시나 내 영역은 아니라 약간의 논란이 있었다. 보통 작성뒤에 잘못된 내용은 빨리 수정하는 편이지만 이번에는 애매모호한 면이 있어서 이 포스트를 읽으시는 분들은 아래 댓글들도 꼭 읽어주시기 바람. 위에 얘기한대로는 링크이동이 아닌 버튼의 경우에 a를 안쓸경우 선택할때 점선이 생기지 않아서 접근성을 해칠우려가 있음. 명확한 결론을 내리기 어려운 관계로 나라디자인의 정찬명님의 포스트 를 참고로 건다. 많이 고민해 보아야 할 문제...   2008. 11. 11
Posted by 1010
반응형
오랜만에 툴에 대한 소개를 하려고 한다. 내가 클라인트사이드 개발에 주로 사용하고 있는 aptana Studio 다. 전에부터 한번 하려고 했는데 IDE를 소개한다는 것은 기능이 워낙 많기 때문에 만만치 않은 일인데 머 간단히 소개정도만 하고 그 뒤로는 새로운 기능파악할 때마다 포스팅해야할 듯 하다.(전체소개 없이 각 기능 소개하기도 좀 머해서....)

사용자 삽입 이미지

제목에는 클라이언트 사이드 IDE라고 소개하기는 했지만 이곳에 중점이 되어 있을 뿐 PHP, Python도 개발이 가능하다. RadRails라고 해서 플러그인을 깔면 Ruby on Rails개발도 할 수 있다. 툴을 이것 저것 써보았지만 클라이언트 사이드(자바스크립트, CSS, HTML)에서는 aptana Studio만큼 맘에 드는 것을 아직 발견하지 못해서 클라언트사이드 개발에는 메인 IDE로 사용하고 있다. (흔히 괜찮은 자바스크립트 에디터가 없다고 하는데 aptana Studio는 그 이상이다.)

aptana사이트에서 다운로드 를 받을수 있고 무료이기 때문에 맘편히 사용할 수 있다. 초기에 나올때는 Communication버전과 Pro버전이 나뉘어져 있었는데 이번에 보니까 커뮤니케이션 버전이라는 말은 아예 사라진듯하다. 기본적으로 무료로 이용할 수 있도록 제공하고 있고 추가 기능이 필요한 사람들을 위해서 aptana Studio Pro(Pro의 추가 기능 )를 위한 구매메뉴를 제공하고 있다. (Jaxer와 Cloud도 있는데 둘다 사용해 보지는 않은데 내가 대충 개념잡기로는 Jaxer는 서버이고 Cloud는 호스팅서비스 같은거다.)

08년 12월 31일 현재 1.2.1버전까지 나와있고 Standalone과 Eclipse 플러그인 2가지 타입으로 다운을 받을 수 있다. 난 Standalone타입을 선호하는 편인데 취향에 따라 쓰면 되겠다. OS는 Windows, Linux, Mac을 모두 제공하고 있다. Linux나 Mac에서는 안서봤지만 다양한 플랫폼을 지원한다는 것은 무조건 좋은거다.. ㅎㅎㅎ 현재는 Standalone로 풀인스톨러로 받으면 130MB정도 한다. 다운받아서 그냥 설치해주면 된다.

사용자 삽입 이미지

자바개발자라면 너무나도 익숙한 인터페이스이다. 위에서 플러그인 형태로 제공하는 걸 보고 눈치챘겠지만 Aptana Studio는 오픈소스 IDE인 Eclipse 를 가지고 만든것이기 때문에 이클립스와 거의 흡사하다. 이클립스기반이기 때문에 이클립스가 요구하는 Requirements 는 그대로 요구하고 있다. 1.5이상의 JRE가 필요하다는 얘기이다. 자바런타임환경만 있으면 달리 구성할 환경은 별로 없다.

나는 툴 사용의 효율성에 관심을 많이 가지고 있는데 개발의 속도를 높이려면 툴의 익숙함이 상당히 중요하다고 생각한다. 그런면에서 이클립스를 사용하는 개발자라면 서버사이드와 클라이언트 사이드의 개발툴이 통일화되어서 따로 익숙해지는 과정이 필요없다는 것은 매우 큰 장점이다. 물론 이클립스를 쓴다면 특별히 클라이언트사이드의 코딩이 엄청나지 않는 이상은 이클립스에서 코딩하기도 하지만 지원하는 면에서 비교가 안된다고 생각한다. 나도 일일이 벌갈아가면서 하지는 않지만 aptana Studio의 기능이 이클립스에서 안되서 답답한 적이 많다.(물론 플러그인형태로도 제공하니까 플러그인을 쓰면 된다.)

그리고 또하나의 장점은 이클립스에서 사용하는 플러그인을 그대로 사용할 수 있다는 것이다. 오픈소스 이클립스를 지원하는 방대한 양의 플러그인의 규모는 엄청난데 SVN, MyLyn등등 그대로 다 쓸수 있는 것이다.



그럼 aptana Studio의 몇가지 기능을 살펴보자. 머 거창한건 아니고 간단한 기본기능들 위주로....이클립스를 안써본 사람도 있겠지만 기본적인 프로젝트 생성같은거는 이클립스랑 동일하기 때문에 굳이 언급하지 않겠다.

IDE의 기본 기능이면서도 개발자에게 가장 크게 와닿는 것중 하나가 코드 어시스트이다. 클라이언트 사이드에서 aptana Studio가 제공하는 코드어시스트는 강력하다. 많은 툴을 다뤄본 것은 아니지만 내가 만져본 것들 중에는 aptana Studio가 제공하는 코드 어시스트가 가장 강력한것 같다.

사용자 삽입 이미지 사용자 삽입 이미지 사용자 삽입 이미지

html, CSS, javascript할 꺼 없이 거의 완벽하게 코드어시스트를 제공해주고 있다. CSS경우는 각 속성에 대한 이름뿐만 아니라 사용할 수 있느 값들까지도 제공하고 있으면 자바스크립트의 경우는 키워드, 함수명, DOM을 다 제공해 줄뿐만 아니라 위의 이미지처럼 사용자가 만든 function까지도 파라미터값까지도 보여준다. 사용할수 있는 키워드를 타이핑할 때마다 직관적으로 보여주고 그 오른쪽에는 지원되는 브라우저가 아이콘으로 표시되기 때문에 크로스브라우징에 맞추어서 개발하는데 정말 편하다. 오른쪽에는 해당 키워드에 대한 간단한 설명까지 나오기 때문에 부족함이 없을 정도이다.

html, css, javascript에서 자주 사용하는 엘리먼트를 바로 추가할 수 있도록 상단에는 아이콘들이 있는데 마우스를 써야 되니까 잘 쓰게 되지는 않는것 같다. ㅎ

사용자 삽입 이미지

코드 어시스트에서 보여주는 브라우저 호환에 대한 부분은 [window] - [Preferences]에 들어가서 [Aptana] - [Browsers/User Agents]에서 설정해 줄 수 있다. 여기서 필요한 브라우저를 체크할 수 있다. (아직 크롬은 없다. ㅎ) 이렇게 설정하면 아래처럼 선택한 브라우저의 호환성을 코드어시스트에서 제공 받을 수 있다.

코드어시스트 브라우저 호환성

위에서 본 에디터 부분에서 기본적으로 소스창을 보지만 따로 브라우저를 띄우지 않고 aptana Studio안에서 IE와 FF에서 미리보기를 해 볼 수 있다.

에디터 하단

아래쪽 탭을 선택하면 바로 볼 수 있으면 추가를 누르면 미리보기 셋팅을 추가해 볼 수 있다.(현재는 브라우저는 IE, FF만 제공하고 있다.) 여기서 볼때도 스크립트 에러가 나는 경우는 바로 표시가 된다.


CSS파일을 만들때도 preview를 제공하고 있는데(HTML에 들어가는 스타일부분 말고 확장자가 .css로 된 파일들....)

CSS 미리보기

CSS파일을 편집할때는 하단쪽 탭이 Preview로 나오게 되는데 실제 html에 적용된걸 보려면 html을 실행시켜서 봐야하기는 하지만 내가 작성한 css를 바탕으로 기본으로 제공되는 텍스트를 통해서 각 엘리먼트가 어떤식으로 보여지는 지를 간단하게 미리볼 수 있다. 오른쪽 톱니바퀴 아이콘을 눌러서 Edit Default preview template를 누르면 CSS preview에서 제공하는 텍스트를 수정해서 사용할 수 있다. file preview setting을 클릭해서 현재 프로젝트의 html파일을 선택해주면 프리뷰를 원하는 형태로 볼 수도 있다.

사용자 삽입 이미지

그리고 이게 코드어시스트말고  내가 aptana Studio를 좋아하는 큰 이유중 하나인데 html파일에서(jsp, asp, php같은 서버측코드는 해석할 수 없으므로...) Run AS - JavaScript Web Application을 시작하면 aptana Studio 내부의 Jaxer서버가 시작되면서 해당 페이지를 구동시켜준다.(정확히는 프로젝트째..)

http://127.0.0.1:8000/Test/new_file.html 와 같은 형태의 주소로 구동되기 때문에 주소를 이용해서 다양한 브라우저에서 쉽게 테스트해볼 수 있다. 수정하면 바로바로 확인해 볼 수 있고 프로젝트 이름이 붙기는 하지만 적대주소도 사용할 수 있기 때문에 아주 유용하다. ㅎㅎ

사용자 삽입 이미지

Run As에서 Run을 눌러서 설정창을 띄우면 서버실행할 때 자동으로 구동시킬 웹브라우저 및 여러가지 설정사항을 지정해 줄 수 있다.



이렇게 개발하는데 도움이 될만한 대략적인 기능들을 살펴봤다. IDE이기 때문에 그 기능은 엄청나고 많이 알면 알수록 개발의 효율은 높아질 것이다.

이외에도 클라이언트사이드개발을 위해서 많은 기능들을 가지고 있다.

프로젝트를 생성할 때 다양한 자바스크립트 프레임워크들을 선택해서 기본적으로 프로젝트에 포함 시킬수 있고 FTP연결연결하거나 Outline뷰에서 DOM트리를 보거나 js파일에서 함수구조를 본다던가 하는 등 많은 기능을 가지고 있다. aptana Studio 짱좋아.. ㅎㅎㅎ
Posted by 1010
반응형
웹개발을 하는데 있어 성능에서 중요한 요소중 하나는 용량을 줄이는 것이다. 전송해야할 파일의 용량이 줄어들면 사용자입장에서는 더 빠르게 로딩할 수 있고 서버측에서는 트래픽이 줄어들기 때문에 많은 이점을 가질 수 있다. 그래서 자바스크립트 코드를 압축해서 js파일의 용량을 줄이는걸 도와주는 툴들이 있다. 이번에 Ajaxian에서 YUI Compressor Online 가 나왔다는 기사가 떴길래 겸사겸사해서 정리해서 올린다.

자바스크립트 압축(Minification)이란 것은 보통 자바스크립트 코딩을 할 때 가독성을 위해서 들여쓰기등 공백이 많이 들어가게 되어 있는데 이런 것을 없애고 코드를 다닥다닥 붙혀서 크기를 줄여주는 것이다. 압축은 말그대로 크기를 줄여주는 것이고 암호화(obfuscation)라는 것도 있는데 이것은 변수나 함수명을 이상하게 바꾸어서 코드를 읽기 어렵게 만든다. 당연히 둘다 함께 할수도 있다.

하지만 암호화의 경우는 자바스크립트의 특성상 약각 읽기만 어렵게 만들어 놓은것 뿐이고 해독툴들을 써서 다시 어느정도 보기좋게 할 수도 있기 때문에 결과적으로 암호화라는 큰 의미는 없다. "웹사이트 최적화 기법"을 보면 사이즈면에서 압호화의 효과는 미비하기 때문에 별로 추천하고 있지 않고 있는데 선택은 각자 나름이고 혹 관심이 있다면 YUI의 글 을 참고바란다.

내가 아는 것으로는 3가지 서비스가 있다.




JSMIN

JSMIN 부터 보자. 자바스크립트계의 요다라고도 불리는 JSON 을 창시한 더글라스 크록포드(Douglas Crockford)가 만든 JavaScript Minifier이다.

JSMIN 사이트

JSMIN은 JS파일을 압축하는 기능을 가지고 있는 간단한 프로그램(?)형태로 제공되고 있다. 위에 보는다와 같이 사이트에서 다양한 언어로 제공되고 있기 때문에 취향에 따라서 가져다가 사용할 수 있다. 일반적인 윈도우 환경에서는 MS-DOS.exe형태로 배포되는 JSMIN을 가져다가 사용하면 된다.

JSMIN 실행화면

JSMIN.EXE를 받아서 js파일이 있는 곳에 놓고는 위와같이 실행하면 된다.  명령어는

jsmin <압축할파일> 새로만들 파일명 "주석"

와 같은 형태로 사용하면 된다. 뒤에 주석부분을 적지 않아도 되고 적을 경우는 새로만들 js파일 최상단에 주석에 넣은 부분이 주석형태로 추가된다.

압축된

  1. /*********** before Minification **************/ 
  2. var checker = false; // 체커  
  3.  
  4. function test() {   
  5.     alert(checker);  
  6. }  
  7.  
  8. test(); // 실행  
  9.  
  10. /*********** after Minification **************/ 
  11. var checker=false;function test(){alert(checker);}  
  12. test();  

JSMIN으로 prototype.js를 압축한 모습이다. 보는바와 같이 주석과 공백등은 모두 없애고 특정단위별로 한줄씩 적어주어 용량을 줄여주고 있다.




/packer/

Dean Edwards 가 만든 자바스크립트 압축기 packer 이다.

packer

웹상에서 간단하게 사용할 수 있다는게 큰 장점이고 옵션으로 Base62 압호화와 변수이름 축소(Shrink variables)를 적용할 수 있다.

  1.  
  2. /*********** before Minification **************/ 
  3. var checker = false; // 체커  
  4.  
  5. function test() {   
  6.    alert(checker);  
  7. }  
  8.  
  9. test(); // 실행  
  10.  
  11. /*********** after Minification **************/ 
  12. var checker=false;function test(){alert(checker)}test();  
  13.  
  14. /*********** after Minification : Base62 encode **************/ 
  15. eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('2 0=3;4 1(){5(0)}1();',6,6,'checker|test|var|false|function|alert'.split('|'),0,{}))  
  16.  
  17. /*********** after Minification : Shrink variables **************/ 
  18. var checker=false;function test(){alert(checker)}test();  
  19.  

예제소스가 짧아서 Shrink variables가 차이가 없게 나타나버렸다  ㅡ..ㅡ 암호화는 코드읽는 능력이 좋아서 읽을수 있다면 어쩔수 없지만 저 간단한 코드를 도저희 머하겠다는 건지 모를 코드로 만들어 놓았다. 하지만 딘에드워즈가 친절하게 unpacker 도 만들어주었고 변수이름까지 고대로 잘 디코딩 된다는거~~




YUI Compressor

Yahoo User Interface Library에서 제공하는 YUI Compressor 이다. jar파일 형태로 제공되고 있고 사용하려면 자바 1.4이상이 필요하다. 그냥 사용하기는 좀 불편한것 같고(사용까진 안해봤다.) 이걸 이용해서 만든 서비스들이 있다.

사용자 삽입 이미지

이 포스팅의 계기를 만들어 준 Rodolphe STOCLIN 가 만든 YUI Compressor Online 이다. 깔끔한 인터페이스에 얼마나 압축이 되었는지도 시각적으로 표시해 준다.

  1.  
  2.  
  3. /*********** before Minification **************/ 
  4. var checker = false; // 체커  
  5.  
  6. function test() {   
  7.    alert(checker);  
  8. }  
  9.  
  10. test(); // 실행  
  11.  
  12. /*********** after Minification **************/ 
  13. var checker=false;function test(){alert(checker)}test();  
  14.  
  15. /*********** after Minification : Minify only, do not obfuscate **************/ 
  16. var checker=false;function test(){alert(checker)}test();  
  17.  
  18. /*********** after Minification : Preserve all semicolons **************/ 
  19. var checker=false;function test(){alert(checker)}test();  
  20.  
  21. /*********** after Minification : Disable all micro optimizations **************/ 
  22. var checker=false;function test(){alert(checker)}test();  
  23.  
  24.  


먼 차이냐 ㅡ..ㅡ 소스가 간단해서 그런가... 어쨌든 이녀석은 약간 문제가 있다. 한글이 들어갈 경우는 EUC-KR이든 UTF-8이든 한글이 모두 ?로 깨져버린다. 코드에 한글이 들어가 있으면 사용못한다는 얘기다.

Online Javascript/CSS Compression Using YUI Compressor 사이트

Online JavaScript/CSS Compression Using YUI Compressor 는 디자인이 평이해서 그렇지 완성도가 더 좋은편이다. 웹상에서 직접 압축하는 것과 파일로 하는 것을 모두 지원하면 js뿐만아니라 CSS의 압축까지도 지원하고 있다. 압축후에는 용량이 어떻게 어떻게 달라졌고 몇퍼센트가 달라졌는지 표시해 주고 있다.

  1. /*********** before Minification **************/ 
  2. var checker = false; // 체커  
  3.  
  4. function test() {   
  5.    alert(checker);  
  6. }  
  7.  
  8. test(); // 실행  
  9.  
  10. /*********** after Minification **************/ 
  11. var checker=false;function test(){alert(checker)}test();  
  12.  
  13. /*********** after Minification : Minify only, do not obfuscate **************/ 
  14. var checker=false;function test(){alert(checker)}test();  
  15.  
  16. /*********** after Minification : Preserve unnecessary semicolons **************/ 
  17. var checker=false;function test(){alert(checker);}test();  
  18.  
  19. /*********** after Minification : Disable all the built-in micro optimizations  **************/ 
  20. var checker=false;function test(){alert(checker)}test();  
  21.  
  22.  

여기서는 Preserve all semicolons 옵션이 적용되는군....




한꺼번에 툴을 여러개 소개하다보니 포스팅이 좀 길어지긴 했는데 얼마나 줄어드나 보자. 테스트는 2가지 파일로 했다. 소스를 작성하는 형태가 각자 다르기 때문에 압축률에서도 상황에 따라 달라질것으로 생각한다. 내가 최근 프로젝트에서 만들고 있는 49KB짜리 script.js랑 보편화된 127KB짜리 prototype.js를 가지고 테스트 했다.

JSMIN
script.js -> 36KB
prototype.js -> 94KB

/packer/
script.js -> 36KB
script.js -> 22KB (Base62 encode)
script.js -> 32KB (Shrink variables)
prototype.js -> 93KB
prototype.js -> 51KB (Base62 encode)
prototype.js -> 76KB (Shrink variables)

YUI Compressor Online
script.js -> 33KB
script.js -> 35KB (Minify only, do not obfuscate)
script.js -> 35KB (Preserve all semicolons)
script.js -> 35KB (Disable all micro optimizations)
prototype.js -> 74KB
prototype.js -> 93KB (Minify only, do not obfuscate)
prototype.js -> 94KB (Preserve all semicolons)
prototype.js -> 94KB (Disable all micro optimizations)

Online JavaScript/CSS Compression Using YUI Compressor
script.js -> 34KB
script.js -> 36KB (Minify only, do not obfuscate)
script.js -> 34KB (Preserve unnecessary semicolons)
script.js -> 34KB (Disable all the built-in micro optimizations)
prototype.js -> 75KB
prototype.js -> 94KB (Minify only, do not obfuscate)
prototype.js -> 75KB (Preserve unnecessary semicolons)
prototype.js -> 75KB (Disable all the built-in micro optimizations)


다양하게 테스트한건 아니라서 절대성능비교라고 하기는 좀 그렇고 그냥 참고용이다.

압축화할때는 조심해야 할게 있다. 보면 약간 걱정되는 것처럼 이게 돌아갈까? 하는 생각인데 생각대로 이건 조심해야 된다. 공백이 없어지는 바람에 소스가 달라붙어서 의도하지 않은 오류가 나지 않아야 한다. 이건 충분히 일어날 수 있는 일이기 때문에 평소 코딩습관을 잘 들이는게 좋다고 생각한다. 더글라스 크록포드는 이런 자바스크립트 검증을 위해서 Javascript VarifierJSLint 를 제공하고 있다.

압축을 하고 난 다음에는 솔직히 유지보수를 할수 없는 지경이기 때문에 개발소스는 그대로 유지하고 배포할때 압축하는 게 맞는 방법인것 같다. 그래서 다들 Java파일 같은 라이브러리로 쓸수 있는 형태로 제공하는 것으로 보인다.
Posted by 1010
반응형
보통 웹사이트를 구축하면 헤더나 푸터등 공통된 부분이 있기 때문에 이런 부분은 별도로 만들어서 공통으로 사용하게 한다. 각페이지에 헤더,푸터파일을 인클루드해서 사용할 수도 있지만 그렇게 되도 반복코드가 많이 발생하니까 일반적으로는(그냥 내 생각에.. ㅡ..ㅡ) 템플릿 파일을 만들고 contents부분만 바꿔가면서 사용하지 않을까 싶다.(일단 난 그렇게 한다 ㅡ..ㅡ 전에 올렸던 포스팅처럼...)

이렇게 할때 가장 큰 문제가 자바스크립트 초기화 코드이다. 항상 바꿔치기할 contents부분은 <body>의 정중앙에 들어있는데 보통 스크립트는 <head>안에 있거나 <body>맨아래 있단 말이지. contents부분에 들어갈 페이지에 스크립트코드를 같이 써줘도 되기는 하지만 완성된 html에서 중간에 스크립트 코드가 들어가기 때문에 별로 좋은 방법은 아니라고 본다.

여기서 초기화코드라는 것은 머 여러가지가 될수 있는데 쉽게 페이지 로딩후(onload)에 자동으로 수행할 함수를 말한다. 가장 많이 쓰는데 이벤트 핸들러 등록이라던가 하는거고 onload후에 focus를 어디에 둔다던지 하는등의 코드를 말한다. 페이지가 다 다르게 생겼으므로 이런 코드도 다 다를 수 밖에 없는데 contents에 들어갈 페이지에서는 이걸 다룰수가 없다는게 고민거리였다. 물론 if-else문으로 해당 엘리먼트가 있는지 라든가 페이지 주소를 이용해서 억지로 할수야 이겠지만 쓸데없이 검사해야 하기 때문에 성능도 떨어지고 별로 알흠답지 못한 방법같았다. 이벤트 핸들러의 경우 html 엘리먼트에 직접 써넣는게 일반적이지만(<input type="button" onclick="test();"> 이렇게...) 요즘 추세는 자바스크립트도 완전히 분리하는 것이기 때문에 이걸 분리하자면 초기화코드가 꽤 많아진다. (이게 Unobtrusive Javascript.... 이렇게 하면 디자인 바뀌어도 많이 손 안대도 된다. 물론 Unobtrusive Javascript가 말하고자 하는건 저게 중점은 아니지만 개인적으로는 큰범주에서 보면 같은 흐름이라고 생각한다.)



어쨌든 이번에 플젝하면서는 이걸 좀 해결해 보고 싶었기 때문에 OKJSP 에 질문글을 올렸더니 임은천님이 답변 을 해 주셨다.(거의 익명사이트긴 하지만 도움얻은걸 혼자한척 하진 않는다.. ㅡ..ㅡ) 딱 내가 기다리던 명쾌한 답변.... 너무 자세하게 답변을 주셔서 구현하는데 별로 어렵지 않았다.

  1. document.observe('dom:loaded', function() {  
  2.     <% if (request.getAttribute("jsDispatcher") != null && !request.getAttribute("jsDispatcher").equals("")) { %>  
  3.     var dispatcher = new Dispatcher();  
  4.     var jdName = "<%= request.getAttribute("jsDispatcher") %>";  
  5.     eval(dispatcher.get(jdName));  
  6.     <% } %>  
  7. });  

위의 코드를 Template의 부모(?)가 되는 페이지의 스크립트 부분에 넣어준다. 물론 저 코드는 Prototype Framework의 코드이다. 쉽게 가자면 window.onload에다가 이벤트를 건거다. 여기선 JSP코드니까 JSP로 jsDispatcher이 파라미터로 넘어왔는지를 검사하고 jsDispatcher값이 있으면 디스패쳐를 실행한다. 물론 템플릿에 어떤 페이지를 contents부분에 띄워줄지 파라미터로 넘겨줄때 jsDispatcher의 값도 같이 넘겨주어야 한다. 어차피 템플릿으로 구성되는게 구현되어 있을테니까 파라미터 하나 더 넘겨주는건 그리 어렵지 않은 일이다.

디스패쳐가 각 jdName별로 실행할 함수목록을 가지고 있고 파라미터로 넘겨받은 jsDispatcher의 이름으로 디스패쳐에다가 조회해서(get) 해당 실행할 함수들을 가져오고 그자리에서 eval()해서 실행해 버리는거다. 이것 자체가 window.onload때 실행되니까(Prototype.js의 dom:loaded는 약간은 다른의미지만 여기선 별로 중요하지 않다.) 디스패쳐로 가져온 값도 페이지 초기화코드로 실행된다. 물론 여기서 Dispatcher은 이어서 만들 클래스이다. 원래 제공되는게 아니라...



그럼 Dispatcher클래스를 보자.

  1. var Dispatcher = Class.create();  
  2. Dispatcher.prototype = {  
  3.     initialize : function() {},  
  4.     get : function(name) {  
  5.         return this.map[name];  
  6.     },  
  7.     map : { listform: 'ListenerCollection.registEventListFrom()',  
  8.                   writeform: 'ListenerCollection.registEventWriteFrom()',  
  9.                   modifyform: 'ListenerCollection.registEventModifyForm()' 
  10.     }  
  11. }  
  12.  
  13. var ListenerCollection = {  
  14.     registEventListFrom: function() {  
  15.         // 리스트 페이지의 초기화 코드들  
  16.     },  
  17.     registEventWriteFrom: function() {  
  18.         // 작성 페이지의 초기화 코드들  
  19.     },  
  20.     registEventModifyForm: function() {  
  21.         // 수정 페이지의 초기화 코드들  
  22.     }  
  23. }  

여기에는 Dispatcher와 ListenerCollection 2가지 클래스가 있다.(Prototype.js의 관점에서는 Dispatcher만 클래스이지만 그냥 넘어가자.)

Dispatcher클래스는 3가지 매서드가 있다.  initialize는 보는바와같이 아무것도 없는데 prototype.js의 클래스에선 필수로 만들어주어야 하는거라서 신경안써두 되고 get하고 map이사용할 메서드이다. map은 넘겨받은 이름과 함수가 쌍으로 맵핑되어 있고 get에서 넘겨받은 name으로 map에서 찾아서 해당 함수를 돌려준다.

ListenerCollection은 등록할 이벤트리스너(꼭 이벤트리스너일 필욘 없지만)의 코드목록을 담는 곳이다. map내애서 funcion(){}으로 바로 적어줄 수도 있지만 코드량이 많아서 분리했다. 약간 꼬아놔서 그렇지 구조는 별로 어렵지 않다.



이렇게 하면 템플릿을 유지하면서도 페이지별로 초기화 자바스크립트 코드를 따로 둘 수 있다. 모든 페이지에서 이코드가 들어가긴 하지만 위쪽에서 onload로 이벤트를 건 곳을 제외하고는 외부 js파일로 빼면 어차피 캐시가 되기 때문에 성능면에서는 별로 신경안써도 될듯하다. prototype.js를 기반으로 작성되서 prototype.js를 안써본 사람은 약간 코드이해에 어려움이 있을까 좀 걱정되긴 한다...
Posted by 1010
반응형
Script.aculo.Us에서는 드래그앤드롭(Drag N Drop)을 쉽게 구현할 수 있는 클래스가 있는데 Draggable(Droppables)과 Sortable 2개의 클래스이다. 둘다 드래그앤드롭을 위한 클래스인데 Draggable는 객체를 드래그 가능하게 만드는 클래스이고 Sortable은 드래그앤드롭이 되면서 정렬이 가능하도록 하는 클래스이다. 정렬을 하고자 한다면 Sortable을 사용하는 것이 편하고 여기서 정리하려는 것은 Sortable이다.

Sortable.create('id_of_container',[options]);

위 코드이 Sortable 을 사용하는 기본 문법이다. id_of_container에 드래그앤드롭을 가능하게 할 엘리먼트의 id를 주고 options에 드래그앤드롭에 대한 옵션을 JSON형태로 던져주면 바로 정렬가능한 드래그앤드롭을 사용가능하다.  id_of_container이라고 쓴 것처럼 드래그할 객체가 아니라 드래그할 객체들을 담고 있는 container의 id를 주면 되고 options는 안주면 디폴트옵션으로 동작하게 된다.

예를 들어

  1. <ul id="contailner"> 
  2.     <li id="dnd_1">Test 1</li> 
  3.     <li id="dnd_2">Test 2</li> 
  4. <ul> 
  5. <script type="text/javascript"> 
  6.     Sortable.create("contailner");  
  7. </script> 

위와같이 작성하면 dnd_1, dnd_2객체가 바로 드래그앤드롭이 가능하다. (이 얼마나 간단하단 말인가. ㅎㅎㅎ)

이제 옵션을 보자. 자유롭게 사용하려면 옵션을 주어서 원하는 형태로 사용하여야 한다. 옵션은 Draggable과 공통적인 것도 있고 아닌것들도 있다.(아직 Script.aculo.us의 API리스트는 솔직히 좀 아쉽다.) API와 내가 테스트해본걸 바탕으로 적었지만 빠진 부분이 있을수도 있다.

tag : 여기에 HTML태그명을 주면 해당 태그에 대해서 Sortable이 동작하게 된다. 디폴트는 li태그이고 container아래 한단계 밑까지만 동작한다. 쉽게 말해 li안에 li가 또 들어있다고 하더라도 안에 있는 li에는 드래그앤드롭이 동작하지 않는다. Block엘리먼트에만 가능하고 table같은걸 블가능하다.

only : 이 옵션을 주고 여기서 class명을 지정하면 tag에 설정한 태그명이라고 할지라도 only에서 준 class명과 맞지 않으면 드래그앤드롭이 동작하지 않는다.

overlap : 가로 리스트는 horizontal, 세로 리스트는 vertical로 설정하라는데 정확한 동작은 잘 모르겠다.

constraint : horizontal, vertical, false 3가지가 있고 드래그앤드롭의 방향을 설정한다. horizontal/vertical로 설정할 경우에는 가로/세로로만 이동하며 false나 옵션을 주지 않았을 경우에는 어떤 방향이든지 이동이 가능하다.

containment : 이곳에 container 리스트를 지정하고 이곳에 지정한 container간에는 드래그앤드롭이 가능하다.

handle : 드래그앤드롭을 할 엘리먼트에서 전체가 아닌 특정부분만을 이용해서 드래그앤드롭이 가능하도록 하고 싶을때 handle이용한다. 이곳에 id 혹은 class명을 지정하면 핸들러로 사용할 수 있다.

delay : 드래그앤드롭으로 반응할 시간을 미리세컨단위로 설정할 수 있고 기본은 0이다. 너무 민감하게 반응하지 않기를 바랄때는 delay의 숫자를 크게 지정할 수 있다.

dropOnEmpty : true로 설정하면 container가 비어있을때도 drop이 가능하다. false일 경우에는 container에 다른 드래그앤드롭객체가 있을때만 드롭이 가능하다. 기본은 false

scroll : 기본으로는 지정되어 있지 않으며 window로 설정할 경우에는 드롭할 container가 화면밖에 있을경우에 드래그객체가 화면밖으로 나가면 자동으로 스크롤한다.

scrollSensitivity : 기본은 20이고 스크롤이 되게 하기 위해서 넘어가야하는 크기를 지정한다.

scrollSpeed : 스크롤 속도이고 픽셀로 지정하면 기본은 15이다.

onChange : 콜백함수로 드래그앤드롭을 시작하는 등 객체의 위치가 변경되면 계속 발생한다.

onUpdate : 콜백함수로 드래그앤드롭을 하여 실제 순서의 변화가 생겼을때만 발생한다.




아주 간단한 예제를 만들었다. 동작과 소스코드를 보면 쉽게 이해할 수 있을꺼라고 생각한다. 최근 작업을 하면서 몇가지 주의점(?)을 발견한 거라면...

  • container의 id에 언더바(_)가 들어가면 동작하지 않는다.
  • Sortable.serialize를 사용하려면 드래그앤드롭 엘리먼트의 아이디가 언더바(_)로 이어져야 한다. 언더바 뒤쪽에 있는 문자만 표시된다.
  • IE에서는 왼쪽 콘테이너에서 오른쪽 콘테이너로 갈때 드래그엘리먼트가 컨테이너 뒤쪽으로 가는 문제가 생긴다. 드롭하기 위해서 반이상 넘어갈 경우에는 위로 올라오는데 이건 IE의 z-index버그때문에 생기는 문제로 예상되는데 정확한 해결책은 아직 찾지 못했다.
Sortable.serialize는 해당 컨테이너에 있는 드래그앤드롭객체를 순서대로 보여준다. 이것은 위치정렬을 한 후에 Ajax등을 통해서 새로 정렬한 위치를 서버에 저장할 수 있도록 하는 역할을 한다.

그리고 예제의 소스를 보면 알겠지만 기본적으로는 드래그앤드롭을 할 때 해당위치의 공간은 표시하지만 따로 표시되지는 않는다. 이 문제를 해결하기 위해 더미 엘리먼트를 만들었다. OnChage가 발생할 때 해당 엘리먼트의 바로 앞쪽에 더미엘리먼트를 만들어서 insert한다. 이렇게 함으로써 드롭했을때 떨어질 위치가 명시적으로 보일수 있도록 하고 OnChange는 계속 발생하기 때문에 처음에 더미엘리먼트를 지우고 다시 넣어주기 때문에 다른 컨테이너로
Posted by 1010
반응형

jQuery로 작업하기, 3부: jQuery와 Ajax로 RIA 만들기: JQuery: 내일 나올 웹 응용을 오늘 구현해보자

Effects 모듈과 Ajax

developerWorks
문서 옵션
수평출력으로 설정

이 페이지 출력

이 페이지를 이메일로 보내기

이 페이지를 이메일로 보내기

샘플 코드

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Michael Abernethy, 제품 개발 관리자, Optimal Auctions

옮긴이 : 박재호 이해영 dwkorea@kr.ibm.com

원문 게재일 : 2008 년 10 월 28 일
번역 게재일 : 2009 년 1 월 13 일

JQuery는 동적 RIA를 쉽게 개발하는 방법에 목마른 개발자를 위한 자비스크립트 라이브러리로 각광을 받고 있습니다. 브라우저 기반 응용이 데스크톱 응용을 계속 대체하고 있기에, 이런 라이브러리 활용 역시 꾸준히 증가 추세에 있습니다. jQuery 연재물에서 jQuery로 웹 응용 프로젝트를 구현하는 방법을 살펴봅시다.

도입

jQuery는 지난 몇 개월 동안에 웹 개발자를 위한 유력한 자바스크립트 라이브러리로 급속도로 세를 넓혀가고 있다. 이런 현상은 브라우저 기반 응용으로 데스크톱 응용을 교체하기 위한 RIA(Rich Internet Application) 활용과 필요성이 급격하게 늘어나는 상황과 맞물려 돌아간다. 스프레드시트부터 급여 계산에서 전자편지 응용에 이르기까지 브라우저로 데스크톱 응용을 교체해 나가는 현실이다. 이런 응용 개수가 많아지고 복잡해지면서 자바스크립트 라이브러리는 응용을 만드는 튼튼한 기초로 더욱 더 중요성이 높아질 것이다. jQuery는 개발자를 위한 필수 라이브러리가 되었다. 이 연재물에서는 jQuery를 깊숙하게 탐험하며, 개발자가 RIA를 빠르고 쉽게 만들기 위한 튼튼한 토대를 제공한다.

직전 기사에서 RIA를 만드는 세 가지 기본 구성 요소와 페이지에 상호 작용을 추가하는 방법을 배웠다. 첫 번째로 살펴본 Event 모듈은 페이지에서 사용자가 일으킨 사건을 잡아서 프로그램 상에서 반응하도록 만들었다. 이런 기능을 사용해 버튼 누르기, 마우스 이동과 같은 사용자 행동 처리용 코드를 붙인다. 다음으로 살펴본 Attributes 모듈은 페이지 엘리먼트에서 값을 얻고 엘리먼트에 값을 설정하는 방법과 변수값을 포함한 자료 객체로 취급하는 방법을 설명했다. 이런 변수값은 사용자에게 어떤 반응을 보일지 결정하는 과정에 필요한 정보 대다수를 포함한다. 마지막으로 CSS 조작 방법을 살펴보고 페이지를 다시 읽어들이지 않고서도 배치, 색상, 글꼴 등을 변경하는 방법을 익혔다. 이런 세 가지 모듈에 익숙해지면, 상호대화식 웹 페이지를 구성하는 세 가지 기초 구성 요소를 익힌 셈이다. 사용자 반응을 잡아(Event), 정보를 획득하고(Attributes), 사건과 정보를 조합한 내용을 토대로 피드백을 제공한다(CSS).

이 기사에서 동적인 웹 페이지를 구성하는 세 가지 기본 요소를 사용한다. 이런 요소는 오늘날 볼 수 있는 좀 더 첨단 웹 응용의 일부로 자리잡은 "화끈한" 효과와 기능을 제공한다. 추가 모듈이 RIA에 핵심은 아니지만, 사용자가 기억할 만한 추가 기능을 제공하며 RIA에서 사용 가능한 범위와 기능을 엄청나게 넓혀준다. 살펴볼 첫 모듈은 Effects 모듈로 엘리먼트 감추기, 엘리먼트 이동, 페이드 인/아웃과 같은 기능을 포함한다. 다시 말해 웹 페이지를 화끈하게 만드는 기능이다. 이 기사에서 설명하는 마지막 모듈은 비동기식 자바스크립트 + XML(Ajax) 모듈이다. Ajax는 RIA 하면 가장 먼저 떠오르는 단어다. Ajax는 웹 응용에 서버와 통신하는 능력을 부여해 페이지를 다시 읽어들이지 않고서도 정보를 전달하고 인출하는 기능을 제공한다(웹에 떠도는 잘못된 의견과는 달리 AJax는 단순히 멋진 자바스크립트 애니메이션 기능은 아니다). jQuery가 믿기 어려울 정도로 손쉬운 AJax 도구를 제공하며, 실제로 Ajax 사용을 자바스크립트 메서드 호출 수준으로 단순하게 만들어준다.

이 기사에서 소개하는 예제 응용은 Effects와 Ajax 모듈을 데모 웹 응용인 웹 메일로 집어넣는 방법을 보여주면서 끝을 맺는다. 몇 가지 Effects를 데모에 추가해 활력을 불어넣고, 더욱 중요하게 몇 가지 Ajax 코드를 추가해 웹 메일이 페이지를 다시 읽지 않고서도 메시지를 출력하도록 만든다.

Effects

Effects 모듈은 이름처럼 "심각한" 웹 페이지가 회피해야 하는 애니메이션과 특수 효과만 포함한다고 지레짐작하기 쉽다. 하지만 이런 기능으로 끝나지 않는다. 거의 모든 응용에서 특정 페이지 엘리먼트를 가리거나 다른 페이지 엘리먼트 상태에 맞춰 끄고 켤 필요가 있다. 이런 변화 유형이 RIA에 중요한 이유는 페이지를 한 번만 읽으면서 모든 페이지 엘리먼트를 가져온 다음에 특정 엘리먼트를 표시하고 가리는 방식으로 필요한 정보만 보여주기 때문이다. 페이지를 다시 읽는 대안은 좋은 해법이 아니다. div를 감추고 보여주는 두 가지 선택이 가능한 콤보 박스를 생각해보자. 명백히 콤보 박스가 바뀔 때마다 div를 감추고 보여주려고 페이지를 다시 읽어들이는 것보다 클라이언트 쪽 코드에서 단순히 div를 감추고 보여주는 방식이 훨씬 더 쉽고 효율적이다. 단순히 감추고 보여주느냐 페이드 인/아웃 효과를 주느냐는 설계자 마음이다.

위에서 언급한 바와 같이 가장 기초적인 효과는 show()hide() 함수다. 두 함수는 아주 직관적이며, 척 보면 알겠지만 페이지에 있는 특정 엘리먼트를 보여주고 감춘다.


Listing 1. show()와 hide() 함수
				
// 페이지에 나오는 모든 <p>를 보여준다.
$("p").show();

// 페이지에 나오는 모든 <p>를 감춘다.
$("p").hide();

// 페이지에 나오는 모든 <p:odd>를 감춘다.
$("p:odd").hide();

이런 기본적인 기능 이외에, show()hide() 함수는 보여주고 감추는 동작 방식을 좀 더 세부적으로 제어하는 기능도 제공한다. 문서에 따르면 "우아한" 보여주기/감추기 기능은 show()를 페이드 인과 슬라이딩 아웃 조합으로 해석한다.

몇 가지 예제를 살펴보기 앞서, 잠시 한 걸음 물러서서 Effects 함수에 인수를 전달하는 방법을 살펴보자. (일반적인 show()hide() 함수는 예외지만) 함수마다 효과를 완료하고 나서 부르는 함수와 얼마나 빠르거나 느리게 효과를 보여줄지 제어하는 속력을 전달할 수 있다. 속력 인수로 "slow", "fast", "normal"이라는 문자열 중 하나를 지정한다. 추가로 애니메이션 주기를 정확하게 제어할 필요가 있다면 인수로 밀리 초 단위의 숫자를 넘긴다. Effects 함수로 넘기는 두 번째 인수는 함수이며, 효과를 끝내고 나서 호출되는 함수다. 이렇게 하는 이유는 여러 효과를 좀 더 큰 효과 하나로 결합할 때 특정 효과가 끝나고 나서 다음 효과를 지시하는 안정적인 제어 방법을 제공하기 때문이다.


Listing 2. 복잡한 효과
				
// "picture"라는 ID를 지정한 img는 감춰진 상태로 시작한다.
// "showPicture" 버튼이 눌러졌을 때 "picture"라는 ID를 지정한 img를 보여주고
// 애니메이션을 한다. 따라서 잽싸게 페이드인과 슬라이드 아웃을 보여준 다음에
// 쇼가 끝나면 그림에 달린 캡션을 보여준다.
// 캡션은 항상 <img> 태그 오른쪽으로 펼쳐진다.

<input type="button" id="showPicture">

<img src="/pic.jpg" id="picture"><span>This is the picture's caption</span>

// document.ready() 함수 내부에 들어갈 jQuery 코드

$("#picture").hide().next().hide();
$("#showPicture").click(function(){
   $("#picture").show("fast", function(){
       $("#picture").next().show();
   });
});

// 실제 프로그램 코드보다 설명이 더 길어졌음에 주목하자!

Effects 모듈은 show()hide()와 아주 비슷해서 궁극적으로 똑같은 작업을 수행하는 다른 함수를 지원한다. 여기서는 아주 구체적인 동작을 수행하게 만드는 함수 군을 소개하겠다. slideDown()slideUp() 함수는 페이지 엘리먼트를 보여주고 감추는 함수다. 하지만 슬라이딩 다운/업으로 엘리먼트에 애니메이션 효과를 준다(작명에 아주 머리가 파았을 테다!). 조금 전에 설명한 개선된 hide()show() 함수처럼, 슬라이드 속력과 작업이 끝나면 호출될 함수를 제어할 수 있다. 한걸음 더 나가서 여기에는 페이지 엘리먼트를 보여주고/감추기 위한 다른 옵션도 있다. fadeIn()fadeOut() 함수는 이름이 의미하듯이 페이지 엘리먼트를 투명해질 때까지 페이드 효과를 줘서 최종적으로 사라지게 만든다. 이 옵션에도 속력과 작업이 끝나면 호출될 함수를 지정할 수 있다.

페이지 엘리먼트를 완전히 감추거나 보여주지 않는 흥미로운 함수가 하나 더 있다. fadeTo()라는 함수는 페이지 엘리먼트를 일부 투명하게 만든다. RIA에서 이런 기능이 아주 중요한 이유는 투명도는 특정 엘리먼트를 페이지에서 강조하는 훌륭한 수단이며, 페이지에서 비활성 영역을 보여주는 데 사용할 수 있기 때문이다. 예를 들어, 페이지에 여러 탭이 있는 상황에서 다른 탭이 선택하지 못한다는 사실을 강조하려고 나머지 탭에 투명도를 적용할 수 있다. 아니면 페이지 폼에서, 현재 초점이 어떤 Form 엘리먼트에 맞춰져 있는지 사용자에게 알려주고 싶을 때도 초점이 없는 모든 엘리먼트에 투명도를 가하면 구분이 가능하다. 또한 투명도 자체 효과만 해도 정말 멋지다. 뭔가를 디자인할 때 "애플이 하면 진짜 멋지다"라는 일반적인 후광 효과를 따르면 된다.


Listing 3. 멋진 효과를 추가하기 위해 fadeTo() 활용하기
				
// 페이지에 있는 모든 form 엘리먼트에 60%라는 투명도를 준다.
// 현재 초점이 있는 엘리먼트는 투명도 효과에서 제외한다.
// 애플처럼 보이지 않는가?

$(":input").fadeTo("fast", .60);
$(":input").focus(function(){
    $(this).fadeTo("fast", 1);
});
$(":input").blur(function(){
    $(this).fadeTo("fast, .60);
    });

Effects 모듈에서 소개하고픈 마지막 함수는 가장 멋지지만 가장 실수도 저지르기 쉬운 함수다. 이는 전용 애니메이션 메서드로 애니메이션에 필요한 모든 매개변수를 지정하면 나머지는 jQuery가 알아서 처리한다. 매개변수 배열에 최종값으로 넘기면 jQuery는 배열에 정의된 값을 판단해 역시 매개변수로 넘긴 속력을 적용해서 마지막 값에 이를 때까지 페이지 엘리먼트를 부드럽게 움직여준다. Listing 4는 전용 애니메이션 메서드 예를 보여준다. 말하지 않아도 알겠지만 이 함수 응용 분야는 제한이 없으므로, 독자적인 전용 애니메이션이 필요하다고 느낄 때 유용하게 써먹기 바란다.


Listing 4. 전용 애니메이션 메서드
				
// 버튼을 클릭하면, "movingDiv"라는 ID가 붙은 div에 전용 애니메이션 효과를 적용한다.
$("#myButton").click(function(){
   $("#movingDiv").animate({
      // "movingDiv"에 속한 width, opacity, fontSize를 늘리며, 5초 동안 지속한다.
      width: 700;
      opacity: 0.5;
      fontSize: "18px";
   }, 5000);
   });

Ajax

최근에 "Ajax를 사용합니까?"라는 유행어가 모든 웹 페이지에 등장하고 있지만, 모든 사람이 Ajax가 진짜로 무엇을 의미하는지 아는 건 아니다. "Ajax"를 구글에서 검색해 보면 (다른 검색 결과와 마찬가지로) 수백만 건에 이르는 결과가 나타나지만 Ajax 용어가 품고 있는 사상이 무엇인지를 혼동하고 있다는 증거처럼 보인다. Ajax는 몇몇 페이지에서 보여주는 진짜 멋진 애니메이션도 아니며 진짜 멋진 그림자가 아래에 깔린 팝업 창도 아니다. 단지 Ajax가 멋지기 때문에 웹 페이지에서 보여주는 모든 흥미로운 효과를 Ajax라고 부르지는 않는다. Ajax의 핵심은 간단하게 말해 클라이언트 쪽 웹 페이지가 페이지를 다시 읽어들일 필요 없이 서버와 정보를 주고받는 수단일 따름이다. Ajax가 페이지에서 화끈한 효과를 주지는 못하지만, 웹 응용이 데스크톱 응용을 흉내내기 위한 수단을 제공한다. 따라서 Ajax를 둘러싼 소문은 근거가 있다. Ajax를 광범위하게 사용하는 관례는 오늘날 볼 수 있는 RIA 부문의 급격한 성장을 견인하고 있다.

jQuery는 Ajax를 엄청나게 쉽게 만들어준다! 과장해 추켜세울 의도는 없다. 자바스크립트 라이브러리의 도움 없이 Ajax로 작업한다면 XMLHttpRequests를 사용해야 하는데, 마이크로소프트(Microsoft®)와 파이어폭스가 사용하는 XMLHttpRequests 사이에 벌어진 차이점을 인지하고 반환 코드를 파싱하고 그 밖에 온갖 작업을 몸소 진행해야 한다. jQuery는 Ajax를 함수 호출 한방에 끝내버린다. 농담이 아니다. 과거 100행에 이르는 코드는 현재 서너 줄이면 끝난다. 믿기 어려운 시간 절약이 아닌가? 개인적으로 jQuery를 알기 전에는 여기저기 Ajax 함수를 추가하는 데 상당한 작업이 필요한 듯이 보였다. jQuery를 사용하면 Ajax가 너무나도 단순한 작업으로 변하기에 Ajax가 제공하는 모든 기능을 십분 활용하도록 응용 프로그램을 수정해왔다. 일반 함수 호출처럼 단순하다면 사용하지 못할 이유가 무엇이랴?

독자적인 Ajax 코드를 만드는 데 가장 널리 사용하는 함수인 post()get() 메서드에 초점을 맞추자. 두 함수는 현재 이 기사를 읽고 있는 시점에서 일반적인 jQuery 함수와 상당히 비슷하게 동작한다. URL과 넘길 매개변수를 명세하고 Ajax 메서드를 종료할 때 수행하는 함수를 명세하면 된다. 두 함수를 설정하는 방식 때문에 jQuery에서 다른 함수 호출과 정확하게 일치하는 방식으로 Ajax 메서드를 호출할 수 있게 되었다. Listing 5를 살펴보자.


Listing 5. Ajax post()와 get() 메서드
				
// 이 코드는 myTest.php라는 php 파일에 들어간다.
// Ajax 예제를 설명하다가 PHP를 다룬 이유가 무엇일까?
// 자바/JSP를 설명하자면 지면이 부족하다.
// 서블릿 코드도 보여줘야 하기 때문이다. 하지만 PHP를 사용하면 이런 번거로움이 없다.
// 물론 두 함수는 PHP와 자바/JSP에서 제대로 동작한다.
<?php
     echo "This is my return String";
?>

// jQuery에서 Ajax를 호출하는 방법이 얼마나 간단한지를 보여준다.
// post 함수
$.post("myTest.php", {}, function(data){
   $("p").text(data);
});

// get 함수
$.get("myTest.php", {}, function(data){
   $("p").text(data);
   });

두 예제를 보면 알겠지만, 해당 함수는 다른 jQuery 함수와 거의 흡사하며, 자바스크립트 라이브러리 없이 Ajax 프로그램을 작성하는 경우와 비교해 훨씬 더 사용하기 쉽다. Ajax 호출 함수를 확장하기 위해 사용 가능한 몇 가지 인수가 있다. 첫 번째 인수는 두말할 필요없이 호출할 URL이 되어야 한다. PHP 파일, JSP 파일, 서블릿이 될 수 있으며, 실제로 요청을 처리할 수만 있다면 뭐든 가능하다. (나중에 예제 응용을 보면 알겠지만) 요청에 반드시 반응할 필요도 없다. 두 번째 인수는 옵션으로 post/get으로 넘길 자료를 담는다. 이 인수는 배열 형태다. 일반적으로 페이지에서 사용자 ID 등 Form 엘리먼트에 들어있는 정보를 넘길 때 사용한다. 서버 쪽 파일에서 요청을 처리하는 데 필요한 모든 내용을 담고 있다. 세 번째 인수는 역시 옵션이며 Ajax 함수가 성공적으로 끝나고 나서 호출할 함수다. 이 함수는 일반적으로 서버에서 전달하는 정보 결과를 처리하는 코드를 포함한다. Listing 6은 네 번째 인수 설명에 앞서 첫 세 인수를 활용하는 예제를 보여준다.


Listing 6. 추가 인수를 받아들이는 post 메서드
				
// username과 password 입력 필드를 페이지에 추가한다.
<input type=text id="username">
<input type=password id="pass">

// 서버 기반 PHP 파일을 호출한다. 서버쪽으로 전달한 정보를 이 파일 내부에서 처리한다.
$.post("myFormProcessor.php", {username: $("#username").val(), 
                               password: $("#pass").val()});

// 거꾸로, 이 PHP 파일은 받은 결과를 처리할 함수에게 정보를 반환할 수 있다.
$.post("myFormProcessor.php", {username: $("#username").val(), 
                               password: $("#pass").val()},
       function(data){
           // data 변수는 서버에서 반환된 텍스트를 포함한다.
           // 미리 설정할 내용은 없으며, jQuery가 알아서 대신 처리해준다.
           if (data != "ERROR")
              $("#responseDiv").text(data);
       }
       );

지금까지 jQuery로 Ajax를 다루는 방법은 아주 직관적이고 쉽다는 사실을 확인했다. 하지만 단순히 텍스트 문자열이 아니라 서버에서 좀 더 복잡한 정보를 다루기 시작하면 일이 꼬이기 시작한다. 더 많은 Ajax 호출이 걸려있는 좀 더 복잡한 웹 페이지에서 반환 자료는 XML 형태도 가능하다. 반환 자료는 또한 JSON 객체 형태가 될 수도 있다(JSON은 기본적으로 자바스크립트 코드에서 사용 가능한 객체를 정의하는 프로토콜이다). jQuery는 네 번째 옵션 인수로 서버에서 기대하는 반환 값 유형을 미리 정의하는 get/post 메서드에 넘기도록 허용한다. XML 문자열을 위해 "xml"이라는 문자열을 넘기고, HTML 문자열(또는 평문)을 위해 "html"이라는 문자열을 넘기고, 자바스크립트 코드를 위해 "script"라는 문자열을 넘기고, JSON 객체를 위해 "json"이라는 문자열을 넘긴다. 따라서 예를 들어, 반환 객체를 "json" 유형으로 지정하면 jQuery는 자동으로 서버에서 오는 반응 문자열을 JSON 객체로 바꿔 즉시 참조가 가능하게 만든다.


Listing 7. Ajax에서 반환 유형 명세하기
				
// 반환 객체를 JSON 객체 유형으로 정의하고, 객체 형 변환이나 평가 과정을 거치지
// 않고서 내부 필드를 참조하도록 반환 객체를 JSON 객체로 처리한다.

$.post("myFormProcessor.php", {username: $("#username").val(), 
                               password: $("#pass").val()},
       function(data){
          // jQuery는 이미 결과 자료를 JSON 객체로 변환했기에, 
          // 즉시 내부 필드를 참조할 수 있다.
          // 좀 더 깔끔한 코드를 제공하며, 향후 변경에 대응이 가능하다.
          // XML 결과를 직접 처리하는 경우와 비교하면 작업이 훨씬 쉬워진다.
          $("#username").text(data.username);
          $("#address").text(data.address);
          $("#phone").text(data.phone);
       }, 
       "json"  // 여기서 반환 유형이 JSON이라고 명세한다.
       ); 

설명에 시간을 들일 만한 또 다른 Ajax 함수는 load()이며, 사용자가 특정 페이지를 읽어서 결과로 HTML을 얻도록 만들어준다. 설명만 보면 그다지 흥미를 못 느낄지도 모르겠다. 하지만 시작 시점에서 웹 페이지를 파싱하듯이 jQuery 코드를 사용해 반환된 정보를 파싱하는 능력이 생긴다. 이게 무슨 이야기일까? 웹 페이지를 읽은 다음에 jQuery로 파싱이 가능한 능력을 토대로 아주 효율적이고 프로그램 작성이 쉬운 웹 로봇을 직접 만들 수 있다. 특정 페이지에서 어떤 정보 유형도 수집할 수 있다. 예제를 한번 살펴보자.


Listing 8. load() 함수 예
				
// 야후 주식 시세를 호출하는 방법으로 아주 기본적인 주식 시세 시스템을 구축한 다음에
// 야후 주식 시세 페이지에서 정보를 긁어온다.
// 여기서는 IBM 주식 가격을 찾아 "stockPrice"로 ID를 설정한 텍스트 필드에서 보여준다.
// 주식 가격을 포함한 ID는 "yfs_190_ibm"이다.
$("#stockPrice").load("http://finance.yahoo.com/q?s=ibm #yfs_l90_ibm").text();

Ajax 모듈에서 소개할 마지막 두 함수는 Ajax 작업을 훌륭하게 보조해 주는 진짜 유틸리티 함수다. 이미 여러 차례 지적한 바와 같이 클라이언트와 서버 사이에서 일어나는 상호 작용 대다수는 폼과 폼이 포함하는 엘리먼트를 둘러싸고 일어난다. 이런 통신 유형이 아주 일반적이므로 jQuery에는 두 가지 유틸리티 함수가 있어서 HTTP 질의 문자열이거나 JSON 문자열 형태로 서버 쪽에 전달할 매개변수 생성을 도와준다. Ajax가 요구하는 조건에 맞춰 지원하는 유틸리티 함수를 골라 활용한다. 활용법이 아주 간단한 이유는 전체 폼을 캡슐화하므로 개발 도중에 자유롭게 엘리먼트를 추가, 삭제, 변경할 수 있기 때문이다. Listing 9는 이런 예제를 보여준다.


Listing 9. serialize()serializeArray() 함수
				
// serialize() 함수는 지정 엘리먼트에 들어있는 모든 폼 엘리먼트를 살핀 다음에
// 자동으로 엘리먼트의 모든 정보를 포함하는 <element name>=<element value>&
// 형태로 HTTP 문자열을 만든다.
// 예는 "firstname=Michael&lastname=Abernethy"와 같다.
// 이렇게 만든 문자열을 Ajax 호출로 정보를 전달할 URL 뒤에 덧붙인다.
$.post("myFormProcessor.php?" + $("#myForm").serialize());

// 또한 serializeArray() 함수로 비슷한 작업을 수행할 수도 있다.
// 폼을 JSON 형태로 변환한다.
$.post("myFormProcessor.php", {json: $("#myForm").serializeArray()});

여기서 배운 모든 내용을 하나로 합치기

모든 내용을 하나로 합쳐서 만든 데모 웹 응용인 웹 메일을 마지막으로 살펴보자. 이미 지난 연재물에서 충분히 익숙하게 살펴보았을 것이다. 정보 획득을 위해 클라이언트 쪽에서 서버 쪽으로 여러 Ajax 호출을 수행한다. 여기서는 메시지를 읽고 메시지를 지울 때 AJax를 활용한다. 그러고 나서 Effects를 활용해 사용자가 메시지를 지울 때 즉시 화면에서 메시지를 사라지게 만든다. 심지어 사용자가 페이지를 다시 읽지 않으며 Ajax 호출을 활용해 비동기식으로 실제 삭제가 일어나지만 이런 삭제 동작이 즉시 일어난다. 직접 만든 웹 응용에서 Ajax 호출이 얼마나 쉬운지를 살펴보고 데스크톱 응용을 진짜로 흉내내기 위해 Ajax를 활용하는 방법을 살펴보고, Effects를 활용해 응용 프로그램 사용성을 높이는 방법을 예제를 보면서 최종적으로 확인한다.


Listing 10. 예제 웹 응용: 메시지 삭제하기
				
// 먼저 메시지 삭제를 처리하는 방법을 살펴보자.

// 첫 단계는 실제로 메시지를 지울 버튼 생성이다.
<input type=button id="delete" value="Delete">

// 다음으로 테이블 각 행에 체크박스를 추가해 사용자가 삭제를 원하는 메시지를
// 선택하도록 만든다. 이런 체크박스를 나중에 활용할 텐데, 여기에 들어있는 정보는
// 아주 중요하다(예시라고 부른다).
// 각 체크박스 값이 message.id라는 사실에 주목하자.

<tr class="messageRow" id="<%=message.id %>">
<input type=checkbox name="delId" value="<%=message.id%>" class=selectable>

// 이제 HTML이 완료되었으므로 삭제를 수행하는 jQuery 코드를 살펴보자.

// 먼저, 삭제 버튼에 이벤트를 추가한다. 버튼을 누르면 체크된 메시지를 지우기 시작한다.

$("#delete").click(function() {
   deleteMessages();
});

// 마지막으로 deleteMessage() 함수를 정의하자. 오늘 배운 내용에서 가장
// 중요한 내용을 담고 있다.
// 모든 기사에서 다룬 내용을 완성하는 함수이므로, 동작 원리를 자세히 설명하겠다.
// 참고 1 - 아주 구체적인 검색 매개변수를 넘겨 체크된 체크박스를 하나씩
// 순회하며 "selectable" 클래스 멤버만 찾도록 만든다.
// 참고 2 - 체크박스 값이 포함된 테이블 행 ID와 동일하므로, Effects 모듈을 사용해
// 전체 테이블 행을 감출 수 있다. 체크박스 값을 전달하고 표 행을 다시 얻은 다음에 감춘다.
// 참고 3 - Ajax를 호출해 실제로 DB에서 메시지를 삭제한다. messageID를 서버에 전달해
// 삭제될 항목을 알도록 만든다. 체크박스 값에 포함된 정보를 Ajax 호출 과정에서 전달한다.
// 성공인지 아닌지 신경쓰지 않기 때문에 서버에서 돌아오는 대답을 무시한다.

function deleteMessages()
{
    $(".selectable:checked").each(function() {
        $("#"+$(this).val()).remove();
        $.post("<%=HtmlServlet.DELETE_MESSAGES%>.do", {delId: $(this).val()});
    });
    }

두 번째 예제로, 메시지를 읽는 방법을 살펴보자. jQuery에서 Ajax를 활용하는 예를 보여준다.


Listing 11. 예제 웹 응용: 메시지 읽기
				

// 지금까지 예제에서 코드 대부분을 살펴보았으므로, 코드에서 Ajax 부분만 초점을 맞춘다.
// 참고 1 - Ajax 호출을 하면서 인수 네 개를 정의해 넘긴다.
// 메시지를 읽으려면 서버에 두 변수를 넘겨야 한다.
// 첫 번째는 메시지 ID로 읽기를 원하는 메시지가 무엇인지 알아야 하기 때문이다.
// 두 번째는 현재 뷰로 .. 어떤 목적으로 사용했는지 기억나지 않는다.
// (그다지 중요하지 않는 듯이 보인다)
// 참고 2 - Ajax 함수로 넘기는 네 번째 인수는 "json"이다.
// Ajax 호출로 JSON 객체를 반환하라는 표식이다. jQuery는 결과로 반환되는
// 문자열을 JSON 객체로 자동으로 변환한다.
// 참고 3 - eval() 함수를 사용하지 않고 JSON 객체를 직접 다루고 있다는 점에 주목하자.
// jQuery가 객체를 만들었기 때문이다. 따라서 필드를 직접 참조할 수 있다.
$(".messageRow").dblclick(function() {
    if ($(this).hasClass("mail_unread"))
    {
        $(this).removeClass("mail_unread");
    }
    $.post("<%=HtmlServlet.READ_MESSAGE%>.do", {messageId: $(this).attr("id"),
                                                     view: "<%=view %>"}, 
      function(data){
        if (data != "ERROR")
        {
             // JSON 객체를 활용한다.
             $("#subject").val(data.subject);
             $("#message").val(data.message);
             $("#from").val(data.from);
         }
      }, "json");
    $.blockUI(readMess, {width:'540px', height:'300px'});
    });

결론

jQuery와 같은 자바스크립트 라이브러리는 데스크톱에서 브라우저로 응용 프로그램을 이식함에 따라 점점 더 중요해진다. 이런 응용은 점점 더 복잡해지므로, 웹 응용 프로젝트에서 jQuery와 같은 튼튼한 교차 브라우저 해법을 필수로 요구한다. jQuery는 다른 자바스크립트 라이브러리와 격차를 벌이기 시작했으며, 필요한 모든 작업을 수행하는 능력과 함께 손쉬운 개발 특성 때문에 많은 개발자가 jQuery를 핵심 라이브러리로 선택하고 있다.

연재물 세 번째 기사에서, 응용에 풍부함을 더해 데스크톱 응용과 웹 응용 사이에 경계를 허무는 두 가지 모듈을 익혔다. 이번 기사에서 가장 강력하게 추가한 내용은 Ajax 모듈로, 다른 jQuery 메서드 호출처럼 간단하고 직관적인 인터페이스를 제공함으로써 Ajax를 아주 쉽게 활용하도록 만든다. 페이지를 다시 읽느라 지연되는 짜증을 겪지 않고서 응용 프로그램 반응 속력을 높이는 훌륭한 도구로 몇 가지 예제를 곁들여 Ajax의 위력도 살펴보았다. Effects 패키지에 대한 내용도 빠지지 않았다. 애니메이션과 페이지 엘리먼트 감추기/보여주기 기능을 적절하게 사용한다면 좋은 UI 디자인이라는 강력한 지원군을 얻게 된다. Ajax와 Effect를 결합해 효율적으로 활용하면 웹 사이트에 동적인 능력을 상당히 강화할 수 있다.

마지막으로 웹 응용 예제를 다시 한번 살펴보았고, AJax 모듈을 추가해 페이지를 다시 읽어들이지 않고도 메시지를 읽고 삭제하는 방법을 익혔다. 그러고 나서 Ajax와 Effect 조합으로 페이지를 다시 읽어들이지 않고도 사용자 페이지와 DB 웹 응용에서 메시지를 삭제하는 방법을 익혔다. 사용자에게 메시지 삭제는 투명한 과정이며, 미리 정해진 방식에 맞춰 프로그램 상에서 동작한다.

이 기사는 모든 jQuery 배포판에 따라오는 핵심 라이브러리에 대한 소개 내용으로 마무리를 한다. 연재물에서 jQuery에 포함된 모든 모듈을 살펴보았으며, jQuery로 작업하는 과정이 쉽고 직관적이라는 사실을 보여줬다. 또한 어떤 웹 응용을 만들거나 jQuery는 RIA 유형에 무관하게 제 자리를 잡고 있다는 사실을 확인했다. 자바스크립트가 요구하는 수준에 맞춰 튼튼한 토대를 제공하기 때문이다. 연재물은 직접 코드를 작성하는 과정에서 jQuery를 아주 자연스럽게 활용하는 수준에 이르도록 독자들을 이끌었다. 첫 번째 기사는 jQuery 동작 방식, 페이지 엘리먼트 탐색을 위한 활용 방법, 엘리먼트를 순회하는 방법, Array 객체와 같은 방식으로 접근하는 방법을 설명했고, 두 번째 기사는 풍부함을 제공하는 토대로 세 가지 모듈을 소개했다. 마지막으로 세 번째 기사는 완벽하고 복잡한 웹 응용을 만들기 위한 프레임워크를 위한 마지막 퍼즐 조각을 보여줬다.





위로


다운로드 하십시오

설명 이름 크기 다운로드 방식
예제 애플리케이션을 담은 Zip 파일 jquery.zip 69KB HTTP
다운로드 방식에 대한 정보
Posted by 1010
반응형

도메인이 다른 경우

도메인 a1
도메인 a2

a1에서 a2를 호출해서 popup을 띄운다.

a2 버튼 클릭 후 a1을 reload 하고 a2를 close 시키려면 문제가 생긴다.

window.opener.location.reload(); 호출 시 도메인이 달라서 opener를 못찾기 때문이다.

<script>document.domain="도메인 명";</script>

==> cross domain 이라고 검색하면 나옴..

http://coolengineer.com/entry/avoid-cross-domain-1

Posted by 1010
반응형

전체 쿠키 정보를 Text 로 출력한다 . 모든 쿠키에 대한 정보를 알아볼려면  document.cookie 를 호출하면 된다. 집어 넣는 곳은 cookieOut 이라는 DIV 내에 Text 를 출력하는  로직이다.
// 모든 쿠키출력
function viewCookie()
{
   if( document.cookie.length > 0 )
      cookieOut.innerText = document.cookie;
   else
      cookieOut.innerText = "저장된 쿠키가 없습니다.";
}
// 출력화면
<DIV id = "cookieOut"></DIV>


저장된 쿠키값을 쿠키명으로 검색해서 넘겨주는 함수이다.
// param : 쿠키명
// return : 쿠키값
function getCookie( cookieName )
{
   var search = cookieName + "=";
   var cookie = document.cookie;

   // 현재 쿠키가 존재할 경우
   if( cookie.length > 0 )
   {
       startIndex = cookie.indexOf( cookieName );// 해당 쿠키명이 존재하는지 검색후 위치정보를 리턴.

       if( startIndex != -1 ) // 존재한다
      {
         startIndex += cookieName.length;// 값을 얻어내기 위해 시작 인덱스 조절
         endIndex = cookie.indexOf( ";", startIndex );// 값을 얻어내기 위해 종료 인덱스 추출
         if( endIndex == -1) endIndex = cookie.length; // 만약 종료 인덱스 못찾으면 쿠키 전체길이로 설정

         return unescape( cookie.substring( startIndex + 1, endIndex ) );// 쿠키값을 추출하여 리턴
      } else {
         return false; // 존재하지 않을때
      }
   } else {
      return false; // 쿠키 아예없을때
   }
}

쿠키값을 설정한다. 파라미터로는 쿠키명, 쿠키값, 쿠키날짜를 넘긴다
function setCookie( cookieName, cookieValue, expireDate )
{
   var today = new Date();
   today.setDate( today.getDate() + parseInt( expireDate ) );
   document.cookie = cookieName + "=" + escape( cookieValue ) + "; path=/; expires=" +                
           today.toGMTString() + ";"
}


쿠키명을 넘겨 해당하는 쿠키를 삭제한다
function deleteCookie( cookieName )
{
   var expireDate = new Date();
 
   //어제 날짜를 쿠키 소멸 날짜로 설정한다.
   expireDate.setDate( expireDate.getDate() - 1 );
   document.cookie = cookieName + "= " + "; expires=" + expireDate.toGMTString() + "; path=/";
}

Posted by 1010