'분류 전체보기'에 해당되는 글 2491건

  1. 2010.11.25 maven
  2. 2010.11.25 (자카르타_스트럿츠완전해부)Section_1.pdf
  3. 2010.11.25 CookieUtil.js
  4. 2010.11.25 nice.nuguya.oivs.crypto.js
  5. 2010.11.25 웹표준 기본부터 시작하기
  6. 2010.11.22 How to use entities for special characters
  7. 2010.11.22 Images as submit buttons
  8. 2010.11.22 웹접근성을 고려한 Form URIs
  9. 2010.11.22 웹접근성을 고려한 javascript: URIs 사용예
  10. 2010.11.22 innerHTML 을 쓰지 말고 createElement 로 사용해라.
  11. 2010.11.22 form 안에 input 태그 타입이 image 일경우 폼을 서브밋함.
  12. 2010.11.22 [펌] 접근성을 해치지 않는 자바스크립트의 사용
  13. 2010.11.22 [펌] UI 개발자를 위한 북마크
  14. 2010.11.22 [펌] 웹표준 가이드라인 모음
  15. 2010.11.19 http://www.android-themes.com/Android_Games/
  16. 2010.11.15 [펌] 레지스트리로 USB 읽기 쓰기 제어하기
  17. 2010.11.12 [펌] 나는 이렇게 앱을 만들었다
  18. 2010.11.12 ManicTime v1.4.7 (10/19/2010)
  19. 2010.11.02 telnet http 소스 확인하기
  20. 2010.10.29 ajax & spring MVC 게시판 소스
  21. 2010.10.29 eclipse plugin 설치 방법 - Properties Edit Plugin
  22. 2010.10.29 80 AJAX solutions that are excellent and usefull
  23. 2010.10.29 jquery TableSort.zip
  24. 2010.10.29 day-2(dwr기술자료).doc
  25. 2010.10.29 oracle_sql강좌.pdf
  26. 2010.10.26 길이체크 정규식 (아이디 비번 길이 확인)
  27. 2010.10.25 java String StringBuffer 성능 비교
  28. 2010.10.22 it 개발자(?) 위한 개발툴 모음
  29. 2010.10.19 Restlet - General FAQ
  30. 2010.10.19 java 초경량 프레임워크 Play framework 5
52.Apache Project &.../Maven2010. 11. 25. 16:26
반응형


maven의 의미#

maven은 유대어로 '지식 축적기'라고 하는데, Jakarta Turbine 프로젝트를 간소화 하기 위해서 시작했었다. 각각의 프로젝트에는 여러개의 ant빌드 파일이 있는데, 각각 약간씩 다르고, JAR파일도 약간 다른 파일을이 CVS에 체크인되어 있어서.... 표준 프로젝트 개발 툴로 만들려고 어쩌고 저쩌고...

http://maven.apache.org/what-is-maven.html

ant와 비교하여 maven의 장점#

정형화된 절차를 제공한다.#

ant는 모든 과정을 사용자가 코딩해야 하지만, maven은 compile, package, test 등등 작업 프로세스를 정형화 시키고 이를 준수하도록 강제한다.

프로젝트의 소스 트리 구성도 src/main/... 과 같은 패턴을 따르도록 제시하고 있다.

라이브러리 의존성 해결을 자동화한다.#

open source 라이브러리의 경우 maven의 central repository에 모두 저장하고 있어서, 의존성이 있는 라이브러리의 명세만 입력해주면, 자동으로 다운로드 하여 class path에 걸어주기 때문에, 따로 처리할 필요가 없다.

라이브러리 관리의 편의성을 증대시켜준다.#

보통 소스 개발할때, 라이브러리를 SCM(Software Configuration Management)툴에서 관리하는데, 이는 불필요한 공간을 낭비하게 할 뿐 아니라, 버전별 관리도 어렵게한다.

maven에서는 라이브러리 전용 레파지토리를 제공하므로, 통합 관리가 가능하다.


maven 이용 전략#

  1. 프로젝트 빌드 및 디버깅은 eclipse를 최대한 활용한다.
  2. 라이브러리 의존성 관련 처리는 maven을 이용한다.

maven 설치#

  1. http://maven.apache.org/download.html 에서 apache-maven-2.1.0-bin.zip 을 다운로드 한다. (*nix계열이라면 tar.gz이나 tar.bz2가 좋다 )
  2. apache-maven-2.0.10-bin.zip을 설치를 원하는 디렉토리에 압축을 푼다. (eg. c:\Work\lib\apache-maven-2.1.0\)
  3. M2_HOME 환경변수를 '시스템 등록정보'창을 열어서(Window Key + Pause), c:\Work\lib\apache-maven-2.1.0 과 같이 추가해준다. 중간에 공백이 있더라도 따옴표를 넣지 않도록 한다. 또한 Maven < 2.0.9 에서는  맨 마지막에 \를 넣지 말것
  4. 3번의 다이얼로그에서 M2 환경변수를 %M2_HOME%\bin 으로 추가한다.
  5. 선택사항 :  3번 다이얼로그에서 MAVEN_OPTS 라는 변수로 -Xms256m -Xmx512m 같은 환경변수를 추가할 수 있다.

 m2eclipse 설치 ( eclipse plugin )#

  1. http://m2eclipse.codehaus.org/ 에가서  http://m2eclipse.sonatype.org/sites/m2e/  주소 확인후 eclipse 업데이트 주소에 입력후 플러그인 설치
  2. http://download.eclipse.org/releases/ganymede/ 가 plugin update경로에 없을 경우 의존성을 해결해주지 못하는 문제가 발생할 수 있다.

m2eclipse 사용 가이드


m2eclipse 버그

scope를 provided로 잡았는데, war패키지에 전체 내용이 들어가는 경우

eclipse에서 패키징을 할때, scope를 compile로 잡으면 기본적으로 WEB-INF/lib에 라이브러리를 복사한다.

이 작업이 임시 영역에서 이루어지는데...

나중에 scope를 compile -> provided로 바꾸더라도, 그 임시영역의 lib 파일들은 그대로 존재하게 되어, 같이 패키징된다.

이는 현재 버그로 등록 되어 있다.  https://issues.sonatype.org/browse/MNGECLIPSE-2217

해결 방법은 임시영역에서 lib이하의 파일들을 지워주는 것


maven 사용하기#

ant에서는 build.xml 파일에서 프로젝트의 빌드,테스트,디플로이등을 기술한다면, maven에서는 pom.xml 파일을 이용한다.

pom.xml 에는 다음과 같은 정보를 저장하고 있다.

  • 프로젝트 정보 - 프로젝트의 이름, 개발자 등
  • 빌드 정보 - 플러그인 등 빌드와 관련된 설정을 기술
  • 의존성,연관성정보 - 의존 프로젝트(모듈), 상위 프로젝트, 포함하고 있는 하위 모듈 등을 기술

기본 프로젝트 형태#

maven에서 제시하고있는 best practice의 프로젝트 구성은 다음과 같다.

우리 회사 같은 경우에는 web application도 함께 개발하므로, src/main/webapp 라는 폴더가 추가될 것이다. 프로젝트 성격에 따라서 약간의 변동은 있겠지만,

기본적인 뼈대는 아래와 같다.

 아래의 root디렉토리에 보면 pom.xml 파일이 있는데, 이 파일을 통해서 maven은 동작한다.


  1. my-app
    |-- pom.xml
    `-- src
        |-- main
        |   `-- java
        |       `-- com
        |           `-- mycompany
        |               `-- app
        |                   `-- App.java
        `-- test
            `-- java
                `-- com
                    `-- mycompany
                        `-- app
                            `-- AppTest.java

POM 파일의 형태#

POM 설정시의 용어 설명#

  • procject : pom.xml의 최상위 레벨 엘리먼트임
  • modelVersion : POM이 어떤 버전의 오브젝트 모델을 사용할 것인지
  • groupId : 프로젝트를 생성하기 위해 이용되는 유일한 그룹 아이디. 보통 소속 회사나 기관의 url명으로 사용함. eg. org.apache.maven.plugins 는 모든 maven plugin을 위한 그룹 id임
  • artifactId : 이 프로젝트에서 생성할 유니크한 이름. 보통 이 이름의 jar파일로 패키징된다. <artifactId>-<version>.<extenstion>으로 패키징된다.
  • packaging : JAR,WAR,EAR등 어떤 형태로 패키징할 것인지 기본값은 JAR이다.
  • version: 버전
  • name :
  • url :
  • description :

scope의 의미#

  • compile : 기본영역으로 아무것도 지정되지 않은 경우 사용됨. compile 의존관계에 있는 것은 프로젝트의 모든 클래스에서 사용가능함. 또한, 이와 같은 의존관계는 의존관계에 있는 프로젝트에 포함됨.
  • provided : compile 과 매우 유사하지만, 실행시 의존관계를 제공하는 JDK나 컨테이너에 대해서 적용됨. 예를 들어, JEE에 대한 웹 어플리케이션을 만드는 경우, 웹 컨테이너가 서블릿 API와 Java EE API관련 클래스들을 제공하기 때문에 provided 영역으로 의존관계가 세팅되어야 함. 이 영역은 컴파일과 테스트의 클래스패스 용으로 사용되며, 자동영역임.
  • runtime : 의존관계가 컴파일시 필요하지 않지만, 실행시 필요함을 의미함. 실행시와 테스트 클래스패스에 속하지만, 컴파일 클래스패스에는 속하지 않음.
  • test : 일반적인 어플리케이션 사용에 대해서는 의존관계가 필요없고, 테스트 컴파일과 실행 시점에만 사용됨.
  • system : 명시적으로 해당 JAR를 포함하는 것이 제공되어야 한다는 것을 제외하고 provided와 유사함. artifact는 항상 사용가능하며 레파지토리에서 검색하지 않음.
  • import (Maven 2.0.9 이후에서만 적용) : 이 영역은 <dependencyManagement>에서 pom의 의존관계에 대해서 사용됨. 지정된 POM이 해당 POM의 <dependencyManagement> 영역에 있는 의존관계로 대체됨을 의미함. 이것들이 대체되기 때문에 import 영역의 의존관계들은 실질적으로 의존에 대한 제약에 대해 관여하지 않음.
  • 참고 : http://homo-ware.tistory.com/43

servlet 개발을 위한 pom.xml 샘플#

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>MavenTestProject</groupId>
      <artifactId>MavenTestProject</artifactId>
      <packaging>war</packaging>
      <version>0.0.1-SNAPSHOT</version>
      <build>
          <plugins>
              <plugin>
  2.               <!-- java 1.5 이상의 문법을 지원하기 위해서는 다음 설정이 필요하다. -->
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <configuration>
                      <source>1.5</source>
                      <target>1.5</target>
                  </configuration>
              </plugin>
          </plugins>
      </build>
      <dependencies>
          <dependency>
  3.           <!-- 서블릿 소스를 컴파일 하기 위해 필요하다. -->
              <groupId>javax.servlet</groupId>
              <artifactId>servlet-api</artifactId>
              <version>2.5</version>
              <scope>provided</scope>
          </dependency>
      </dependencies>
    </project>

EJB 개발을 위한 pom.xml 샘플#

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>TestEJBM2</groupId>
      <artifactId>TestEJBM2</artifactId>
      <packaging>ejb</packaging>
      <version>0.0.1-SNAPSHOT</version>
      <build>
          <plugins>
              <plugin>
  2.               <!-- ejb 3.0 지원과,
  3.                    배포용 클라이언트 제작( 기본적으로 **/*Bean.class, **/*CMP.class, **/*Session.class and **/package.html 파일을 제외하고 패키징함 )
  4.                    http://maven.apache.org/plugins/maven-ejb-plugin/howto.html 참고
  5.               -->
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-ejb-plugin</artifactId>
                  <configuration>
                      <ejbVersion>3.0</ejbVersion>
                      <generateClient>true</generateClient>
                  </configuration>
              </plugin>
              <plugin>
  6.               <!-- java 1.5문법 지원 -->
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <configuration>
                      <source>1.5</source>
                      <target>1.5</target>
                  </configuration>             
              </plugin>
          </plugins>
      </build>
      <dependencies>
          <dependency>
  7.           <!-- 컴파일시 필요한 ejb관련 라이브러리 -->
              <groupId>javax.ejb</groupId>
              <artifactId>ejb-api</artifactId>
              <version>3.0</version>
          </dependency>
          <dependency>
  8.           <!-- 컴파일시 필요한 jboss 관련 라이브러리(jboss runtime을 전부 포함하는 것은 아님 -->
              <groupId>jboss</groupId>
              <artifactId>jboss</artifactId>
              <version>4.2.3.GA</version>
              <scope>provided</scope>
          </dependency>
          <dependency>
              <groupId>jboss</groupId>
  9.           <!-- 컴파일시 필요한 jboss-annotation 관련 라이브러리-->
              <artifactId>jboss-annotations-ejb3</artifactId>
              <version>4.2.3.GA</version>
              <scope>provided</scope>
          </dependency>
          <dependency>
  10.           <!-- 컴파일시 필요한 jboss-ejb3 관련 라이브러리-->
              <groupId>jboss</groupId>
              <artifactId>jboss-ejb3</artifactId>
              <version>4.2.3.GA</version>
              <scope>provided</scope>
          </dependency>
      </dependencies>
    </project>


maven의 settings.xml 파일 설정#

이 파일은 Maven의 사용자별 설정을 저장한다. pom.xml에 저장되지 않는, 개발자정보, 로컬 세팅, 레파지토리 정보등이 저장된다.

기본적으로 settings.xml 의 위치는 ~/.m2/settings.이다.


maven  repository#

maven을 사용하여 외부 라이브러리를 추가할때, groupId나 artifactId를 미리 알 수없어서 난감할 수가 있다.

예를들어 groupId=jboss,artifactId=jboss,version=4.2.3.GA인데, 이 값을 미리 알기는 쉬운 일이 아니다.

이럴땐 maven repository 검색 사이트를 이용하자.

일부 라이브러리는 라이센스의 문제로, maven repository에 넣을수 없다고 한다. 이럴때는 InternalServer에 등록해놓고, 이용하면 된다.


eclipse 통합환경에서 maven 이용하기#

Dynamic Web Proejct 이용시#

  1. Dynamic Web Proejct 로 프로젝트를 만든다.
  2. m2eclipse 플러그인을 이용하여 Maven관리 프로젝트로 변환
  3. 생성한 프로젝트 폴더의 .settings/org.eclipse.wst.common.project.facet.core.xml 파일을 열어서, <faceted-project> 태그 밑에 '<installed facet="jst.web" version="2.5"/>' 를 추가해준다. (원래는 프로젝트의 Properites 다이얼로그에서 되어야 하는데, 이클립스 버그인지 잘 안된다. )
  4. 프로젝트의 WebContent 아래의 META-INF와 WEB-INF 파일을 src/main/webapp 밑으로 옮겨준다.

EJB Project 사용시#


eclipse와 maven 통합 가이드 동영상#

문서를 보면 이해하기 어려울 수 있는 내용을 동영상을 통해 따라할 수 있도록 제작하였다.

  • maven 설치


  • maven plugin for eclipse 설치


  • Dynamic Web Project 생성하고 maven형식으로 변환


  • elcipse 프로젝트 형태로 deploy하고 디버깅 하기


  • maven으로 컴파일하여 deploy하기


  • InternalServer에 접속하여 의존성 해결하기

기업내 프로젝트의 repository관리 전략#


내부 repository 없이 개발하는 경우#

Maven_clip_image002_0001.jpg

기업내 repository를 이용하여 개발하는 경우#

Maven_clip_image002_0002.jpg


예외사항 처리#

m2eclipse 설치중 의존성 문제로 실패하는 경우#

XMLBuddy라는 플러그인이 깔려있으면 충돌난다.#

  • XMLBuddy라는 플러그인을 삭제해주어야 함

m2eclipse사용하여 컴파일 시 에러#

  • eclipse의 Installed JRE에 JRE로 되어 있으면 에러가 발생한다 -> JDK로 바꿔줘야 함.

    • 헷갈리지 않게 시스템 내의 JRE는 모두 지우자.

 eclipse 실행시 JDK를 이용해서 eclipse를 실행하라는 에러가 뜨는 경우#

테스트 없이 패키징 하기

  • -Dmaven.test.skip=true  옵션 추가


레퍼런스#

maven 공식 문서#


jboss 서블릿 컴파일#

internal repository 세팅하기#


기타#


추가할 내용#

todo#

  • maven을 서버로 deploy 하는법


출처 : http://alexk.springnote.com/pages/3501753
출처 : http://alexk.springnote.com/pages/3501753

Posted by 1010
반응형
(자카르타_스트럿츠완전해부)Section_1.pdf
Posted by 1010
반응형

/**********************************************************************
 *
 *  cookie 공통 모듈
 *
 **********************************************************************/
/**
  * 쿠키정보 가져오기
  * @param name  쿠키명
  */
function getCookie(name) {
 var Found = false;
 var start, end;
 var i = 0;
 var cookieData = document.cookie;
 while(i <= cookieData.length) {
    start = i;
   end = start + name.length;
   
   if(cookieData.substring(start, end) == name) {
      Found = true;
      break;
    }
    i++;
 }
 if(Found == true) {
    start = end + 1;
    end = cookieData.indexOf(";", start);
    if(end < start)
      end = cookieData.length;
     return cookieData.substring(start, end);
   }
    
 return "";
}

/**
  * 쿠키 설정
  * @param cookieName 쿠키명
  * @param cookieValue 쿠키값
  * @param expireDay 쿠키 유효날짜
  */
function setCookie( cookieName, cookieValue){
   var today = new Date();
   today.setDate( today.getDate() + 365 );   // 저장 기간
   document.cookie = cookieName + "=" +  cookieValue  + "; path=/; expires=" + today.toGMTString() + ";";
}

/**
  * 쿠키 삭제
  * @param cookieName 삭제할 쿠키명
  */
function deleteCookie(cookieName ){
   var expireDate = new Date();
 
   //어제 날짜를 쿠키 소멸 날짜로 설정한다.
   expireDate.setDate( expireDate.getDate() - 1 );
   document.cookie = cookieName + "=" + "; expires=" + expireDate.toGMTString() + "; path=/";
 
}

/**********************************************************************
 *
 *  관심자료 cookie
 *
 **********************************************************************/

/**
  * 관심자료 목록 가져오기
  * return : list1[]
  */
function getCernDatList(){
 var list =  "";
 if (navigator.appName.charAt(0) == 'N') {
  list = fromUtf8(getCookie('cernDatList'));
 } else if (navigator.appName.charAt(0) == 'M') {
  list = getCookie('cernDatList');
 }
 if(list.length>0){
  list =  list.split("---");
 }else{
  list = "";
 }
 return list;
}


/**
  * 관심자료 등록 
  */
function setCernDatList(url,title){
 if(title!=""){
  //1.관심자료 목록 가져오기
  var datList = getCernDatList();
  var tempData = "";
  var mode = 0;
  var first = 0;
  var uName = "";
  if(datList.length>0){
   //2. 중복자료 검사
   var para = "";
   var titleV = "";
   var temp = "";
   for(var i=0;i<datList.length;i++){
    temp = datList[i].split("--");
    if(temp != null){
     para = temp[0].substring(4);
     titleV = temp[1].substring(6);
     if(para==url){
      mode = 1;
      break;
     }else{
      // 2-1 데이터 저장
      if(tempData==""){
        uName = 'url=';
      }else{
        uName = '---url=';
      }
      if (navigator.appName.charAt(0) == 'N') {
       tempData += uName+toUtf8(para)+'--title='+toUtf8(titleV);
      } else if (navigator.appName.charAt(0) == 'M') {
       tempData += uName+para+'--title='+titleV;
      }
     }
    }
   }
  }else{
   first = 1;
  }
  //3. 등록 
  if(mode == 0){
   if(datList.length <= 20){    // 저장 개수 설정
    if(first==1){
     uName = 'url=';
    }else{
     uName = tempData+'---url=';
    }
    if (navigator.appName.charAt(0) == 'N') {
     setCookie('cernDatList',uName+toUtf8(url)+'--title='+toUtf8(title));
    } else if (navigator.appName.charAt(0) == 'M') {
     setCookie('cernDatList',uName+url+'--title='+title);
    }
   
    //4. 등록 확인
    var resultSize = getCernDatList();
    if(datList.length<resultSize.length){
     alert("관심자료에 등록되었습니다.");
    }else{
     alert("관심자료 등록 중 오류가 발생하였습니다.");
    }
   }else{
    alert("저장 개수가 초과되었습니다.\n(20개까지 저장 가능합니다.)");
   }
  }else{
   alert("이미 등록된 자료입니다.");
  } 
 }else{
  alert("등록 자료가 없습니다.");
 }
}

/**
  * 관심자료 삭제
  */
function delCernDatList(){
 var oldCernSize = getCernDatList();
 //if(!document.cernFrm.allCernLi.checked){
  
  var delNo = "";
  var cernList = "";
  var temp = "";
  var para = "";
  var titleV = "";
  var tempData = "";
  var boo = "";
  var cntCheckNo = 0;
  for(var i=0;i<els("cernLi").length;i++){
   if(els("cernLi").length==1){
    boo = els("cernLi")[i].checked
    delNo = els("cernLi")[i].value;
    
   }else{
    boo = els("cernLi")[i].checked
    delNo = els("cernLi")[i].value;
   }
    cernList = getCernDatList();
    tempData = "";
   if(getCookie('cernDatList')!=""){
    for(var j=0;j<cernList.length;j++){
     temp = cernList[j].split("--");
     para = temp[0].substring(4);
     titleV = temp[1].substring(6);
     if(para==delNo && boo==true){
      cntCheckNo = 1;
     }else{
      if(tempData==""){
        uName = 'url=';
      }else{
        uName = '---url=';
      }
      if (navigator.appName.charAt(0) == 'N') {
       tempData += uName+toUtf8(para)+'--title='+toUtf8(titleV);
      } else if (navigator.appName.charAt(0) == 'M') {
       tempData += uName+para+'--title='+titleV;
      }
     }
    }
    // 삭제 리스트 제외한 리스트 저장
    setCookie('cernDatList',tempData);
   }
  }
  if(cntCheckNo>0){
   //setCookie('cernDatList',tempData);
   var afList = getCernDatList();
   if(oldCernSize.length>afList.length){
    alert("관심자료 삭제 성공");
   }else{
    alert("관심자료 삭제 실패");
   }
  }else{
   alert("선택된 자료가 없습니다.");
  }
 outputList();
}


/**
  * 관심자료 리스트 뿌려주기
  */
function outputList() {
    var temp = "";
 if (navigator.appName.charAt(0) == 'N') {
     temp = fromUtf8(getCookie('cernDatList'));
   } else if (navigator.appName.charAt(0) == 'M') {
     temp = getCookie('cernDatList');
   }
 var text = temp.split("---");
 var outText = "";
 var divHtml = "<ul>";
 if(temp!=""){
  var sortNo = text.length-1;
  var tempNo = 0;
  for(var i = 0; i<text.length;i++){
    outText = text[sortNo].split("--");
    tempNo = i+1;
    divHtml += "<li><input type=\"checkbox\" class=\"vmid\" name=\"cernLi\" value=\""+outText[0].substring(4)+"\"/><a href=\"#\" onclick=\"javascript:openPop('"
      + outText[0].substring(4) + "');\">&nbsp;" + tempNo +".&nbsp;"
      + outText[1].substring(6).replace("00000","<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;") +
      "</a></li>";
    sortNo--;
     }
 }else{
   divHtml += "<li>자료 없음</li>";
 }
 //alert(divHtml);
    document.getElementById("cernDat").innerHTML = divHtml+"</ul>";

 
/**
  * 관심자료 리스트 보여주기
  */
function fCernDat(){
 var mode = document.getElementById("cernDat").style.display;
 if(mode==""){
  document.getElementById("cernDat").style.display = "none";
 }else{
  document.getElementById("cernDat").style.display = "";
  outputList();
 }
 
   
}
 
/**********************************************************************
 *
 *  Unicode ⇔ UTF-8
 *
 **********************************************************************/

function toUtf8(s) {
  var c, d = "";
  for (var i = 0; i < s.length; i++) {
    c = s.charCodeAt(i);
    if (c <= 0x7f) {
      d += s.charAt(i);
    } else if (c >= 0x80 && c <= 0x7ff) {
      d += String.fromCharCode(((c >> 6) & 0x1f) | 0xc0);
      d += String.fromCharCode((c & 0x3f) | 0x80);
    } else {
      d += String.fromCharCode((c >> 12) | 0xe0);
      d += String.fromCharCode(((c >> 6) & 0x3f) | 0x80);
      d += String.fromCharCode((c & 0x3f) | 0x80);
    }
  }
  return d;
}

function fromUtf8(s) {
  var c, d = "", flag = 0, tmp;
  for (var i = 0; i < s.length; i++) {
    c = s.charCodeAt(i);
    if (flag == 0) {
      if ((c & 0xe0) == 0xe0) {
        flag = 2;
        tmp = (c & 0x0f) << 12;
      } else if ((c & 0xc0) == 0xc0) {
        flag = 1;
        tmp = (c & 0x1f) << 6;
      } else if ((c & 0x80) == 0) {
        d += s.charAt(i);
      } else {
        flag = 0;
      }
    } else if (flag == 1) {
      flag = 0;
      d += String.fromCharCode(tmp | (c & 0x3f));
    } else if (flag == 2) {
      flag = 3;
      tmp |= (c & 0x3f) << 6;
    } else if (flag == 3) {
      flag = 0;
      d += String.fromCharCode(tmp | (c & 0x3f));
    } else {
      flag = 0;
    }
  }
  return d;
}

 /**********************************************************************
 *
 *  내가 찾은 자료  & 검색어 목록
 *
 **********************************************************************/
 
/**
  * 리스트 보여주기
  */
function fQuickDat(dataId){
 var mode = document.getElementById(dataId+"List").style.display;
 if(mode==""){
  document.getElementById(dataId+"List").style.display = "none";
 }else{
  document.getElementById(dataId+"List").style.display = "";
  outputDataList(dataId);
 }
 
   
}
 
 
/**
  * 목록 가져오기
  * return : list1[]
  */
function getDatList(dataId){
 var list =  "";
 if (navigator.appName.charAt(0) == 'N') {
  list = fromUtf8(getCookie(dataId));
 } else if (navigator.appName.charAt(0) == 'M') {
  list = getCookie(dataId);
 }
 if(list.length>0){
  list =  list.split("---");
 }else{
  list = "";
 }
 return list;
}

/**
  * 등록 
  */
function setDatList(dataId, url, title){
 
 if(title != ""){
  //1.목록 가져오기
  var datList = getDatList(dataId);
  var tempData = "";
  var first = 0;
  var uName = "";
  if(datList.length > 0){
   //2. 중복자료 검사
   var preSavedUrl = "";
   var preSavedTitle = "";
   var temp = "";
  
   for(var i = 0; i < datList.length; i++){
    temp = datList[i].split("--");
    preSavedUrl = temp[0].substring(4);
    preSavedTitle = temp[1].substring(6);
   
    if(preSavedUrl == url){
     //alert(preSavedUrl); 최상위로 올림
     //return false;
     
    }else{
     // 2-1 데이터 저장
     if(tempData == ""){
       uName = 'url=';
     }else{
       uName = '---url=';
     }
     if (navigator.appName.charAt(0) == 'N') {
      tempData += uName + toUtf8(preSavedUrl) + '--title=' + toUtf8(preSavedTitle);
     } else if (navigator.appName.charAt(0) == 'M') {
      tempData += uName + preSavedUrl + '--title=' + preSavedTitle;
     }
    }
   }
  }
  else{
   first = 1;
  }
  
  //3. 등록 
  //alert(mode+"---"+datList.length);
  if(first==1){
   uName = 'url=';
  }
  else{
   uName = tempData + '---url=';
  }
 
  if (navigator.appName.charAt(0) == 'N') {
   setCookie(dataId, uName + toUtf8(url) + '--title=' + toUtf8(title));
  }
  else if (navigator.appName.charAt(0) == 'M') {
   setCookie(dataId, uName + url + '--title=' + title);
  }
 
  //alert(datList.length);
  if(datList.length > 20){  // 저장 개수 설정
   delDatList(dataId, 1);
  }
 }
 
}

 
 
/**
  * 삭제        (쿠키 id, 삭제 모드)
  */
function delDatList(dataId,mode){
 var oldCernSize = getDatList(dataId);
 if(mode==1){
  var cernList = "";
  var temp = "";
  var para = "";
  var titleV = "";
  var tempData = "";
 
    cernList = getDatList(dataId);
    tempData = "";
   if(getCookie(dataId)!=""){
    for(var j=0;j<cernList.length;j++){
     temp = cernList[j].split("--");
     para = temp[0].substring(4);
     titleV = temp[1].substring(6);
     if(j==0){
      
     }else{
      if(tempData==""){
        uName = 'url=';
      }else{
        uName = '---url=';
      }
      if (navigator.appName.charAt(0) == 'N') {
       tempData += uName+toUtf8(para)+'--title='+toUtf8(titleV);
      } else if (navigator.appName.charAt(0) == 'M') {
       tempData += uName+para+'--title='+titleV;
      }
     }
    }
    // 삭제 리스트 제외한 리스트 저장
    setCookie(dataId,tempData);
   }
  
 }else{
  deleteCookie(dataId);
  var resultSize = getDatList(dataId);
  if(oldCernSize.length>resultSize.length){
   alert("삭제 성공");
  }else{
   alert("삭제 실패");
  }
 }
 //outputDataList(dataId);
}
 
 
/**
  * 리스트 뿌려주기
  */
function outputDataList(dataId) {
    var temp = "";
 if (navigator.appName.charAt(0) == 'N') {
     temp = fromUtf8(getCookie(dataId));
   } else if (navigator.appName.charAt(0) == 'M') {
     temp = getCookie(dataId);
   }
 var text = temp.split("---");
 var outText = "";
 var divHtml = "";
 var conTit = "";
 if(temp!=""){
  var sortNo = text.length-1;
  for(var i = 0; i < text.length && i < mainListSize;i++){
    outText = text[sortNo].split("--");
   if(outText != ""){
    if(dataId=="myFindDat"){
     idxStart = outText[1].indexOf("[");
   
     if(idxStart > 6) subject = outText[1].substring(6, idxStart);
     else    subject = outText[1].substring(6);
     subject = subject.replace("00000","").replace("_", "").replace("title=", "").replace("n", "");
     if(subject.length > 23) subject = subject.substring(0, 24) + "...";
     
     if(idxStart > 0){
         content = outText[1].substring(idxStart);
         conTit  = outText[1].substring(idxStart);
        
     } else {
         content = "";
         conTit  = "";
     }
     
     if(content.length > 8) content = content.substring(0, 9) + "...";
   
     divHtml += "<dt><a href=\"#\" onclick=\"javascript:openPop('" + outText[0].substring(4) + "');\" >"
      //+ (i + 1) + ". "
      + subject + "</a></dt>";    
     divHtml += "<dd><span title='"+conTit+"'>" + content + "</span></dd><br>";
    }else{
     divHtml += "<p><a href=\"#\" onclick=\"javascript:openPop('" + outText[0].substring(4) + "');\" >"
      + (i + 1) + ". " + outText[1].substring(6) + "</a></p><br>";
    }
   }
    sortNo--;
     }
         /*alert(outText[0].substring(4));
         alert(outText[1].substring(6));*/
 }else{
   divHtml += "<dt>조회한 이력이 없습니다.</dt>";
 }
    document.getElementById(dataId).innerHTML = "<dl>" + divHtml + "</dl>";

function outputDataNmList(dataId) {

    var temp = "";
 if (navigator.appName.charAt(0) == 'N') {
     temp = fromUtf8(getCookie(dataId));
   } else if (navigator.appName.charAt(0) == 'M') {
     temp = getCookie(dataId);
   }
 var text = temp.split("---");
 var outText = "";
 var divHtml = "";
 if(temp!=""){
  var sortNo = text.length-1;
  for(var i = 0; i < text.length;i++){
    outText = text[sortNo].split("--");
    divHtml += "<p><a href=" + outText[0].substring(4) + " >"
      + (i + 1) + ". " + outText[1].substring(6) + "</a></p>";
    sortNo--;
     }
         /*alert(outText[0].substring(4));
         alert(outText[1].substring(6));*/
 }else{
   divHtml += "<p>자료 없음</p>";
 }
    document.getElementById(dataId).innerHTML = divHtml;


/**
  * 검색어 쿠키 등록
  */
function fSearchKeySaveF(){
 setDatList('schTrmDat','searchKeyWord',document.getElementById("searchKeyWord").value);
}

function searchTrmSave(url, id){
 setDatList('schTrmDat', url, el(id).value);
}

/**
  * 검색어 쿠키 등록  (다음 실행 함수)
  */
function fSearchKeySave(nextProc){
 setDatList('schTrmDat','searchKeyWord',document.getElementById("searchKeyWord").value);
 nextProc();
}

function addMyFindDat(url, id){
    try{
 url = url.replaceAll("<strong>", "").replaceAll("</strong>", "");
 setDatList("myFindDat", url, id)
 }catch(e){deleteCookie("myFindDat");}
}

// 내가 찾은용어  검색 라인에 보여주기
function searchTrmView(callBackName){
 var temp = "";
 var dataId = "schTrmDat";
 if (navigator.appName.charAt(0) == 'N') {
     temp = fromUtf8(getCookie(dataId));
   } else if (navigator.appName.charAt(0) == 'M') {
     temp = getCookie(dataId);
   }
 var text = temp.split("---");
 var outText = "";
 var divHtml = "";
 if(temp == null || temp.trim() == ""){
   divHtml += "검색어를 입력하세요.";
 }
 else{
  var sortNo = text.length;
  if(sortNo > 5){
   sortNo = 5;
  }
  var tempNo = text.length - 1;
  var txtTitle = "";
  for(var i = 0; i < sortNo; i++){
    outText = text[tempNo].split("--");
    txtTitle = outText[1].substring(6);
    if(txtTitle.length > 7){
     txtTitle = txtTitle.substring(0,7) + "...";
    }

   if(i > 0) divHtml += ", ";
   if(typeof(callBackName) != "undefined" && callBackName != null){
    divHtml += "<a href=# onclick=\"javascript:" + callBackName + "('" + outText[1].substring(6) + "');\" >" + txtTitle + "</a>";
   }
   else{
     divHtml += "<a href=" + outText[0].substring(4) + " title="+outText[1].substring(6)+">" + txtTitle + "</a>";
   }

    tempNo --;
     }
  divHtml = divHtml.substring(0, divHtml.length - 1); 
 }

    document.getElementById("searchTrm").innerHTML = divHtml;
}


 /**********************************************************************
 *
 *  내가 찾은 법령 이력
 *
 **********************************************************************/
var maxDetailCookie = 10;
function setDetailSelectCookie(lawKubun,seq){
 var dataId = "lawHistory";
 var dataSeq = "";
 var dataSeq = lawKubun+","+seq;
 
 if(dataSeq != ""){
  var datList = getDatList(dataId);
  var tempData = "";
  var uName = "";
  var isFirst = true;
  if(datList.length > 0){
   for(var i = 0; i < datList.length; i++){
    if ( datList[i] == dataSeq ) continue;

    if(tempData == ""){
      uName = "";
    }else{
      uName = "---";
    }
    if (navigator.appName.charAt(0) == 'N') {
     tempData += uName + toUtf8(datList[i]);
    } else if (navigator.appName.charAt(0) == 'M') {
     tempData += uName + datList[i];
    }       
   }
   isFirst = false;
  }
 
  if( isFirst == true ) {
   uName = "";
  } else {
   uName = tempData + "---";
  }
 
  if (navigator.appName.charAt(0) == 'N') {
   setCookie(dataId, uName + toUtf8(dataSeq));
  } else if (navigator.appName.charAt(0) == 'M') {
   setCookie(dataId, uName + dataSeq);
  } 
 
  if(datList.length >= maxDetailCookie){  // 저장 개수 설정
   delDetailSelectCookie(dataId);
  }     
 }
}

/**
  * 20개 이상 쿠키 삭제
  */
function delDetailSelectCookie(dataId){
 var oldList = getDatList(dataId);
 
 if ( oldList.length <= maxDetailCookie ) return;
 
 var tmpData = "";
 var isFirst = true;
 var uName = "";
 
 
 oldList.reverse();
 
 for(var i = 0; i < maxDetailCookie; i ++) {
  if ( i == 0 )
   uName = "";
  else
   uName = "---";
  if (navigator.appName.charAt(0) == 'N') {
   tmpData = toUtf8(oldList[i]) + uName + tmpData;
  } else if (navigator.appName.charAt(0) == 'M') {
   tmpData = oldList[i] + uName + tmpData;
  }
 }
 
 // 삭제 리스트 제외한 리스트 저장
 setCookie(dataId,tmpData);
}

function getDetailSelectCookie(dataId){
 var list =  "";
 if (navigator.appName.charAt(0) == 'N') {
  list = fromUtf8(getCookie(dataId));
 } else if (navigator.appName.charAt(0) == 'M') {
  list = getCookie(dataId);
 }
 return list;
}



/**********************************************************************
 *
 *  Nethru_pcId 모듈
 *
 **********************************************************************/

function Nethru_getCookieVal(offset)
{
 var endstr = document.cookie.indexOf (";", offset);
 if (endstr == -1)
  endstr = document.cookie.length;
 return unescape(document.cookie.substring(offset, endstr));
}

function Nethru_SetCookie(name, value){
   var argv = Nethru_SetCookie.arguments;
   var argc = Nethru_SetCookie.arguments.length;
   var expires = (2 < argc) ? argv[2] : null;
   var path = (3 < argc) ? argv[3] : null;
   var domain = (4 < argc) ? argv[4] : null;
   var secure = (5 < argc) ? argv[5] : false;
 //alert(value);
   //alert("DOMAIN = " + domain);
   document.cookie = name + "=" + escape (value) +
        ((expires == null) ? "" : ("; expires="+expires.toGMTString())) +
     ((path == null) ? "" : ("; path=" + path)) +
     ((domain == null) ? "" : ("; domain=" + domain)) +
        ((secure == true) ? "; secure" : "");

 //alert(document.cookie);
}

function Nethru_GetCookie(name){
   var arg = name + "=";
   var alen = arg.length;
   var clen = document.cookie.length;
   var i = 0;
   while (i < clen)
      {
      var j = i + alen;
      if (document.cookie.substring(i, j) == arg)
         return Nethru_getCookieVal (j);
      i = document.cookie.indexOf(" ", i) + 1;
      if (i == 0)
         break;
      }
  return null;
}

function Nethru_makePersistentCookie(name,length,path,domain)
{
// alert(name+" -- "+length+"--"+path+"--"+domain);
    var today = new Date();
    var expiredDate = new Date(2011,1,1);
    var cookie;
 var value;

    cookie = Nethru_GetCookie(name);
    if ( cookie ) {
//  alert(cookie);
        return 1;
 }

 var values = new Array();
 for ( i=0; i < length ; i++ ) {
  values[i] = "" + Math.random();
 }

 value = today.getTime();

 // use first decimal
 for ( i=0; i < length ; i++ ) {
  value += values[i].charAt(2);
 }

    Nethru_SetCookie(name,value,expiredDate,path,domain);
}

function Nethru_getDomain() {
 var _host   = document.domain;
 var so      = _host.split('.');
 var dm    = so[so.length-2] + '.' + so[so.length-1];
 return (so[so.length-1].length == 2) ? so[so.length-3] + '.' + dm : dm;
}

var Nethru_domain  = Nethru_getDomain();
Nethru_makePersistentCookie("PCID",10,"/",Nethru_domain);



Posted by 1010
반응형

/// #############################################################################
/// #####
/// ##### 한국신용정보주식회사 서비스 운영에 필요한 Crypto JavaScript 소스
/// #####
/// ##### =====================================================================
/// #####
/// ##### Descriptions
/// #####  - 서비스 운영에 필요한 Javascript Crypto Algorithm을 관리한다.
/// #####
/// ##### ---------------------------------------------------------------------
/// #####
/// ##### 작성자   : (주)유비아이에스컨설팅 (www.ubisc.com)
/// ##### 원본참조 :
/// ##### 원본파일 :
/// ##### 작성일자 : 2006.02.06
/// #####
/// #############################################################################

// -----------------------------------------------------
// ----- 보안 처리를 위한 Object 처리 정보
// -----------------------------------------------------

var cryptoObject = new Object();
cryptoObject.KeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

//
// Base 64 Decode
//
cryptoObject.decode64 = function( input )
{
 var output = "";
 var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;
    var strValue = input;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
 var re = /[^A-Za-z0-9\+\/\=]/g;
    strValue = strValue.replace( re, "" );

    do
    {
       enc1 = cryptoObject.KeyStr.indexOf(strValue.charAt(i++));
       enc2 = cryptoObject.KeyStr.indexOf(strValue.charAt(i++));
       enc3 = cryptoObject.KeyStr.indexOf(strValue.charAt(i++));
       enc4 = cryptoObject.KeyStr.indexOf(strValue.charAt(i++));

       chr1 = (enc1 << 2) | (enc2 >> 4);
       chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
       chr3 = ((enc3 & 3) << 6) | enc4;

       output = output + String.fromCharCode(chr1);

       if (enc3 != 64)
       {
          output = output + String.fromCharCode(chr2);
       }

       if (enc4 != 64)
       {
          output = output + String.fromCharCode(chr3);
       }
    }
    while (i < strValue.length);

   return output;
}

//
// Base 64 Encode
//
cryptoObject.encode64 = function( input )
{
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    do
    {
       chr1 = input.charCodeAt(i++);
       chr2 = input.charCodeAt(i++);
       chr3 = input.charCodeAt(i++);

       enc1 = chr1 >> 2;
       enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
       enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
       enc4 = chr3 & 63;

       if (isNaN(chr2))
       {
         enc3 = enc4 = 64;
       }
       else if (isNaN(chr3))
       {
        enc4 = 64;
       }

       output = output + cryptoObject.KeyStr.charAt(enc1) + cryptoObject.KeyStr.charAt(enc2) +
          cryptoObject.KeyStr.charAt(enc3) + cryptoObject.KeyStr.charAt(enc4);
    }
    while (i < input.length);

    return output;
}

//
// MD5 Hash
//
cryptoObject.md5 = function( sMessage )
{
  function RotateLeft(lValue, iShiftBits) { return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits)); }
  function AddUnsigned(lX,lY) {
  var lX4,lY4,lX8,lY8,lResult;
  lX8 = (lX & 0x80000000);
  lY8 = (lY & 0x80000000);
  lX4 = (lX & 0x40000000);
  lY4 = (lY & 0x40000000);
  lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
  if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
  if (lX4 | lY4)
  {
   if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
   else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
  }
  else return (lResult ^ lX8 ^ lY8);
 }
 function F(x,y,z) { return (x & y) | ((~x) & z); }
 function G(x,y,z) { return (x & z) | (y & (~z)); }
 function H(x,y,z) { return (x ^ y ^ z); }
 function I(x,y,z) { return (y ^ (x | (~z))); }
 function FF(a,b,c,d,x,s,ac) {
  a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
  return AddUnsigned(RotateLeft(a, s), b);
 }
 function GG(a,b,c,d,x,s,ac) {
  a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
  return AddUnsigned(RotateLeft(a, s), b);
 }
 function HH(a,b,c,d,x,s,ac) {
  a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
  return AddUnsigned(RotateLeft(a, s), b);
 }
 function II(a,b,c,d,x,s,ac) {
  a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
  return AddUnsigned(RotateLeft(a, s), b);
 }
 function ConvertToWordArray(sMessage)
 {
  var strMsg = new String( sMessage );
  var lWordCount;
  var lMessageLength = strMsg.length;
  var lNumberOfWords_temp1=lMessageLength + 8;
  var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
  var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
  var lWordArray=Array(lNumberOfWords-1);
  var lBytePosition = 0;
  var lByteCount = 0;
  while ( lByteCount < lMessageLength ) {
   lWordCount = (lByteCount-(lByteCount % 4))/4;
   lBytePosition = (lByteCount % 4)*8;
   lWordArray[lWordCount] = (lWordArray[lWordCount] | (strMsg.charCodeAt(lByteCount)<<lBytePosition));
   lByteCount++;
  }
  lWordCount = (lByteCount-(lByteCount % 4))/4;
  lBytePosition = (lByteCount % 4)*8;
  lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
  lWordArray[lNumberOfWords-2] = lMessageLength<<3;
  lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
  return lWordArray;
 }
 function WordToHex(lValue) {
  var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
  for (lCount = 0;lCount<=3;lCount++) {
   lByte = (lValue>>>(lCount*8)) & 255;
   WordToHexValue_temp = "0" + lByte.toString(16);
   WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
  }
  return WordToHexValue;
 }

 var strMsg = new String( sMessage );
 var x=Array();
 var k,AA,BB,CC,DD,a,b,c,d
 var S11=7, S12=12, S13=17, S14=22;
 var S21=5, S22=9 , S23=14, S24=20;
 var S31=4, S32=11, S33=16, S34=23;
 var S41=6, S42=10, S43=15, S44=21;
 // Steps 1 and 2.  Append padding bits and length and convert to words
 x = ConvertToWordArray(strMsg);
 // Step 3.  Initialise
 a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
 // Step 4.  Process the message in 16-word blocks
 for (k=0;k<x.length;k+=16) {
  AA=a; BB=b; CC=c; DD=d;
  a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
  d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
  c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
  b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
  a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
  d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
  c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
  b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
  a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
  d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
  c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
  b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
  a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
  d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
  c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
  b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
  a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
  d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
  c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
  b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
  a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
  d=GG(d,a,b,c,x[k+10],S22,0x2441453);
  c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
  b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
  a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
  d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
  c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
  b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
  a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
  d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
  c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
  b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
  a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
  d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
  c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
  b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
  a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
  d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
  c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
  b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
  a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
  d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
  c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
  b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
  a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
  d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
  c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
  b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
  a=II(a,b,c,d,x[k+0], S41,0xF4292244);
  d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
  c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
  b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
  a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
  d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
  c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
  b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
  a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
  d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
  c=II(c,d,a,b,x[k+6], S43,0xA3014314);
  b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
  a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
  d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
  c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
  b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
  a=AddUnsigned(a,AA); b=AddUnsigned(b,BB); c=AddUnsigned(c,CC); d=AddUnsigned(d,DD);
 }
 // Step 5.  Output the 128 bit digest
 var temp= WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
 return temp.toLowerCase();
}

//
// DES Symmetric Key
//
cryptoObject.des = function( key, message, encrypt, mode, iv )
{
 //des_createKeys
 //this takes as input a 64 bit key (even though only 56 bits are used)
 //as an array of 2 integers, and returns 16 48 bit keys
 function des_createKeys( key )
 {
  //declaring this locally speeds things up a bit
    pc2bytes0  = new Array (0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204);
    pc2bytes1  = new Array (0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101);
    pc2bytes2  = new Array (0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808);
    pc2bytes3  = new Array (0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000);
    pc2bytes4  = new Array (0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010);
    pc2bytes5  = new Array (0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420);
    pc2bytes6  = new Array (0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002);
    pc2bytes7  = new Array (0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800);
    pc2bytes8  = new Array (0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002);
    pc2bytes9  = new Array (0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408);
    pc2bytes10 = new Array (0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020);
    pc2bytes11 = new Array (0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200);
    pc2bytes12 = new Array (0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010);
    pc2bytes13 = new Array (0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105);

    //how many iterations (1 for des, 3 for triple des)
    var iterations = key.length >= 24 ? 3 : 1;
    //stores the return keys
    var keys = new Array (32 * iterations);
    //now define the left shifts which need to be done
    var shifts = new Array (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
    //other variables
    var lefttemp, righttemp, m=0, n=0, temp;

    for (var j=0; j<iterations; j++)
    { //either 1 or 3 iterations
     left = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
       right = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);

       temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
       temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
       temp = ((left >>> 2) ^ right) & 0x33333333; right ^= temp; left ^= (temp << 2);
       temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
       temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
       temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
       temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);

       //the right side needs to be shifted and to get the last four bits of the left side
       temp = (left << 8) | ((right >>> 20) & 0x000000f0);
       //left needs to be put upside down
       left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0);
       right = temp;

       //now go through and perform these shifts on the left and right keys
       for (i=0; i < shifts.length; i++)
       {
         //shift the keys either one or two bits to the left
         if (shifts[i]) {left = (left << 2) | (left >>> 26); right = (right << 2) | (right >>> 26);}
         else {left = (left << 1) | (left >>> 27); right = (right << 1) | (right >>> 27);}
         left &= 0xfffffff0; right &= 0xfffffff0;

         //now apply PC-2, in such a way that E is easier when encrypting or decrypting
         //this conversion will look like PC-2 except only the last 6 bits of each byte are used
         //rather than 48 consecutive bits and the order of lines will be according to
         //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
         lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf]
                 | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf]
                 | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf]
                 | pc2bytes6[(left >>> 4) & 0xf];
         righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf]
                   | pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf]
                   | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf]
                   | pc2bytes13[(right >>> 4) & 0xf];
         temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff;
         keys[n++] = lefttemp ^ temp; keys[n++] = righttemp ^ (temp << 16);
       }
    } //for each iterations

    //return the keys we've created
    return keys;
 } //end of des_createKeys

 //declaring this locally speeds things up a bit
   var spfunction1 = new Array (0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004);
   var spfunction2 = new Array (0x80108020,0x80008000,0x8000,0x108020,0x100000,0x20,0x80100020,0x80008020,0x80000020,0x80108020,0x80108000,0x80000000,0x80008000,0x100000,0x20,0x80100020,0x108000,0x100020,0x80008020,0,0x80000000,0x8000,0x108020,0x80100000,0x100020,0x80000020,0,0x108000,0x8020,0x80108000,0x80100000,0x8020,0,0x108020,0x80100020,0x100000,0x80008020,0x80100000,0x80108000,0x8000,0x80100000,0x80008000,0x20,0x80108020,0x108020,0x20,0x8000,0x80000000,0x8020,0x80108000,0x100000,0x80000020,0x100020,0x80008020,0x80000020,0x100020,0x108000,0,0x80008000,0x8020,0x80000000,0x80100020,0x80108020,0x108000);
   var spfunction3 = new Array (0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200);
   var spfunction4 = new Array (0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080);
   var spfunction5 = new Array (0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100);
   var spfunction6 = new Array (0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010);
   var spfunction7 = new Array (0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002);
   var spfunction8 = new Array (0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000);

   //create the 16 or 48 subkeys we will need
   var keys = des_createKeys (key);
   var m=0, i, j, temp, temp2, right1, right2, left, right, looping;
   var cbcleft, cbcleft2, cbcright, cbcright2
   var endloop, loopinc;
   var len = message.length;
   var chunk = 0;
   //set up the loops for single and triple des
   var iterations = keys.length == 32 ? 3 : 9; //single or triple des
   if (iterations == 3) {looping = encrypt ? new Array (0, 32, 2) : new Array (30, -2, -2);}
   else {looping = encrypt ? new Array (0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array (94, 62, -2, 32, 64, 2, 30, -2, -2);}

   message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes
   //store the result here
   result = "";
   tempresult = "";

   if (mode == 1) { //CBC mode
     cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
     cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
     m=0;
   }

   //loop through each 64 bit chunk of the message
   while (m < len)
   {
     left = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
     right = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);

     //for Cipher Block Chaining mode, xor the message with the previous result
     if (mode == 1) {if (encrypt) {left ^= cbcleft; right ^= cbcright;} else {cbcleft2 = cbcleft; cbcright2 = cbcright; cbcleft = left; cbcright = right;}}

     //first each 64 but chunk of the message must be permuted according to IP
     temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
     temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
     temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
     temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
     temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);

     left = ((left << 1) | (left >>> 31));
     right = ((right << 1) | (right >>> 31));

     //do this either 1 or 3 times for each chunk of the message
     for (j=0; j<iterations; j+=3)
     {
        endloop = looping[j+1];
        loopinc = looping[j+2];
        //now go through and perform the encryption or decryption
        for (i=looping[j]; i!=endloop; i+=loopinc)
        { //for efficiency
          right1 = right ^ keys[i];
          right2 = ((right >>> 4) | (right << 28)) ^ keys[i+1];
          //the result is attained by passing these bytes through the S selection functions
          temp = left;
          left = right;
          right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f]
                | spfunction6[(right1 >>>  8) & 0x3f] | spfunction8[right1 & 0x3f]
                | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f]
                | spfunction5[(right2 >>>  8) & 0x3f] | spfunction7[right2 & 0x3f]);
        }

        temp = left; left = right; right = temp; //unreverse left and right
     } //for either 1 or 3 iterations

     //move then each one bit to the right
     left = ((left >>> 1) | (left << 31));
     right = ((right >>> 1) | (right << 31));

     //now perform IP-1, which is IP in the opposite direction
     temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
     temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
     temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
     temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
     temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);

     //for Cipher Block Chaining mode, xor the message with the previous result
     if (mode == 1) {if (encrypt) {cbcleft = left; cbcright = right;} else {left ^= cbcleft2; right ^= cbcright2;}}
     tempresult += String.fromCharCode ((left>>>24), ((left>>>16) & 0xff), ((left>>>8) & 0xff), (left & 0xff), (right>>>24), ((right>>>16) & 0xff), ((right>>>8) & 0xff), (right & 0xff));

     chunk += 8;
     if (chunk == 512) {result += tempresult; tempresult = ""; chunk = 0;}
   } //for every 8 characters, or 64 bits in the message

   //return the result as an array
   return result + tempresult;
} //end of des

//
// Print Hex Array
//
cryptoObject.printHex = function( s )
{
 var r = "0x";
   var hexes = new Array ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
   for (var i=0; i<s.length; i++) {r += hexes [s.charCodeAt(i) >> 4] + hexes [s.charCodeAt(i) & 0xf];}
   return r;
}

//
// Print UnHex Array
//
cryptoObject.unHex = function( s )
{
 var r = "";
   for (var i=2; i<s.length;i+=2) {
    x1 = s.charCodeAt(i);
    x1 = x1 >= 48 && x1 < 58 ? x1 - 48 : x1 - 97 + 10;
    x2 = s.charCodeAt(i+1);
    x2 = x2 >= 48 && x2 < 58 ? x2 - 48 : x2 - 97 + 10;
    r += String.fromCharCode (((x1 << 4) & 0xF0) | (x2 & 0x0F));
   }

   return r;
}

//
// Client Random Key 생성
//

cryptoObject.getRandomKey = function( digits )
{
 var rndKey, nIndex;

 rndKey = "";

 do
 {
  nIndex = Math.floor( Math.random() * cryptoObject.KeyStr.length ) + 1;
  rndKey = rndKey + cryptoObject.KeyStr.substr( nIndex, 1 );
 }
 while ( rndKey.length < digits )

 return rndKey;
}

Posted by 1010
반응형

1. 태그이름은 소문자로

예)

<HTML> → <html>

<BODY> → <body>


.. 속성은 괜찮은건가?


2. Empty 태그 끝에는 공백/>


<area> <base> <basefont> <br> <col> <frame> <hr> <img> <input> <param> <isindex> <link> <meta> 등등


3. img 태그에는 alt="" 를 반드시 넣자

 

4. 속성값은 "" 따옴표 안에 넣자.


예)

<img src="b.gif" width="84" height="18" border="0" alt=" " />


5. DOCTYPE 과 ENCODING 을 적어주자.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=euc-kr" />

<title>homepage</title>

..


6. 스타일에 사용하는 숫자값에는 단위를 넣어주세요.


웹표준 준수

 

XHTML 1.x 나 HTML 4.x 표준에 맞춘 문서는 99% 접근성이 좋은 사이트들이다.

table 레이아웃 --> div

font, b --> CSS

html 코드는 반으로 코딩과 유지보수 효율성은 2배로~

 

구조/표현/동작(양식)을 분리

 

구조 (Structure) - HTML, XHTML

표현 (Presentation) - CSS

동작 (Behavior) - DOM, ECMAScript, 서버 측 개발

 

최소한의 디버깅


구조 (Structure) - HTML, XHTML - http://validator.w3.org

표현 (Presentation) - CSS - http://jigsaw.w3.org/css-validator/

동작 (Behavior) - DOM, ECMAScript - Mozilla Firefox 의 자바스크립트 디버거


효율적인 웹 개발 방법론


기획 -> 디자인 -> 개발

컨베이어 벨트에 놓인 물건 같이 완성품을 만들어가는 것이 아니라

구조, 표현, 양식을 나누어 공동으로 작업



출처 : http://cafe.naver.com/w3design.cafe
출처 : http://cafe.naver.com/w3design.cafe

Posted by 1010
반응형

How to use entities for special characters

For copyright notices, or trademarks it is customary to include the appropriate signs:

Symbol Entity Example
Copyright sign &copy; Copyright © 1999 W3C
Registered trademark &reg; MagiCo ®
Trademark &#8482; Webfarer™

Note HTML 4.0 defines &trade; for the trademark sign but this is not yet as widely supported as &#8482;

There are a number of other entities you may find useful:

Symbol Entity Example
Less than &lt; <
Greater than &gt; >
Ampersand &amp; &
nonbreaking space &nbsp;  
em dash &#8212;
quotation mark &quot; "

And then, there are entities for accented characters and miscellaneous symbols in the Latin-1 character set:

  &nbsp; &#160; Ð &ETH; &#208;
¡ &iexcl; &#161; Ñ &Ntilde; &#209;
¢ &cent; &#162; Ò &Ograve; &#210;
£ &pound; &#163; Ó &Oacute; &#211;
¤ &curren; &#164; Ô &Ocirc; &#212;
¥ &yen; &#165; Õ &Otilde; &#213;
¦ &brvbar; &#166; Ö &Ouml; &#214;
§ &sect; &#167; × &times; &#215;
¨ &uml; &#168; Ø &Oslash; &#216;
© &copy; &#169; Ù &Ugrave; &#217;
ª &ordf; &#170; Ú &Uacute; &#218;
« &laquo; &#171; Û &Ucirc; &#219;
¬ &not; &#172; Ü &Uuml; &#220;
­ &shy; &#173; Ý &Yacute; &#221;
® &reg; &#174; Þ &THORN; &#222;
¯ &macr; &#175; ß &szlig; &#223;
° &deg; &#176; à &agrave; &#224;
± &plusmn; &#177; á &aacute; &#225;
² &sup2; &#178; â &acirc; &#226;
³ &sup3; &#179; ã &atilde; &#227;
´ &acute; &#180; ä &auml; &#228;
µ &micro; &#181; å &aring; &#229;
&para; &#182; æ &aelig; &#230;
· &middot; &#183; ç &ccedil; &#231;
¸ &cedil; &#184; è &egrave; &#232;
¹ &sup1; &#185; é &eacute; &#233;
º &ordm; &#186; ê &ecirc; &#234;
» &raquo; &#187; ë &euml; &#235;
¼ &frac14; &#188; ì &igrave; &#236;
½ &frac12; &#189; í &iacute; &#237;
¾ &frac34; &#190; î &icirc; &#238;
¿ &iquest; &#191; ï &iuml; &#239;
À &Agrave; &#192; ð &eth; &#240;
Á &Aacute; &#193; ñ &ntilde; &#241;
 &Acirc; &#194; ò &ograve; &#242;
à &Atilde; &#195; ó &oacute; &#243;
Ä &Auml; &#196; ô &ocirc; &#244;
Å &Aring; &#197; õ &otilde; &#245;
Æ &AElig; &#198; ö &ouml; &#246;
Ç &Ccedil; &#199; ÷ &divide; &#247;
È &Egrave; &#200; ø &oslash; &#248;
É &Eacute; &#201; ù &ugrave; &#249;
Ê &Ecirc; &#202; ú &uacute; &#250;
Ë &Euml; &#203; û &ucirc; &#251;
Ì &Igrave; &#204; ü &uuml; &#252;
Í &Iacute; &#205; ý &yacute; &#253;
Î &Icirc; &#206; þ &thorn; &#254;
Ï &Iuml; &#207; ÿ &yuml; &#255;

You can also use numeric character entities for the greek letters and mathematical symbols defined in Unicode. For more details, take a look at the list specified in the HTML 4 specification. Note that the entity names for these characters aren't recognized in Navigator 4, so you are recommended to stick to the numeric entities instead.

Posted by 1010
반응형
Images as submit buttons

This technique relates to the following sections of the guidelines:

Task:

Avoid using images with onclick="form.submit()" as submit buttons.

A submit button is a submit button, and an image is an image. There is no need to mix the two. However, it is very common to see the following code, which leaves users of screen readers and people who can't use a mouse completely unable to submit their form:

Deprecated Example:

 
<form>
<img src="submit.gif" alt="Submit this form" onclick="submitmyform()">
</form>

Example:

The example below shows how to create an image-based submit button that is compatible with assistive technology:

 
<form>
<input type="image" name="submit" src="submit.gif" alt="Submit this form">
</form>
Posted by 1010
반응형
Form URIs

This technique relates to the following sections of the guidelines:

Task:

Avoid javascript: URIs for form actions.

Setting the action attribute in a form to a javascript: URI causes non-script-capable browsers to fail silently.

Deprecated Example:

This example code shows a problematic use of the javascript: URI:

 
<form action="javascript:submitmyform()">
...
</form>

Deprecated Example:

Another common error is to point the form's action to "#" (the top of the current document), while using the onsubmit event. This causes users of non-script-capable browsers to become confused, as their repeated activation of the submit button does nothing.

 
<form action="#" onsubmit="submitmyform()">
...
</form>

Example:

The correct method for firing an ECMAScript function when a form is submitted is to use the onsubmit event. The checkFormFields() function would return true if there are form errors, stopping the submission of the form:

 
<form action="submit.php" onsubmit="return checkFormFields();">
...
</form>
Posted by 1010
반응형
 javascript: URIs

This technique relates to the following sections of the guidelines:

Task:

Avoid javascript: URIs. Attach events using DOM event attributes.

The javascript: URI space should not be used. All ECMAScript should be designed to degrade gracefully when script is not supported, and javascript: URIs necessarily break that graceful degradation.

Editorial Note: This is being discussed in the WG presently. One issue is whether, if JavaScript is assumed to exist in the client, it is necessary to restrict javascript: URIs. On the other hand, the javascript: namespace has referentiality problems, and in many cases, users can enjoy backward-compatibility without any undue burden on the author. (See bug 1073 for more detail.)

Deprecated Example:

Code such as the example below locks many users out of important portions of the site:

 
<a href="javascript:window.open('register.php')">click here</a> to register.

Example:

It is better in general to use the DOM events (onactivate, onclick, onkeypress, etc.) to call script functions, but leave a real http: URI in the link for non-script-capable browsers. In rare cases, it may be necessary to create a second page that duplicates the functionality of the page called by the script, but most of the time it is sufficient to point users to the same target page that is called by the script.

 
<a href="register.php" target="registerwindow"
 onclick="window.open('',this.target);">register here</a>
 
Posted by 1010
반응형

2.2 Dynamic content generation

This technique relates to the following sections of the guidelines:

Task:

Avoid document.write() and innerHTML().

Assistive technologies such as screen readers rely on the Document Object Model (DOM) to interpret the semantics in HTML for a different modality. Given this, the document.write() and innerHTML() methods can render content invalid (and inaccessible via DOM) after the fact.

Deprecated Example:

This deprecated example shows a script that inserts a header, a paragraph (which is unterminated, and thus invalid), and a list (again, invalid) into a given document.

 
function fillContent() {
	document.write("<h1>Welcome to my site</h1>");
	document.write("<p>Lorem ipsum dolor sit amet");
	document.menu.innerHTML = "<ul><li><a href="foo.html">foo</a>";
}

Example:

The following code sample does the same as the example above, but produces valid code which appears in the HTML document's DOM tree:

 
function fillContent() {
	// parentelem is a specified element in the DOM
	var header = document.createElement("h1");
	header.insertText("Welcome to my site");
	var para = document.createElement("p");
	para.insertText("Lorem ipsum dolor sit amet");
	var list = document.createElement("ul");
	itemone = document.createElement("li");
	itemonelink = document.createElement("a");
	itemonelink.setAttribute("href","foo.html");
	itemonelink.insertText("foo");
	list.appendChild(itemone);
	parentelem.appendChild(header);
	parentelem.appendChild(para);
	parentelem.appendChild(list);
}

Editorial Note: Two issues have been raised with this example what happens to XSL on server-side and how does this effect XPointers (and RDF-based accessibility).

Posted by 1010
반응형
<form name="frmLinkInfo" action="/foahome/jsp/site_link.jsp" method="post" target="_blank" onsubmit="return linkSite(this.selSite);">
  <select id="jump_02" name="selSite">
    <option value="">산림행정정보사이트</option>
    <option value="http://www.meari.go.kr">대국민업무포털메아리</option>
    <option value="http://www.nature.go.kr">국가생물종지식정보</option>
    <option value="http://www.nature.go.kr/kpni">국가표준식물목록</option>
    <option value="http://carbon.forest.go.kr">기후변화와산림</option>
    <option value="http://www.forestland.go.kr/">산지정보시스템</option>
    <option value="http://www.forestlove.or.kr/">숲사랑커뮤니티</option>
    <option value="http://kfep.forest.go.kr">숲사랑지도원관리시스템</option>
    <option value="http://fec.forest.go.kr/legal">산림사업법인</option>
    <option value="http://fgis.forest.go.kr">산림공간정보</option>
    <option value="http://forestfire.kfri.go.kr">산불위험예보시스템</option>
    <option value="http://sanfire.forest.go.kr">산불정보시스템</option>
    <option value="http://sansatai.forest.go.kr/welcome.do">산사태관리</option>
    <option value="http://www.foreston.go.kr">숲에ON</option>
    <option value="http://soft.forest.go.kr">임산물수출입통계</option>
    <option value="http://www.forestinfo.or.kr/index2.html">임산물유통정보</option>
    <option value="http://www.huyang.go.kr">자연휴양림예약정보</option>
    <option value="http://photo.forest.go.kr">포토갤러리</option>
  </select>
  <!--a href="#jump_02"><img src="/html/common/_images/jump_btn.gif" alt="go 새창" /></a-->
  <input type="image"  src="/html/common/_images/jump_btn.gif" alt="산림행정정보사이트로 이동합니다.-새창 " align="middle" />
  </form>

form 안에 input 태그 타입이 image 일경우 폼을 서브밋함.
Posted by 1010
반응형

접근성을 해치지 않는 자바스크립트의 사용

신현석

2006년 5월

자바스크립트에 대한 잘못된 생각

자바스크립트 없이는 개발을 할 수 없다?

많은 개발자들이 자바스크립트가 없이는 개발을 할 수 없다고 생각한다. 그만큼 자바스크립트를 일상적으로 많이 사용하고, 자바스크립트에 대해서 잘못 오해하고 있는 부분이 많다는 것이다. 자바스크립트는 클라이언트 환경에서 작동하기 때문에 핵심로직에 사용해서는 안된다. 핵심적인 로직은 서버사이드 언어로 처리를 하고 자바스크립트는 그 옆에서 UI구성을 위해서 도와주기만 해야 한다. 바꿔 말하면 자바스크립트가 없어도 핵심 로직은 작동을 해야 한다. 먼저 자바스크립트없이 HTML과 서버사이드 언어만으로 완벽하게 작동 할 수 있게 개발을 끝낸 후 자바스크립트를 이용해서 좋은 UI나 유효성 검사 등을 하는 부분을 추가 하는 순서로 만들어야 한다. 만약 이를 어기고 자바스크립트를 기능의 일부로 사용하면 접근성이 떨어지는 것 뿐만 아니라 보안도 떨어지고 데이터의 무결성도 보장되지 않는다.

자바스크립트가 작동하지 않는 환경도 고려를 해 줘야 하는가?

자바스크립트가 작동하지 않는 환경이 일반적인 상황은 아니지만 스크립트를 사용할 수 없는 환경에 대한 고려는 반드시 필요하다. 실제로 브라우져에 따라서는 자바스크립트 버젼이 다를 수 있고 개발 환경에서는 잘 작동하던 기능이 어떤 사용자 환경에서는 작동하지 않을 수도 있다. 그리고 사용자 중에서도 여러 이유로 스스로 자바스크립트 사용을 중지하고 사용하는 경우도 있다. 자바스크립트를 사용하지 않아도 핵심 기능을 구현할 수 있음에도 불구하고 불필요한 자바스크립트를 사용하여 접근성을 떨어뜨리는 것이 올바른 페이지 제작 방법은 아니다.

서버 부하를 줄이기 위해서 자바스크립트로만 유효성 검사를 한다?

자바스크립트를 이용해서 서버의 부하를 줄일 수 있다는 것은 많은 사람들이 알고 있을 것이다. 자바스크립트로 선처리를 행함으로서 네트웍이나 서버의 처리를 감소시킨다는 것인데 이것을 잘못 이해하여 자바스크립트만으로 유효성을 체크하는 것이 좋다고 생각하는 사람들이 있다. 자바스크립트로 선처리를 한결과물을 그대로 믿으면 안된다. 사용자측으로 부터 넘오온 모든 값은 그 값의 유효성을 완전히 보장할 수 없기 때문에 서버측에서도 유효성 체크를 해 줘야만 한다. 이것은 서버의 부하를 높이는 것 이전에 자료의 무결성을 보장하는 중요한 과정이다. 자바스크립트를 거치지 않고 서버에 임의로 변조된 값을 보내는 일은 아주 쉬운 일이다.

자바스크립트를 사용하지 않으면 UI가 불편해 진다?

자바스크립트를 이용해서 RIA나 좋은 UI를 만들 수 있는 것은 사실이지만 웹환경을 이해하고 일반적인 웹 인터페이스를 이용해서 만드는 것이 더 좋은 UI를 제공할 수 있다. 사용자 친화적인 UI에 대한 고민을 해야지 자바스크립트를 사용했다고 좋은 UI가 나오는 것은 아니다. 실제적으로 가장 사용자가 이해하기 쉬운 UI는 사용자 OS나 브라우저에서 기본적으로 제공하는 컨트롤 인터페이스를 그대로 사용하는 것이고 이는 자바스크립트 없이도 충분히 가능하다.

자바스크립트는 사용자 환경에 내려보내지고 사용자의 브라우져에서 실행이 되기 때문에 이에 의존해서 프로그램을 만들게 되면 보안, 접근성에 문제가 생기기 쉽다. 이러한 자바스크립트의 특징을 정확히 이해하지 못한 잘못된 개발 방법이나 상식들 때문에 자바스크립트가 오용되고 있는 경우가 많다. 자바스크립트는 어디까지나 보조적인 수단이라는 것을 이해하고 핵심적인 기능을 해치지 않는 한도에서 사용하는 것이 무엇보다 중요하다.

자바스크립트 선언

<script language="Javascript">
//code
</script>

자바스크립트는 <script> 엘리먼트로 선언을 한다. 모든 <script>엘리먼트는 type을 명시해 주어야 하고 자바스크립트의 type은 "text/javascript" 이다. 많은 경우 language 만을 선언해서 자바스크립트버젼을 명시하는데 반드시 type도 같이 명시를 해 주어야 한다.

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

<a>의 href 속성과 자바스크립트의 사용

href는 Hypertext REFerence의 약자이다. 다시 말해서 hypertext의 위치를 나타내는 uri를 그 값으로 갖는다. 하지만 많은 경우 이 href안에 "javascript:myFunction()"과 같이 잘못된 구문을 이용하는 것을 볼 수 있다. 이와 같이 href안에 잘못된 값이 들어가게 될 경우, 북마크나 새창, 새탭으로 열기 등의 href 관련된 브라우저의 기능들이 정상적으로 작동하지 않게 된다. 따라서 href안에는 항상 uri가 들어가도록 하고 자바스크립트 적용은 onclick과 같은 이벤트 속성을 이용해야 한다.

의미 없는 href 값을 사용한 경우

사용자의 링크 클릭이 링크와 관련이 있고 이를 자바스크립트를 이용해서 처리를 하야 하는 경우가 있다면 우선은 자바스크립트를 빼고도 페이지의 이동을 할 수 있게 href에 적절한 값을 넣어 주어야 한다. 이와 같은 경우로 탭메뉴를 들 수 있다. 탭메뉴의 경우 탭을 누르면 해당 탭과 관련있는 컨텐츠를 보여주는 식으로 작동하게 된다. javasript가 없다면 탭을 클릭했을 때 해당 컨텐츠로 이동을 하는 식으로 구현 되면 된다. href 안의 값으로 페이지 안에서의 해당 컨텐츠 앵커 주소를 넣는 것으로 간단히 구현 된다.

<a href="#notice-list"><img src="notice-tab.gif" alt="Notice" /></a>

그리고 이 마크업을 기본으로 하여 이벤트 속성으로 원하는 기능을 넣어주면 된다.

<a href="#notice-list" onclick="showNoticeTab(); return false;"><img src="notice-tab.gif" alt="Notice" /></a>

onclick으로 탭을 보여준 후 false를 리턴하여 해당 앵커로 이동하지 않도록 처리 한다. 자바스크립트가 작동을 할 때에는 클릭하면 정상적으로 탭으로 작동을 할 것이고, 그렇지 않을 경우에는 해당 컨텐츠로 이동을 하여 높은 접근성을 유지할 수 있다.

만약 자바스크립트가 링크와 관련이 없는 경우에는 <a>태그를 사용해서 스크립트를 적용하면 안된다. 보통 특정 효과를 주는 것이 이러한 것에 해다하게 되는데 이 경우 자바스크립트가 작동을 하지 않아도 컨텐츠 이해에 크게 문제가 되지 않는 경우이다.

<img src="button.gif" style="cursor: pointer;" onclick="myAction()" />

효과를 위한 자바스크립트는 단순히 onclick을 이용해서 적용을 하고 <a>를 사용하지 않는다. 그리고 사용자가 마우스 포인터를 올렸을 때 손모양으로 나오는 것은 스타일로 처리하면 된다.

팝업창을 열 때(window.open)

<img src="openWindow.gif" onclick="window.open('popup.html', '', 'widht=300,height=200')">
<a href="#"><img src="openWindow.gif" onclick="window.open('popup.html', '', 'widht=300,height=200')"></a>

href에 #과 같은 의미 없는 값을 넣거나 onclick 안에 경로를 처리하는 경우가 있는데 팝업창은 링크이고 페이지가 별도로 존재 하기 때문에 <a>를 이용해서 기능을 구현하고 href엔느 해당 팝업의 경로를 넣어야 한다.

<a href="popup.html" onclick="window.open(this.href, 'popupName', 'width=300,height=200'); return false;"><img src="openWindow.gif"></a>

이럴 경우 사용자가 자신의 의도 대로 팝업창을 새창, 새탭 등으로 열 수 있고 심지어 즐겨 찾기도 할 수 있다.

자바스크립트를 이용한 페이지 이동

웹사이트를 이용하다 보면 폼에서 값을 입력하고 서밋을 하는 순간 "따다다닥" 하는 식으로 클릭을 여러번 한 것과 같은 소리가 나는 경우를 접하게 된다. 프로세스가 여러페이지에 걸쳐서 일어나게 되는데 이 처리를 자바스크립트로 처리를 해서 이러한 현상이 발생을 하게 된다.

<script type="text/javascript">document.location.href="redirection.html";</script>

위와 같이 페이지를 이동 하거나 아래와 같이 <form>을 이용해서 값을 넘기는 경우가 이러한 경우이다.

<form name="login_form">
	<input type="hidden" name="user_id" value="myid" />
	<input type="hidden" name="user_pwd" value="mypassword" />
	<input type="hidden" name="redirect_url" value="http://mysite.com/login/" />
	<input type="hidden" name="somevalue" value="blahblah" />
	...
</form>
<script type="text/javascript">
f = document.forms.login_form;
f.action = "http://login.oursite.com/login/";
...
f.submit();
</script>

심한 경우 아래와 같이 전혀 의미 없는 폼을 이용하기도 한다.

<form method="post" name="sg_form" action="http://www.qubi.com/" target="_top">
</form>
<script> sg_form.submit(); //3</script>

위와 같은 페이지들은 html 문법상 오류가 있는 페이지 들이고 이 때문에 작동이 안 될 수도 있다. <form>엘리먼트나 <script>엘리먼트는 상위에 <body>나 <head>엘리먼트가 있어야 하는데 위와 같은 경우 이러한 엘리먼트가 없기 때문에 html로 해석이 안되어 스크립트가 작동 되지 않거나 값이 넘어가지 않을 수도 있다. 그리고 <form>에 submit <input>이 없기 때문에 자바스크립트로 submit이 일어나지 않을 수도 있다.

이와 같이 페이지를 이동하거나 값을 넘길 필요가 있을 때 자바스크립트에 의존해서 이를 처리하게 되면 클라이언트의 환경에 따라서 동작이 실패할 수 있다. 따라서 이러한 처리는 자바스크립트에서 처리 하지 말고 서버 측에서 http헤더 정보를 이용해서 처리해야 한다.

이러한 중간과정에서의 처리를 서버측에서 모두 처리 하는 것이 가장 바람직 하지만 어쩔 수 없이 사용을 해야할 경우에는 - 그럴 경우가 많지는 않겠지만 기존의 호환성을 위해서 - DTD선언이나 <html> 루트 엘리먼트, <head>, <body>와 같이 필수 엘리먼트들이 존재하는 완결된 페이지를 사용 하도록 하고, 자바스크립트가 작동하지 않는 경우를 위해서 <form>에 submit버튼도 제공을 하고, 결과 메세지도 alert외에 일반 text와 <a>를 이용한 링크를 제공하도록 해야 한다.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr" />
<title>Redirect</title>
</head>
<body>
<script type="text/javascript">
/*
 some processes...
*/
alert('이래저래한 이유로 다시 돌아 갑니다.');
document.location.href="redirection.html";
</script>
<p><a href="redirection.html">이래저래한 이유로 다시 돌아 갑니다.</a></p>
</body>
</html>

charset이 없는 경우 브라우져의 기본 설정으로 alert이 작동하기 때문에 브라우져의 기본 설정이 ko-kr이 아닌 경우 한글이 깨지게 된다. 문서의 mime-type도 text/html인지 확인해야 한다.

<form>에서의 자바스크립트 사용

일반적으로 <form>은 사용자가 입력한 값을 서버측에 전달하는 역할을 하고 그 전달은 <form>의 submit 기능을 통해서 이루어 진다. 이러한 폼을 구현 할 때에 일반적으로 자바스크립트를 사용하는 경우가 많다.

submit

폼은 그 자체적으로 값을 보내는 서밋기능을 제공하고 있다. <input type="submit" />이나 <input type="image" />이 서밋기능을 하는 컨트롤인데 폼의 값 유효성 체크를 하는 과정에서 이러한 폼의 자체적인 서밋기능을 이용하지 않고 자바스크립트로 폼 서밋을 하는 경우가 있다.

<script type="text/javascript">
function submitForm() {
	loginForm.submit();
}
</script>
<form id="loginForm" name="loginForm" action="">
	User Id <input type="text" name="loginId">
	User Password <input type="password" name="loginPassword"><br>
	<img src="login.gif" onclick="submitForm()">
</form>

위와 같은 경우 폼에 서밋기능이 없기 때문에 브라우져에 따라서 script로 서밋이 안되는 경우도 있고 서밋 대신에 이미지가 들어가 있기 때문에 의미적으로도 맞지 않게 된다. 따라서 폼을 제작할 때에는 반드시 서밋기능을 <input>을 이용해서 제공해야 한다.

<form id="loginForm" name="loginForm" action="">
	<p>
		<label for="loginId">User Id</label>
		<input type="text" id="loginId" name="loginId" /><br />
		<label for="loginPassword">User Password</label>
		<input type="password" id="loginPassword" name="loginPassword" />
	</p>
	<p>
		<input type="image" src="login.gif" alt="Login" />
	</p>
</form>

많은 경우 <html>제작 과정에서 서밋을 <img>로 넣는 경우가 있는데 이 경우 이를 그냥 사용하면 안되고 적절한 <input>으로 바꾸어서 사용해야 한다.

validation

클라이언트 측에서 자바스크립트를 이용한 유효성 검증은 <form>의 서밋 이벤트를 캐치하는 방식으로 구현해야 하고 자바스크립트가 폼을 서밋하는 방식을 사용하면 안된다.

<script type="text/javascript">
function submitForm() {
	if (!loginForm.loginId.value) {
		alert("아이디를 넣어주세요.");
		loginForm.loginId.focus();
	} else if (!loginForm.loginPassword.value) {
		alert("비밀번호를 넣어주세요.");
		loginForm.loginPassword.focus();
	} else {
		loginForm.submit();
	}
}
</script>
<form id="loginForm" name="loginForm" action="">
	아이디 <input type="text" name="loginId">
	비밀번호 <input type="password" name="loginPassword"><br>
	<img src="login.gif" onclick="submitForm()">
</form>

위와 같은 경우 자바스크립트만을 이용해서 폼을 서밋하고 있기 때문에 자바스크립트가 없이 HTML만으로는 기능이 작동하지 않는다.

<script type="text/javascript">
function submitForm(formEl) {
	//TrimAll(formEl);

	var errorMessage = null;
	var objFocus = null;

	if (formEl.loginId.value.length == 0) {
		errorMessage = "아이디를 넣어주세요.";
		objFocus = formEl.loginId;
	} else if (formEl.loginPassword.value.length == 0) {
		errorMessage = "비밀번호를 넣어주세요.";
		objFocus = formEl.loginPassword;
	}

	if(errorMessage != null) {
		alert(errorMessage);
		objFocus.focus();
		return false;
	}
	return true;
}
</script>

<form id="loginForm" name="loginForm" action="" onsubmit="return submitForm(this)">
	<label for="loginId">아이디</label> <input type="text" id="loginId" name="loginId" />
	<label for="loginPassword">비밀번호</label> <input type="password" id="loginPassword" name="loginPassword" /><br />
	<input type="image" src="login.gif" alt="Login" />
</form>

이와 같이 onsubmit 이벤트를 이용해서 폼의 유효성을 체크하고 그 결과를 true나 false로 보내줌으로써 폼이 스크립트에 따라서 서밋을 진행하거나 멈출 수 있고, onsubmit 이벤트가 발생하지 않아도 사용자는 폼을 사용할 수 있기 때문에 접근성이 높아지게 된다.

게시판 등에서 기능을 모두 자바스크립트로 하는 경우

게시판에서 페이지의 이동을 자바스크립트만으로 하는 것을 많이 볼 수 있다. 아래와 같이 사용자 인풋이 없는 빈 <form>을 하나 만들고 이것과 자바스크립트를 이용해서 글을 읽거나 페이지를 이동하는 것이다.

<form method="post" name="vars">
	<input type="hidden" name="articleId" value="23" />
	<input type="hidden" name="page" value="3" />
	<input type="hidden" name="keysord" value="" />
	<input type="hidden" name="searchType" value="" />
	<!-- 등등 -->
</form>

...

<a href="javascript:ArticleRead()">글읽기</a>
<a href="javascript:GoList()">리스트 보기</a>

url이 간단해 지고 다루기 쉽다는 이유로 이러한 방식으로 개발을 하는 경우가 많은 것 같은데 절대로 사용해서는 안되는 방식이다.

우선 위와 같이 모든 기능을 자바스크립트를 이용해서 구현을 하게 되면 자바스크립트 오류가 있거나 핸드폰과 같이 자바스크립트가 정상적으로 작동 하지 않는 상황에서는 접근을 할 수 없게 된다. 또한 모든 변수를 post를 통해서 전달하기 때문에 url에 표시가 되지 않고 해당 페이지를 따로 북마크 한다든지 저장을 할 수가 없게된다. 게시판의 경우 해당 게시물로의 접근을 쉽게 해 주어야 하는데 사용자가 url을 알 수 없게 함으로써 접근을 원천적으로 막게 된다.

자바스크립트를 이용하지 않고도 <a>와 url만으로도 작동 가능한 페이지를 만들고 QueryString을 효율적으로 다루는 방법을 모색하여 개발을 진행하는 것이 가장 좋은 방법이다.

마치며

본인이 웹사이트 개발을 하면서 접할 수 있었던 몇몇 잘못된 자바스크립트 사용 예를 적어 보았다. 그런데 놀라운 것은 이러한 개발 방식을 초보부터 어느정도 경력이 된 개발자들 까지 아무런 고민 없이 사용하고 있다는 것이다. 책이 잘못된 것인지 교육이 잘못 된 것인지 정확히 근원을 알 수는 없지만 많은 개발자들이 웹이 가지고 있는 기본적은 특성을 무시한채 잘못된 방법을 이용하여 개발을 하고 있는 것이 사실이다. 그리고 또 초보 개발자들은 HTML을 잘 모르기 때문에 이러한 개발 방식을 아무 고민 없이 그냥 받아들이고 있는 것이 사실이다.

브라우저 접근성을 가장 크게 낮추고 있는 것이 바로 이 잘못된 자바스크립트의 사용이다. 부디 조금이라도 많은 개발자들이 링크에 기초한 웹의 특성을 이해하고 접근성 높은 웹사이트, 웹 어플리케이션을 구축 하기를 바라는 바이다.

다운로드 : accessible-javascript.pdf(pdf 225KB)

Posted by 1010
반응형
출처 : http://naradesign.net/wiki/UI_개발자를_위한_북마크
출처 : http://naradesign.net/wiki/UI_개발자를_위한_북마크

뉴스

드림위버

모바일

블로그

웹 표준

웹 접근성

자바스크립트

IT Trends

User Experience


블로그 허브

사용자 맞춤형 웹 서비스

사전

웹 디자인

사진

아이콘

웹 브라우저

웹 브라우저들

웹 브라우저 에뮬레이터

모바일 웹 브라우저 에뮬레이터

웹 브라우저 테스트

웹 브라우저 호환성 문제

웹 브라우저 확장

웹 사용성

웹 성능 분석

웹 어플리케이션

웹 접근성

지침

기법


웹 표준

유니버설 디자인

통계

CSS

CSS Framework

CSS Reference

CSS Standards

CSS Vendor Extensions

CSS3

Flash

Fonts

HTML/XHTML

HTML5

Javascript

jQuery

User Interface 개발

Posted by 1010
반응형
근래 들어 NHN 웹표준화팀의 NULI 사이트가 여기저기서 소개가 되고 있네요. 좋든 싫든 NHN이라는 기업이 갖고 있는 폐쇄적인 이미지와 달리 자신들의 지식과 정보를 '널리' 알리고 공유하고 싶다는 박태준 팀장님과 팀원들의 의지가 담겨 있는 멋진 UI 가이드라인 사이트라고 생각합니다. NULI 외에도 다음 다음의 UI개발팀이 운영하고 있는 가이드라인과 모질라, 오페라 등이 운영하고 있는 사이트들이 있어서 간단히 소개해 드립니다.

NULI - 널리 공유하는 웹 표준화 가이드

최근에 가장 많이 알려진 곳이며, 네이버를 중심으로 NHN의 웹서비스 UI관련 가이드를 꼼꼼히 정리하고 있는 곳입니다. HTML, CSS를 비롯한 기본적인 가이드에서부터 웹접근성에 대한 연구 결과 등을 공개하고 있어 별도의 연구나 분석이 쉽지 않은 회사 또는 개인에게 좋은 정보를 제공하고 있습니다. 최근에 스크린리더(센스리더)에 대한 리뷰는 정말 도움이 되더군요.

Daum UIDev Guideline

NULI만큼 알려지지는 않았지만 다음에도 UI개발팀에서 운영되고 있는 가이드라인이 있습니다. NULI처럼 NHN 웹서비스를 위해 조사하고 연구된 내용을 공유하기 위한 목적은 아니어서 그런지 자체 웹서비스를 위한 참고 가이드의 성격이 강합니다. 하지만 사내 웹표준 가이드 등을 만들 생각이 있다면 다음의 UI가이드가 도움이 될 것 같습니다. 다음의 UI개발자 블로그는 NULI와 달리 따로 운영되고 있네요. 이곳에서도 종종 좋은 정보들이 올라오고 있습니다.

MDC - Mozilla Developer Center

모질라 재단이 운영하고 있는 개발자 센터입니다. 기술(Technologies) 카테고리에서 HTML, CSS, XML, AJAX, DOM, RSS 등 많은 기술 문서를 열람해 보실 수 있습니다. 회원가입을 하시면 직접 글을 올릴 수도 있습니다.

Dev.Opera

오페라 소프트웨어의 개발자 센터입니다. 외견상 MDC와 유사하며, Articles 카테고리를 통해서 HTML, CSS, Javascript 등에 대한 글을 열람해 보실 수 있습니다. 최근에 개설된 Web Standards Curriculum 은 정말 좋습니다! (제가 활동중인 스터디그룹에서도 WSC를 이용해서 공부를 하고 있습니다.) Dev.Opera 역시 MDC와 마찬가지로 회원 가입을 하면 저자가 되어서 직접 글을 올릴 수 있습니다. 최근의 내용을 봐서는 오페라쪽이 좀 더 활발한 것 같습니다.

Aptana Reference Guides

Aptana가 제작 운여하고 있는 레퍼런스입니다. 역시 HTML, CSS, Javascript 를 다루며, Jaxer라는 자사 서비스 가이드를 포함하고 있습니다. 개인적으로 자주 찾는 곳인데 각각의 브라우저별 지원 현황이 잘 정리되어 있어서 보기 좋습니다. 별도의 레퍼런스 북이 없다면 정말 괜찮은 사이트입니다.

웹표준을 탐험하는 히치하이커를 위한 지침서

더글러스 애덤스가 쓴 '은하수를 여행하는 히치하이커를 위한 안내서'를 패러디한 제목의 웹표준 가이드 사이트입니다. ELEX님이 작성하신 것으로 초기에는 PDF 문서로 배포되다가 최근에 스프링노트를 통해서 가이드라인 사이트를 구축하신 것 같습니다. 기부금을 내시면 ELEX님께 도움을 드릴 수도 있을것 같군요! 포털사가 만든 가이드가 복잡해 보이고, 영어로 된 가이드가 영 읽기 힘들다면 ELEX님의 가이드를 한번 추천해 드립니다. 꼼꼼하게 잘 정리하시고 운영하는 열정이 대단하신것 같습니다.


이 밖에도 W3C Schools이나 Max Design, Yahoo! UI Library와 같이 이미 많이 알려진 레퍼런스, 가이드 사이트도 있습니다. 찾아보면 더 많은 곳이 있을 것이고, 카페(하코사와 같은)나 사이트(CDK같은) 등 소규모로 제작 운영되는 레퍼런스와 가이드도 알찬 것들이 많을 것이라고 생각해 봅니다. 또한 대부분의 회사가 자체 가이드라인을 가지고 있거나 제작하고 있는 것으로 알고 있습니다. 아직 준비되어 있지 않다면 직접 한번 만들어 보시는 것도 좋은 공부가 되지 않을까 싶습니다. 그런 의미에서 저 역시 틈틈히 '마크업 가이드라인'을 만들어 보고 있습니다. 게을른 탓에 지지부진하긴 하지만 자신의 작업 스타일이라든가 알고 있는 지식을 정리해볼 수 있는 좋은 기회라고 생각됩니다.


출처 : http://www.pageoff.net/828
Posted by 1010
04.Anddoid2010. 11. 19. 13:35
반응형
Posted by 1010
90.개발관련문서2010. 11. 15. 12:51
반응형

1) Windows XP USB쓰기관리

MS Windows XP Service Pack 2에서 USB Bus 제어를 위한 기능이 추가되었음.

USB 장치 중 대용량 저장장치로 인식되는 장치에 대해 처리하는 방식을 사용함.
 
[설정 방법] 
위치 : HKEY_LOCAL_MACHINE\SystemCurrent\ControlSet\Control\StorageDevicePolicies
값 : WriteProtect
종류 : DWORD
데이터 : 0 -> 사용 안 함
            1 -> 사용 함
 
사용함으로 설정하면 USB Bus를 통한 쓰기를 조작할수 있다. 

 


2) Windows Vista USB쓰기관리

XP의 후속작인 Vista역시 이기능을 제공한다. 하지만 레지스트리 위치가 다르다.

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced]

"EncryptionContextMenu"=dword:00000001
 

00000000 이면 해체

 

 

3) 독립적인 S/W를 사용하는 USB쓰기 관리

 

S/W를 이용하는 방법은 크게 2가지

 ① 프로세스를 기동시키는 법

 ② 서비스에 등재하는 법


출처 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=6127&MAEULNO=769&no=26326&page=11

Posted by 1010
90.개발관련문서2010. 11. 12. 17:00
반응형
Posted by 1010
91..개발관련프로그램2010. 11. 12. 16:15
반응형
ManicTime download includes Standard (free) and Professional edition.

It also includes a 15 day free trial to preview Professional edition. After the trial ends you can revert back to a Standard (free) edition or purchase a licence key and use Professional edition.
Available for Windows XP SP3 or newer
ManicTime v1.4.7 (10/19/2010)
Recommended download
ManicTime.exe (5.4 MB)
Other downloads
* these versions won't check for .Net framework 3.5 SP1 so make sure it is installed before you run ManicTime.



Auto tracking of computer usage

Manictime sits in the background and records your activities, so you can just forget it is there and focus on your work. When you are finished you can use collected data to accurately keep track of your time.

Keep track of your work hours

After you have finished working, you can use MT to keep track of your hours. That means no more "punch-clock" like software, where you always forget to start or stop the clock. Just sit back and do your work. After you are finished, you can easily use collected data to accurately keep track of your time.

Simple and intuitive UI

During the course of the day average user can switch back and forth between applications more than a 1000 times, which means ManicTime gathers a lot of data. Using our timeline technology Manictime presents the data in an easy to understand way. You can drag on the timelines to select time or just mouse over to see hints about underlying data.

Local storage

Gathered data can sometimes be sensitive and you don't want it sent over the wire and shared. That is why all the data Manictime gathers is stored locally on your computer and you can delete it any time you want. Having a local database also enables you to use ManicTime offline, without an Internet connection.

Powerful statistics

See which applications you use the most or on which web sites you spend the most time. Also easily figure out how much time you spent working on projects to accurately bill your clients or just keep track of your work.


Posted by 1010
90.개발관련문서2010. 11. 2. 13:29
반응형
$ telnet www.naver.com 80
Connected to www.xxxx.xxxx.
Escape character is '^]'.
GET /index.html HTTP/1.0

Posted by 1010
반응형
Posted by 1010
56. Eclipse Etc.../Eclipse2010. 10. 29. 11:38
반응형

자바프로그램에서 propeties 라는 파일이 있습니다. classpath에 위치하면서 설정이나 다국어 처리를 위한 파일로 많이 씁니다.

주의할 점은 한글을 써 놓으면 그대로 쓰지 못합니다. 유니코드로 바꿔줘야하는데, %JAVA_HOME%\bin\native2ascii.exe 프로그램을 쓰고는 합니다.



이렇게 파일의 한글을 알아볼 수 없게 되어버립니다. 이쯤되면 한 마디 나오죠. "어쩌라고"

이클립스에서 프로퍼티 편집을 쉽게 하도록 플러그인이 일본에서 만들어졌습니다.
구글에서 propedit 하면 처음에 나오는 사이트입니다.
http://propedit.sourceforge.jp/index_en.html
이클립스에서 바로 플러그인을 설치할 수 있습니다. 업데이트 주소가 필요한데, 사이트에서 다음과 같은 주소를 찾을 수 있습니다.
http://propedit.sourceforge.jp/eclipse/updates/

이 주소를 복사하고 다음과 같이 이클립스 메뉴에서 Help > Software Updates > Find and Install... 을 선택합니다.


두 번째 메뉴을 선택합니다. Search for new features to install


참고로 첫 번째 메뉴 Search for updates of the currently installed features 는 현재 이클립스에 있는 컴포넌트들의 업데이트들을 찾아서 설치하는 메뉴입니다.

우측의 New Remote Site... 버튼을 클릭하고 Name에는 propedit , 아래 URL에는 아까 복사한 업데이트 URL을 붙여넣기 합니다. 그리고 아래쪽의 Finish 버튼을 누릅니다.

이후 Updaes 타이틀이 붙어있는 창이 뜨고 Search Results가 나옵니다. propedit 를 펼쳐보면 항목이 3개 있는데, 가운데 플러그인은 3.3에서는 동작하지 않아서 체크하지 않았습니다. 세 번째 플러그인은 vi 키보드 편집처럼 에디터를 쓸 수 있도록 해주는 것입니다. 같이 설치하도록 하겠습니다. 잘도 만드네요.

설치를 마치면 이클립스를 재시작합니다.

프로퍼티 파일의 아이콘이 바뀝니다. 오른 버튼으로 Open With라는 메뉴를 보면 가능한 편집기 리스트가 나옵니다. 첫 번째 Properties File Editor는 이클립스 내장 에디터입니다. 맨 처음 보았던 것이죠. 두 번째 있는 PropertiesEditor가 새로 설치한 플러그인에서 지원하는 에디터입니다. 아이콘이 다름을 알 수 있습니다. 이것으로 열어보겠습니다.

에디터 탭을 옮겨서 두 에디터를 비교하면 다음과 같습니다. 에디터 탭의 아이콘으로 구분이 가능합니다.


같은 파일이 편집기에 따라서 다르게 보임을 알 수 있습니다. 편집은 가독성있는 문자코드로 하고 저장만 유니코드로 자동변환되어 저장됩니다.

잘 쓰시기 바랍니다.
오늘은 요기까지입니다.



출처 : http://www.okjsp.pe.kr/seq/104351

Posted by 1010
06.Ajax2010. 10. 29. 11:35
반응형

AJAX Solutions can be used by web developers to create amazing applications. Dozens of projects, even Gmail, made with AJAX provide new interactivity for applications that can have enhanced user functionality. Using AJAX, better, faster, more flexible web solutions are available. AJAX is the first step toward web applications of the future.

What exactly is AJAX? AJAX is an acronym for Asynchronous JavaScript and XML, and though some think it’s a new programming language, it’s really not. AJAX is basically XHTML, DOM, CSS, XML, XMLHttpRequest used together to do one thing, which is to improve the user-server interaction.
• To better understand AJAX, check out some articles about it.
• To learn the AJAX basics, look up some tutorials.
• To learn about CSS, look up some articles and tutorials.

Remember: Google is your friend!
Contained in this article are 80+ AJAX scripts and resources you should have at your side while designing your own applications. Auto-completion, instant field editing, menus, calendars, interactive elements, visual effects, animation, basic Javascript, as well as an extensive developer’s suite are contained here for a useful toolbox, so that you don’t have to go through a huge list of bookmarks.

Auto Complete Scripts

1. AJAX AutoSuggest

2. AJAX Autocompleter / script.aculo.us library

3. AJAX AutoCompleter

4. Ajax autosuggest/autocomplete from database

5. Ajax dynamic list

Instant Editor Scripts

6. AJAX inline text edit 2.0

7. AJAX & CSS Flickr-like Editing Fields

8. AJAX Instant Edit

Tab and Menu Scripts

9. 14 Tab-Based Interface Techniques

10. AJAX Accordion Navigation

11. AJAX Dialogs, Menus, Grids, Trees and Views

12. AJAX Tab Module - Closeable Implementation

13. Ajax Tabs Content

14. MooTabs - Tiny tab class for MooTools

15. Dynamically loaded articles

Calendar/Datetime Scripts

16. AJAX Datetime Toolbocks - Intuitive Date Input Selection

17. AJAX Calendars

Interactive Elements Scripts

18. AJAX Floating Windows

19. AJAX Star Rating Bar

20. Ajax poller

Developer’s Suite Scripts

21. AJAX HistoryManager, Pagination

22. AJAX Login System Demo

23. AJAX image preloader

24. AJAX Tooltips: Nice Titles revised | Blog | 1976design.com

25. 40+ Tooltips Scripts With AJAX, JavaScript & CSS | Smashing Magazine

26. AJAX Web Controls

27. AJAX syntaxhighlighter

28. Transparent Message

29. ModalBox — An easy way to create popups and wizards

30. Chained select boxes

31. Fly to basket

32. AJAX Key Events Signal

33. Disable form submit on enter keypress

Enhanced Solutions

34. AJAX Instant Completion

35. Novemberborn: Event Cache

36. Altering CSS Class Attributes with JavaScript

37. Select Some Checkboxes JavaScript Function

38. AJAX Emprise Charts

39. amCharts: customizable flash Pie & Donut chart

40. PJ Hyett : The Lightbox Effect without Lightbox

Forms

41. AJAX Upload Form

42. An AJAX contact form

43. AJAX contact form

44. Ajax.Form

45. Ajax form validation

46. Really easy field validation

47. AJAX fValidate

48. Ajax newsletter form

49. wForms

Tables and Grids

50. Data Grids with AJAX, DHTML and JavaScript | Smashing Magazine

51. Grid3 Example

52. AJAX Table Sort Script (revisited)

53. AJAX Sortable Tables

54. AJAX TableKit

Showcases, Galleries, and Lightbox Scripts

55. 30 Scripts For Galleries, Slideshows and Lightboxes | Smashing Magazine

56. AJAX LightBox, Sexy Box, Thick Box

57. AJAX Lightbox JS

58. AJAX Unobtrusive Popup - GreyBox

59. SmoothGallery: Mootools Mojo for Images | Full gallery

60. AJAX Libraries and Frameworks

Animation and Visual Effects Scripts

61. How to Create Digg Comment Style Sliding DIVs with Javascript and CSS

62. How to Create a Collapsible DIV with Javascript and CSS

63. How to Create an Animated, Sliding, Collapsible DIV with Javascript and CSS

64. AJAX Shopcart

65. Draggable content

66. Dragable RSS boxes

67. AJAX Pull Down Effect

68. AJAX Animation Effects

69. Combination Effects in scriptaculous wiki

70. AJAX Motion Transition

Useful Javascript Scripts

71. 9 Javascript(s) you better not miss!

72. Top 10 custom JavaScript functions of all time

73. Hyperdisc Materials: JavaScript: Top 10: Automatic Breadcrumb Trail

74. JavaScript: Top 10 Most Useful JavaScripts

75. My Favorite Javascripts for Designers: Blakems.com ?

More Resources and Galleries

76. Max Kiesler - mHub : Ajax and rails examples & how-to’s

77. Ajax Resources

78. DZone Snippets: Store, sort and share source code, with tag goodness

Posted by 1010
반응형
Posted by 1010
90.개발관련문서2010. 10. 29. 11:25
반응형
Posted by 1010
02.Oracle/DataBase2010. 10. 29. 11:17
반응형
Posted by 1010
반응형
/^[a-z0-9_]{4,20}$/;
Posted by 1010
01.JAVA/Java2010. 10. 25. 17:33
반응형

public class Tuning {
 public static void main(String[] args) {
 
  // 1.
  String s = new String();
  long start = System.currentTimeMillis();
  long stop = 0;
  for(int i =0 ; i < 10000 ; i++){
   s += "a";
   stop = System.currentTimeMillis();
  }
  System.out.println("String : "+(stop - start)+"초");
 
  // 2.
  StringBuffer sb = new StringBuffer();
  long start2 = System.currentTimeMillis();
  long stop2 = 0;
  for(int i =0 ; i < 10000 ; i++){
   sb.append("a");
   stop2 = System.currentTimeMillis();
  }
  System.out.println("String : "+(stop2 - start2)+"초");
 
 }
}

사용자 삽입 이미지








Posted by 1010
90.개발관련문서2010. 10. 22. 17:44
반응형

출처 : http://www.msaccess.co.kr/newpage/tech/access/access_2.php#1

아래의 내용은
15년 가량 IT를 경험한 컨설턴트가 평가한 것으로 PowerBuilder, Visual Basic, COBOL, Oracle, SQL-SERVER, MySQL 등 다양한 종류의 프로그램언어와 데이터베이스를 경험한 이후에 기술된 내용입니다.

 

목차 

1.    가장 강력한 Component형 개발 툴

2.    편리한 Database Bound형태의 개발 툴

3.    엔진이 필요 없는 Server 혹인 Client형 데이터베이스

4.    최고의 Rapid 개발 툴

5.    QBE를 이용하여 초보자도 사용 가능한 강력한 SQL언어 제작기능

6.    어떠한 자료 형태도 관계형 데이터베이스처럼 연결(Relation Join) 가능

7.    ODBC를 이용한 모든 데이터베이스의 연결 및 통합

8.    calable개발 툴

9.    Data Migration을 위한 통합형 데이터베이스

10.   Win32 API 및 ActiveX 와 100% 호환

11.  Engine이 필요 없는 관계형 데이터베이스

12.  오피스 제품과의 완벽한 자료호환성

13.  데이터베이스와 프로그램을 통합한 새로운 개발 툴

14.  VBA언어 사용

15.  Application OLE기능

16.  Setup 및 Distribution의 자유로움

17.  Xml 지원 및 ADO, DAO, ODBC등 다양한 형태의 자료연결 기능

18.  개발자를 위한 강력한 마법사 기능

19.  데이터베이스 분석 툴 및 Documentation 기능

20.  준비된 내장함수

21.  사용자 중심의 표현식 작성기(Expression Builder)

22.  전산실이나 급하게 개발해야 하는 프로그램에 용이

23.  중소기업을 위한 진정한 개발 툴이 존재 하는가요?

24.  액세스 !! 만남 자체만으로도 여러분에게 많은 신선함을 약속할 수 있습니다

       

        1.       가장 강력한 Component형 개발 툴

       Form, Table, Query, Report, Module

자주 개발하는 프로그램에서 이전에 사용한 프로그램을 재사용하는 것은 프로젝트에 있어서 아주 중요한 문제입니다. 보안 및 사용자 계정, 네트워크 구성에 따른 모듈 등이나, 기본적인 자료를 처리하는 반복적인 업무의 프로그램 개발은 생산성을 떨어뜨리는 원인이 됩니다.

아무리 잘 만든 프로그램 logic이라 하더라도 다른 프로그램을 개발할 경우에는 이미 잘 만들어진 ActiveX 컨트롤이 아닌 다음에는 반드시 일부는 재개발 해야 하는 것을 피할 수 없습니다.  이럴 때 가장 중요한 것이 이전에 만들어 놓은 폼, 보고서, 스크립트 등의 일부라도 쉽게 가져올 수 있게 하는 것입니다.

이러한 면에서 액세스는 두 개의 액세스화면을 열어 놓고 마우스로  Drag & Drop만을 하면 어떠한 형태의 객체(Form, Table.)든 관계없이 객체를 주고 받을 수 있는 재사용성이 뛰어난 개발툴 입니다.

2.       편리한 Database Bound형태의 개발 툴

    Bound형태란 일반 프로그래밍 툴에 있어서는 생소할 수 있습니다. 여기에 해당하는 것은 3rd Party툴 형태로 지원되는 ActiveX DLL, Component형태로 지원되는 라이브러리 등이 있습니다. Bound폼이나, Bound Report에는 이러한 여러 종류의 라이브러리 중 데이터에 관한 ActiveX형태의 컨트롤이 폼이나 Report자체에 들어 있다고 보면 됩니다.

      Form

                                                물론 액세스의 Bound폼에는 데이터를 가져오는 ActiveX는 어디에도 보이지 않습니다. 폼 자체가 ActiveX와 같은 형태일 수 있습니다.

                                               그러나 이 폼은 DataGrid 컨트롤과 같은 형태와는 비교도 안 되는 유연함을 보여주면서도, 개발자 스스로가 VB  와 같이 Unbound 형태로 개발해도 아무런 문제가 없습니다.

                                                액세스의 Bound폼은 5가지 형태로 제공됩니다. 5가지 형태의 폼은 불과 1~3초 만에 정교한 폼을 만들어 주나, Visual Basic이나 Delphi 등으로 만들면 최소 30분에서 1 이상 소요됩니다. Report 뿐만 아니라 폼에서도 액세스는 Bound 형태이면서도 일반 ActiveX처럼 배포에 대한 불편함이나 Licence에 대한 부담이 없습니다. 또한, 이러한 ActiveX조차도 Windows자체가 지원하는 라이브러리 내에 존재하기 때문에 속도가 상당히 빠릅니다.

       Report

                                              일반적으로 가장 많이 사용되는 Report툴은 Segate사의 Crystal Report입니다. 필자도 대형 프로젝트를 통해 Crystal Report2년 가까이 꾸준히 사용해 보았기 때문에 개발의 편리상이나 개발 속도적인 면, 보고서의 모양 등에 있어서 최고의 툴로 평가해도 과하지 않다고 생각합니다.

                                              그러나 액세스가 가지고 있는 보고서 기능은 이 Crystal Report에 못지 않은 많은 기능을 가지고 있습니다. 오히려 Crystal Report가 가지고 있지 않은 유용한 형태의 많은 보고서를 제공합니다. 더욱이 Bound Unbound형태를 모두 제공하기 때문에 자연스럽고 고급스런 보고서를 작성할 수 있습니다.

3.       엔진이 필요 없는 Server 혹인 Client형 데이터베이스

       액세스는 엔진이 없는 상태에서도 데이터베이스로 만족한다

                                               액세스는 모든 자료형태로 표현되는 Text파일이나  Excel, Dbase ISAM파일, Paradox 등 기타 많은 자료를 링크하여 관계형 데이터베이스처럼 활용가능 할 뿐만 아니라, 서로 다른 자료 형태를 관계형으로 연결 할 수 있습니다.

상상할 수 없었던 형태, 예를 들면 서버의 Oracle 데이터베이스와 일반 PC에 존재하는 Text데이터나  Excel 같은 형태의 자료를 서로 관계형 데이터베이스로서 Join하는 작업을 쉽게 만들어 줍니다. 또한 이렇게 연결된 자료들을 아무런 작업 없이 그대로 SQL에 사용 가능한 방법을 제공합니다

       Client/Server의 대형프로젝트에 필수적인 데이터베이스

진정한 형태의  Client/Server프로그램은 Client에 데이터베이스를 둠으로써 전체적인 프로그램을 효율적으로 운영하기 위한 방법의 제안 이었습니다.

                                                 그러나 국내에서 이러한 형태의 Client/Server프로그램을 구현하는 방법은 서버에 Oracle과 같은 대형 데이터베이스를 두고 Client에는 Sql-Server같은 데이테베이스를 둠으로써 Client자체가 일반 PC가 아닌 서버급의 고비용을 발생하게 하는 형태로 발전하게 되었습니다.

                                                진정한 Client/Server응용 프로그램은 Client PC에 데이터베이스를 둠으로써 데이터베이스 서버의 가격을 낮추고 성능 저하의 원인이 되는 데이터의 집중현상을 줄이기 위한 방법이어야 합니다. 즉, 일반 PC에 데이터베이스를 둠으로써 가장 효과적인 시스템구축 방법을 찾기 위한 수단이 되는 것입니다.

                                                예를 들어, 한 회사에서 1,000건이 넘는 상품코드를 사용할 경우 하나의 재고관리 프로그램에서 조회하는 상품코드는 프로그램이 실행되는 동안에는 계속해서 상품코드를 조회합니다. 매번 프로그램을 실행할 때마다 이 상품코드를 서버에서 가져온다면 서버자체의 물리적 성능이나 데이터베이스의 성능이 상당히 월등해야 합니다. 그러나 서버에 존재하는 상품코드의 복사본을 Client에 가지고 있고 이 상품코드를 서버에서 가져오지 않고 Client PC 즉, 현재 프로그램이 실행되고 있는 PC에 보관하고 사용한다면 아주 효율적인 시스템이 구축됩니다.

 액세스는 Client(PC)에 엔진이 필요없는 관계형 데이터베이스를 제공함으로써 Client/Server에 전형적인 시스템 구축을 도와 줍니다.

최근에 메신저()형태의 개인용 응용프로그램이 많이 배포되고 있습니다. 이러한 대부분의 개인용 자료를 보관(메일, 주소록, 일정관리)하는 대부분의 프로그램이 이 액세스 DB를 사용하고 있습니다. 확장자를  MDB가 아닌 다른 형태로 Rename했을 뿐 액세스 데이터베이스를 그대로 사용하고 있습니다.

4.       최고의 Rapid 개발툴

       Form, Report 제작 5 ~ 30

액세스는 Bound 형태의 폼이나 보고서를 제공하기 때문에 일반 개발 툴에 비하여 상당히 빠른 개발도구 입니다.

설계가 끝난 상태에서 프로그램을 개발할 경우라면 Visual Basic이나 Delphi, PowerBuilder등의 개발 기간이 5개월 정도라고 한다면, 액세스는 최대 1개월 이면 충분할 정도의 개발환경 및 도구를 제공합니다.

       QBF

액세스는 많은 변수로부터 자유로울 수 있습니다.

액세스는 보고서 및 폼에 있는 컨트롤이나 필드의 값을 직접 참조할 수 있는 기능을 제공하며, 이러한 형태의 값에 대한 참조를 SQL이나 모든 함수에서 사용 가능하므로 개발생산성 측면에서나 프로그램 자체를 이해하는데 있어서도 많은 도움이 됩니다.

5.       QBE를 이용하여 초보자도 사용가능한 강력한 SQL언어 제작기능

      QBE를 이용한 빠른 SQL작성(GUI환경)

액세스는 거의 최초로 제공되었던 GUI형태의 SQL Builder를 제공합니다

액세스가 처음 나왔던 91년 경에 이미 GUI형태의 SQL Builder를 제공했기 때문에 10년 이상이 흐른 현재의 Builder는 더욱 진보된 형태로 SQL을 잘 모르거나, 기억하기 어려운 Syntax등을 자동으로 생성해 줍니다.

       SQL언어 내부에 내장함수 사용이 가능하다

액세스의  SQL은 다양한 데이터베이스를 지원할 뿐만 아니라 액세스 자체에서 포함하고 있는 내장함수나, 심지어는 사용자가 만든 함수 등을 SQL에 포함하여 사용할 수 있습니다. 이러한 함수 조차도 액세스가 해석하여 다양한 데이터베이스에 사용해도 전혀 문제 없이 실행할 수 있는 강력한 SQL을 제공합니다.

      RPC, Stored Procedure사용 가능

오라클이나 대형 데이터베이스에서 제공하는 RPC, Stored Procedure를 액세스에서 만들 수 있을 뿐만 아니라 만들어진 RPC, Stored Procedure를 실행 할 수 있습니다

       Crosstab Query

직접 구현하려면 최소 50줄 이상이라야 가능한 SQL명령을 SQL Builder를 통하여 쉽게 구현합니다

▶    Crosstab Query는 기간별 영업실적, 지역별 영업실적 담당자별 영업실적 등..행의 값이 열로, 혹은 열의 값이 행으로 이동하여 통계를 구축하는 등의 어려운 SQL문장을 만들어 주는 마법사를 이용하여 불과 몇 초 만에 어느 정도 수준의 SQL사용자도 만들기 어려운 Crosstab Query를 구현해 줍니다.

        사용자 정의 함수 사용

일반 데이터베이스에서 제공하는 대부분의 SQL용 함수를 제공합니다.

액세스 내부에 포함된 모든 내장함수와 사용자 정의 함수를 SQL에 포함하여 실행할 수 있습니다.

       Query를 이용한 View Table작성

액세스는 액세스자체에 SQL문을 레코드셋처럼 취급할 수 있으므로 SQL을 만들어 이렇게 만들어진 SQL자체를 쿼리라는 객체형태로 마치 서버의 View테이블처럼 만들 수 있습니다.

6.       어떠한 자료 형태도 관계형 데이터베이스처럼 연결(Relation Join) 가능

       Text, Excel, Dbase 간의 연결(Relation Join) 가능

마이크로소프트가 배포하는 오피스 내부에는 Power point, Word, Excel, Visio, Frontpage, InfoPath, Outlook등이 존재하고 있으며 이러한 응용프로그램이 사용하는 모든 자료를 액세스로 주고 받을 수 있습니다

       Text, Excel, Dbase Oracle, SQL-SERVER, ORACLE간의 연결(Relation Join) 가능

오피스 내부에 존재하는 모든 자료의 형태나 일반적인 ISAM파일, DBASE등의 자료와 대형 데이터베이스와도 관계형 연결(Relational Join)이 가능합니다

7.       ODBC를 이용한 모든 데이터베이스의 연결 및 통합

       Local Database에 이 기종 및 서로 다른 Database 통합연결

현재 존재하는 거의 모든 형태의 자료와 서버에 존재하는 모든 형태의 데이터베이스와 연결 가능합니다.

이러한 연결이라는 것은 단순한 링크가 아니라 액세스 내부에서는 동일한 데이터베이스처럼 취급되기 때문에 대부분의 SQL문의 사용이 가능합니다

       Remote Database에 이 기종 및 서로 다른 Database 통합연결

원격지에 있는 데이터베이스끼리도 odbc를 통하여 연결하고 또한 Client에 존재하는 일반 ISAM 형태의 자료를 동시에 연결할 수 있습니다

액세스는 동시에 이 기종의 데이터베이스와 연결할 뿐만 아니라 동시에 EXCEL이나 ISAM 등 모든 자료를 연결할 수 있습니다. 이러한 연결은 사용자에게 데이터의 종류에 관계없이 서로간에 자료를 주고 받거나 프로그램을 하는데 있어서 대단한 편리성과 유연성을 제공합니다

8.       Scalable개발툴

      From Desktop To Enterprise level Client/Server 개발 툴

PC에서 운영되는 작은 프로그램에서부터 대형 프로젝트에 이르기 까지 어떠한 환경에서도 운영 가능한 개발 툴입니다

       Excellent Group Business Tool

특히 부서단위나, 지역단위의 프로그램이나, 이러한 형태로 개발된 데이터베이스를 통합하는 형태의 프로젝트에 있어서는 더욱 뛰어난 기능을 발휘합니다

       Standalone 개발 툴

액세스는 워낙 빠른 시간에 개발 가능한 툴이기 때문에 갑작스런 프로젝트나 실험용 프로그램, 통계 프로그램 등 한번 사용하고 버리는 형태의 프로그램에는 생산성 높은 많은 기능을 제공합니다.

      Frontend To Backend 데이터베이스

이미 구축된 ERP나 다른 응용프로그램에 존재하는 모든 데이터를 쉽게 접근하여 새로운 프로그램을 개발한다든가 혹은     이렇게 개발된 프로그램으로 기존의 ERP데이터에 자료를 검색, 입력, 수정하는 등의 형태의 개발이 뛰어납니다.

9.       Data Migration을 위한 통합형 데이터베이스

       Upsizing, Downsizing

모든 형태의 자료나 관계형 데이터베이스가 연결 가능하기 때문에 프로그램의 규모나 데이터베이스를 서버로 올린다거나 내릴 경우에는 최대의 효과 및 편의를 제공합니다.

10.   Win32 API ActiveX 100% 호환

일반적인 프로그램 개발 툴에서 사용하는 3rd Party에서 제공하는 모든 종류의 라이브러리 사용을 지원합니다 (ActiveX Control, DLL, Class 라이브러리).

11.   Engine이 필요 없는 관계형 데이터베이스

       액세스나 오피스가 설치되어 있지 않더라도 액세스파일 자체만 가지고도 데이터베이스로서의 모든 기능이 지원됩니다.

12.   오피스 제품과의 완벽한 자료 호환성

       Excel TO Access

       MS Word TO Access

      Visio TO Access

13.   데이터베이스와 프로그램을 통합한 새로운 개발 툴

       프로그램 자체도 R-DB형태로 존재

       프로그램과 DB를 분리하여 개발 가능

      프로그램과 DB를 통합하여 개발 가능

14.   VBA언어 사용

       Visual Basic For Application

15.    Application OLE기능

액세스로 Excel이나 Word의 응용프로그램을 끌어 들여 사용 가능합니다

      Excel Application

       Word Application

16.   Setup Distribution의 자유로움

사실상 모든 개발 툴에 있어서의 최종적인 문제는 완성된 프로그램의 배포에 있습니다. 이러한 배포는 Install shield Setup Package형태로 배포하게 되는데, 실제 많은 응용프로그램 설치를 자세히 살펴보면 최소한 20~60여 개에 가까운 많은 파일이 설치 됩니다. 따라서 이렇게 많이 설치되는 파일이 어디에 존재하는지, 또한 현재 설치되는 OS에 적합한지를 판단하기 이전에 모든 설치가 마무리 되는 것을 생각해 보면 새로운 프로그램을 윈도우에 설치한다는 자체가 어느 정도의 모험이 될 수 있습니다.

더 심각한 문제는 설치한 프로그램을 제거할 경우는 아예 설치된 파일을 모르기 때문에 완벽한 제거는 포기하게 된다는 것입니다.

그러나 액세스는 단 두 개의 파일만 설치하면 됩니다. 물론 액세스를 실행하기 위한 msaccess.exe 파일을 제외하면 개발된 프로그램.mdb만을 배포하면 됩니다.

물론 배포될 컴퓨터에 오피스가 설치되어 있다는 전제가 있어야 합니다.

      MS Windows Office의 라이브러리의 호환성

       하나의 파일만으로 모든 프로그램의 배포

17.   Xml 지원 및 ADO, DAO, ODBC등 다양한 형태의 자료 연결 기능

최근에 각광을 받고 있는 XML형태의 자료를 연결하거나 혹은 원하는 자료를 내보낼 수 있는 기능이 있습니다.

       Xml Import, Export, Linking

       ADO, DAO, RDO

18.   개발자를 위한 강력한 마법사 기능

프로그램에 사용되는 모든 객체에 대한 강력한 마법사 기능으로 프로그램개발에 필요한 모든 작업을 기본적으로 제공하는 마법사를 통하여 최소 30%에서 100%에 이르는 완성도로 모든 객체를 만들어 줍니다.

       Form

       Query

      Report

       Table

        Macro

        Button Wizard

19.   데이터베이스 분석 툴 및 Documentation 기능

프로젝트 시작 시 혹은 종료 시 만들어야 할 프로젝트 문서 기능을 제공하기 때문에 개발에 포함된 각각의 객체에 대한 속성 및 리스트를 제작해 줍니다.

      Analyze Database

20.   준비된 내장함수

테이블 및 View테이블 등을 대상으로 하는 편리한 도메인 함수 및 일반적인 개발 툴이 사용하는 대부분의 함수를 제공합니다.

       도메인함수

      문자열함수

       Data Connection관련 함수

21.   사용자 중심의 표현식 작성기(Expression Builder)

변수 명이나 각 객체의 이름을 일일이 암기하지 않더라도 표현식 작성기를 통하여 모든 객체에 대한 Collection 및 속성, Value등을 쉽게 참조하기 때문에 개발 시 부담하는 변수에 대한 스트레스 등이 없습니다.

       Form, Report, Table, Query등 참조

22.   전산실이나 급하게 개발해야 하는 프로그램에 용이

일반적으로 전산실은 노가다(?) 작업을 많이 합니다. 이미 ERP나 기간업무가 개발되어 있지만, 회사는 언제 어디서든 엉뚱한(?)자료를 요구할 경우가 너무 많습니다.

대부분의 전산실이 밤을 세우는 이유가 여기에 있습니다(아마..동감하는 사람이 너무도 많을 것입니다)  사용해본 사람만 알 수 있겠지만 액세스는 전산실에서 하루 종일 해야 할 작업을 10분이면 끝내줄 수 있는 모든 도구를 제공할 것입니다.

       갑작스런 자료의 통계나 추출

      갑작스럽게 주어진 업무의 해결

23.   중소기업을 위한 진정한 개발 툴이 존재 하는가요?

      국내에 모든 기업의 전산화를 위한 개발 툴이 동일하다

국내 대기업과 중소기업의 환경은 너무나 다릅니다. 하지만 전산화는 기업의 규모에 관계없이 기업을 이끌어 가는 중요한 수단으로 자리잡고 있습니다. 전산화가 목표가 될 수 는 없지만 그 목표를 달성하는 중요한 수단임은 분명합니다.

그러나 이러한 수단이 기업의 규모에 관계없이 거의 비슷하다는 현실입니다.

중소기업도 서버를 구입하고 네트워크환경을 구축해야 합니다. 지금까지의 모든 개발자들은 대기업에서 사용하던 시스템(하드웨어)나 개발  툴을 그대로 적용하는 현실입니다.

중소기업은 전산실도 없고, 컴퓨터를 잘 아는 사람도 없습니다. 2~3,000천 만원씩 하는 서버를 무료로 지원해도 중소기업은 그러한 장비와 소프트웨어를 유지할 인력이나 비용이 없다는 사실입니다.

많은 개발자 여러분들은 적은 비용으로 또는 전문인력이 없는 상황에서도 중소기업의 전산화가 잘 될 수 있도록 좋은 기술과 솔루션을 제공해야만 합니다.

중소기업의 열악한 현실을 알면서도 동일한 기술과 솔루션으로 접근하는 것은 어린아이를 물가로 몰고 가는 현실과도 같다고 생각합니다.

액세스는 일반 컴퓨터만으로도 네트워크환경에서 문제없이 움직일 수 있는 데이터베이스입니다. 데이터베이스의 백업 및 복구조차도 단순히 파일복사만으로도 충분하며  MultiUser환경을 지원합니다. 액세스는 단순한 개발 툴이라기 보다는 규모의 크기나 업무의 영역을 초월한 다양한 형태를 지원하는 하나의 솔루션입니다.

24.   액세스 !! 만남 자체만으로도 여러분에게 많은 신선함을 약속할 수 있습니다

 

    사례1>

     보험업무를 중심으로 하는 대기업에서 각 보험지국의 데이터베이스는 SQL-SERVER로 구축되어 있으며, 본사는 ORACLE로 되어 있는 상황에서 각 보험설계사가 노트북을 가지고 다니며 고객에 대한 정보를 보험지국과 본사의 서버에 모든 자료를 동기화 하려고 한다.

    해결방안>

    전형적인 Client DB를 가져야 하는 상황입니다. 그렇지 않을 경우에는 보험설계사가 노트북에 입력한 고객정보를 서버나 보험지국에 다시 한번 입력해야 하는 일이 발생됩니다.

    MS Access는 그 자체가 프로그램 개발 툴이면서 관계형 데이터베이스로서 MS Office만 설치된 노트북이라면 언제는 자체 MS Access DB에 고객정보를 입력하고, 보험지국에 돌아와서는 동일한 노트북에서 MS Access DB에 연결된 SQL-SERVER나 본사에 연결하여 그대로 자료를 전송할 수 있습니다.

    사례2>

     사례1과 동일하며 다만 고객정보가 Excel로 되어 있다

    해결방안>

    MS Access는 몇 초 만에 대부분의 자료를 관계형 데이터베이스로 쉽게 구축할 수 있습니다. 또한 일반 텍스트형태의 자료와 Excel같은 자료를 서로 연결하여 사용하거나, 이러 Excel자료를 대형 데이터베이스와 연결(Relation Join)하여 사용 가능하므로 기본자료의 종류에 관계 없이 어떠한 데이터베이스에도 연결 가능합니다.

Posted by 1010
01.JAVA/Java2010. 10. 19. 17:20
반응형
Posted by 1010
01.JAVA/Java2010. 10. 19. 16:33
반응형
java 초경량 프레임워크
서버를 재기동 할 필요가 없다.

성능은 과연 ?
http://www.playframework.org/
Posted by 1010