javascript에서의 delete는 개체(object), 개체의 속성(property),

배열의 특정 인덱스에 있는 원소(element)를 지우는 연산자이며. 문법은 다음과 같다

delete objectName
delete objectName.property
delete objectName[index]
delete property // with 문장 안에서만 유효

 

objectName은 개체 이름이고, property는 개체에 존재하는 속성이고, index는 배열의 원소 위치를 나타내는 정수.

네 번째 형식은 개체의 속성을 지우는 코드인데, with 문장 안에서만 사용할 수 있다.

암시적으로 선언된 변수를 지울 때는 delete 연산자를 사용할 수 있지만

단 var 문장을 이용해서 선언된 변수는 지울 수 없다.

delete 연산자 실행이 성공하면, 속성이나 원소가 undefined로 설정되며.

delete 연산자는 실행이 가능하면 true를 반환하고, 불가능하면 false를 반환하게 된다.

x=42
var y= 43
myobj=new Number()
myobj.h=4      // h라는 속성을 만듭니다
delete x       // returns true (암시적으로 선언된 변수는 지울 수 있습니다)
delete y       // returns false (var로 선언한 변수는 지울 수 없습니다)
delete Math.PI // returns false (미리 정의된 속성은 지울 수 없습니다)
delete myobj.h // returns true (사용자 정의 속성은 지울 수 있습니다)
delete myobj   // returns true (암시적으로 선언되었으므로 지울 수 있습니다)

 

배열의 원소를 지우기


머 당연하지만 배열의 원소를 지워도, 배열의 길이에는 변화가 없게 된다.

즉 delete로 지우는 경우 원소는 더이상 배열에 존재하지 않게 된다(undefined).

하지만 delete와 배열원소에 undefined를 할당한 경우 조금 의미가 다르다.

 

먼저 아래 예제에서 trees[3]을 delete로 제거한 예제이다.

 

trees=new Array("redwood","bay","cedar","oak","maple")
delete trees[3]
if (3 in trees) {
   // 이 블록은 실행되지 않는다.

   alert(trees[3]);
}

즉 trees라는 배열에는 trees[3] 이라는 배열원소 자체가 삭제(undefined)되어 실행되지 않지만

단지 배열 원소가 존재하긴 하지만 정의되지 않은 값을 가지도록 하고 싶다면

delete 연산자 대신 undefined 키워드를 사용하면 된다.

 

다음은 trees[3]undefined 값을 할당하는 경우이다

 

trees=new Array("redwood","bay","cedar","oak","maple") trees[3]=undefined if (3 in trees) { // 이 블록은 실행된다. }

 

undefined 키워드로 배열의 값은 정의되지 않았지만 배열원소는 유지되므로 블록은 실행된다

 

 

흐음 아직은 국내에서 ExtJS를 쓰는 곳은 많이 없는지 덕분에 머 하나 막히면 ExtJS 포럼을 열씸 뒤지는 중이다.

그래도 예전에 비해 ExtJS에 관련된 블로그들이 많이 눈에 띄는 것을 보면 언젠가 ExtJS의 한글서적도 나오지 않을까?

dojo 관련한 책도 영문서적만 있는 걸 보면 큰 기대는 못하고 있지만...-_-

mvc 프레임워크로 스트럿츠2를 사용하기 때문에 요즈음 dojo와  extjs, jQuery 통합을 시도해보고는 있는데

기냥 하나만 쓸까? 고민..

 

여하튼 ExtJS 사용자들을 위한 팁하나 소개할까 한다.

ExtJS로 툴바 또는 버튼을 만들면 a 태그를 사용할 때 처럼 onFocus 상태에서 점선박스가 생기게 된다.

매번 해당 컴포넌트를 만들면서 onFocus ='this.blur()' 를 해주기는 어려운 노릇..

 

ext-all.js 파일을 열어보자

 

<em unselectable=\"on\"><button class=\"x-btn-text\" type=\"{1}\" >{0}</button></em>

 

라는 구문을 찾아서 다음과 같이 수정한다.

 

<em unselectable=\"on\"><button class=\"x-btn-text\" type=\"{1}\" onfocus=\"this.blur()\">{0}</button></em>

 

 이젠 별다른 조치없이도 점선박스는 사라진다. ㅋㅋ

 

PS. 찾아보면 두군데 수정을 하게 된다.

혹여나 이글을  보고 수정했는데 여전히 점선이 나온다는 사람이 있을지 몰라서 언급..*^^*

 

[Oracle 10g] UTL_FILE 패키지..

오라클 | 2008. 9. 25. 19:41
Posted by 시반
 

◆ UTL_FILE Package

 

UTL_FILE 패키지를 사용하여 PL/SQL에서 파일의 입출력을 수행 할 수 있다.
PL/SQL에는 SQL*Plus의 SPOOL에 해당하는 간략화된 명령어가 없으므로 큰 로그를 출력하고 싶은 경우에는 UTL_FILE 패키지를 사용하든지 혹은 테이블을 사용한다.

 

표준 출력에는 DBMS_OUTPUT 패키지를 사용한다.

Oracle 8i이전이라면 초기화 파라미터 UTL_FILE_DIR를 설정해야 한다

 

프로그램의 Input과 output으로서, 서버OS 상의 텍스트파일을 사용하는 것으로,

PL/SQL프로그램 이외의 프로그램 정보를 뿌려주는것이 가능합니다.

 

UTL_FILE 패키지는 텍스트파일의 Open, Close, Read, Write의 기능을 제공합니다.

 

Oracle7.3부터 OS파일에 대한 쓰기,읽기를 지원하였으며

Oracle9iR2 부터 파일의 복사, 이동, 삭제 및 디렉토리 오브젝트의 이용도 가능해졌습니다.

 

주의사항 


안전을 보증하기 위해서, 파일에 접근하려면 초기화 파라메타 파일 UTL_FILE_DIR에

접근대상의 폴더(디렉토리)를 지정해 둘 필요가 있습니다. 

 

개행코드는 자동부가/삭제됩니다.

  - 한개의 행은 최대 1024바이트(개행코드 포함)가 될 수 있습니다.

  - Oracle8.0.5 부터 32767바이트(개행코드 포함) 까지 가능합니다.

    ◈FOPEN 프로시져로 크기를 지정 할 수 있습니다.

 

◆ UTL_FILE_DIR 편

 

.인스턴스를 시작한 OS 사용자가 지정한 디렉토리를 의미하며 파일에 대해서 OS레벨으로 I/O를 허가할 필요가 있다. 또한 모든 디렉토리를 대상으로 하기 위해 「UTL_FILE_DIR = *」으로 지정하는 경우 보안에 취약할 수 있으므로 되도록 특정위치를 지정하도록 한다.

 

 예) UTL_FILE_DIR = C:\TEMP

 

오라클 패키지중. dbms_logminer_d 라는 패키지를 이용하여 오라클 dictionary를 파일로 받으려는 경우  파일생성 위치를 패키지에서 utl_file_dir에 설정된 경로내에서만 지정할 수 있게 된다.

  복수의 디렉토리를 지정할 경우는, 사이에 다른 파라미터가 들어오지 않고 UTL_FILE_DIR 을 복수행 지정합니다.

 예)UTL_FILE_DIR = C:\TEMP

      UTL_FILE_DIR = C:\TEST

     

서로 다른  파라미터가 들어 있는 경우 맨 뒤에 지정한  경로만을 지정한 것으로 처리된다. 

 

준비작업


 

■ 디렉토리 작성

디렉토리를 작성할 경우에 OS 의 DBA 인 유저(통상은 oracle)로 디렉토리를 작성한다.

root 로 작성하는 경우에는, chown, chgrp, chmod 등에 의해 읽고 쓰기의 권한을 올바르게 설정한다.

파일의 I/O는 서버 프로세스에 의해서 행해지므로 그 프로세스의 오너(oracle)가 읽고 쓰기할 수 있어야 한다.

작성과 권한의 설정예 (root 에 의한 조작:권한만 있으면 root 일 필요는 없습니다)

# mkdir /u05/file_storage/recv_dir

# mkdir /u05/file_storage/send_dir

 

# chgrp dba /u05/file_storage/recv_dir

# chgrp dba /u05/file_storage/send_dir

 

# chown oracle /u05/file_storage/recv_dir

# chown oracle /u05/file_storage/send_dir

 

# chmod 700 /u05/file_storage/recv_dir

# chmod 700 /u05/file_storage/send_dir

 

디렉토리·오브젝트에 의한 파일 액세스


 

■ 디렉토리의 작성 CRAETE DIRECTORY

Oracle 9i 버젼부터 UTL_FILE 패키지가 CREATE DIRECTORY에 대응하게 되었다.
디렉토리의 추가에 따르는 재기동도 불필요.

  • 디렉토리 오브젝트의 작성
    DIRECTORY의 작성은 CREATE DIRECTORY 권한이 필요

         CREATE DIRECTORY recv_area AS '/u05/file_storage/recv_dir';
         CREATE DIRECTORY send_area AS '/u05/file_storage/send_dir';

  • 디렉토리에의 액세스권의 설정
    읽기 권한과 쓰기 권한은 개별적으로 처리한다.

        GRANT READ ON DIRECTORY recv_area TO user_name ;
        GRANT WRITE ON DIRECTORY send_area TO user_name ;
         --
         SELECT * FROM ALL_DIRECTORIES ;

 

■ 파일쓰기 (초기화 파라메터 사용시 )

CREATE OR REPLACE PROCEDURE RIVUS.CREATE_DIR_WRITE_SAMPLE

AS

  vHandle   UTL_FILE.FILE_TYPE;

  vDirname  VARCHAR2(250);

  vFilename VARCHAR2(250);

  vOutput   VARCHAR2(32767);

BEGIN

  vDirname  := 'SEND_AREA'; -- (주)디렉토리 오브젝트명을 대문자로 지정한다

  vFilename := 'test.txt';

  vHandle   := UTL_FILE.FOPEN(vDirname ,vFilename,'w', 32767);

  vOutput   := 'CREATE DIRECTORY 경유로의 파일출력';

  UTL_FILE.PUT_LINE(vHandle, vOutput);

  UTL_FILE.FCLOSE(vHandle);

EXCEPTION WHEN OTHERS THEN

  UTL_FILE.FCLOSE_ALL;

  RAISE;

END;

/

■ 파일읽기 (초기화 파라메터 사용시 )

CREATE OR REPLACE PROCEDURE RIVUS.CREATE_DIR_READ_SAMPLE

AS

  vHandle   UTL_FILE.FILE_TYPE;

  vDirname  VARCHAR2(250);

  vFilename VARCHAR2(250);

  vInput    VARCHAR2(32767);

BEGIN

  vDirname  := 'RECV_AREA';

  vFilename := 'test.txt';

  vHandle   := UTL_FILE.FOPEN(vDirname ,vFilename,'r', 32767);

 

  BEGIN

    LOOP

      UTL_FILE.GET_LINE(vHandle, vInput,32767);

      DBMS_OUTPUT.PUT_LINE(vInput);

    END LOOP;

  EXCEPTION WHEN NO_DATA_FOUND THEN

    DBMS_OUTPUT.PUT_LINE('파일의 마지막');

  END;

 

  UTL_FILE.FCLOSE(vHandle);

EXCEPTION WHEN OTHERS THEN

  UTL_FILE.FCLOSE_ALL; RAISE;

END;

/

주의사항 


  • UTL_FILE 패키지를 사용해 한 번에 입출력할 수 있는 길이는 32767(32K) 바이트 (※) 

  • OPEN 한 파일은 반드시 CLOSE 하도록 예외 처리를 해둔다.UTL_FILE.FCLOSE_ALL 를 사용하면 편리

  • RAW형을 출력할 수 있지만 줄 끝에는 OS 고유의 개행 코드가 반드시 부여된다.


    Oracle 10g 에서는 wb 에 의한 (RAW 모드) FOPEN 가 서포트되고 있으므로, 그 쪽을 사용하면 문제 없다.

이 제한에 있어서 Oracle 10g 이후가 아니면 순수한 바이너리필드를 사용할수 없다.

(※) 한 번의 기입으로 32KB 를 넘을 수 없지만, RAW 모드로의 기입에 대해서는 여러 차례에 기입을 분할하는 것으로 1행이 32KB 를 초과하는 것이 가능하다

 

◆DIRECTORY 편

UTL_FILE 패키지를 사용해 PL/SQL에서 파일의 입출력을 실시할 수 있다.Oracle 9i 이후부터는 CREATE DIRECTORY 를 사용하여 유저 단위, 읽어들이기, 쓰기의 제한이 가능하게 되었다. 또한  디렉토리를 추가하고 싶은 경우에도 Oracle 의 재기동이 필요하지 않으므로 다운 타임을 줄일 수 있다

 

준비작업


■ 디렉토리 작성

디렉토리 파일의 작성 (UTL_FILE_DIR 편과 같다)

디렉토리를 작성할 경우에 OS 의 DBA 인 유저(통상은 oracle)로 디렉토리를 작성한다.

내용은 생략 ⇒ UTL_FILE 의 사용법 (UTL_FILE_DIR 편)의 준비작업을 참조

 

디렉토리·오브젝트에 의한 파일 액세스


■ 디렉토리의 작성 CRAETE DIRECTORY

Oracle 9i 버젼부터 UTL_FILE 패키지가 CREATE DIRECTORY 에 대응하게 되었다.
디렉토리의 추가에 따르는 재기동도 불필요.

  • 디렉토리 오브젝트의 작성
    DIRECTORY의 작성은 CREATE DIRECTORY 권한이 필요

         CREATE DIRECTORY recv_area AS '/u05/file_storage/recv_dir';
         CREATE DIRECTORY send_area AS '/u05/file_storage/send_dir';

  • 디렉토리에의 액세스권의 설정
    읽기 권한과 쓰기 권한은 개별적으로 처리한다.

        GRANT READ ON DIRECTORY recv_area TO user_name ;
        GRANT WRITE ON DIRECTORY send_area TO user_name ;
         --
         SELECT * FROM ALL_DIRECTORIES ;

 

■ 파일쓰기 (초기화 파라메터 사용시 )

CREATE OR REPLACE PROCEDURE RIVUS.CREATE_DIR_WRITE_SAMPLE

AS

  vHandle   UTL_FILE.FILE_TYPE;

  vDirname  VARCHAR2(250);

  vFilename VARCHAR2(250);

  vOutput   VARCHAR2(32767);

BEGIN

  vDirname  := 'SEND_AREA'; -- (주)디렉토리 오브젝트명을 대문자로 지정한다

  vFilename := 'test.txt';

  vHandle   := UTL_FILE.FOPEN(vDirname ,vFilename,'w', 32767);

  vOutput   := 'CREATE DIRECTORY 경유로의 파일출력';

  UTL_FILE.PUT_LINE(vHandle, vOutput);

  UTL_FILE.FCLOSE(vHandle);

EXCEPTION WHEN OTHERS THEN

  UTL_FILE.FCLOSE_ALL;

  RAISE;

END;

/

■ 파일읽기 (초기화 파라메터 사용시 )

CREATE OR REPLACE PROCEDURE RIVUS.CREATE_DIR_READ_SAMPLE

AS

  vHandle   UTL_FILE.FILE_TYPE;

  vDirname  VARCHAR2(250);

  vFilename VARCHAR2(250);

  vInput    VARCHAR2(32767);

BEGIN

  vDirname  := 'RECV_AREA';

  vFilename := 'test.txt';

  vHandle   := UTL_FILE.FOPEN(vDirname ,vFilename,'r', 32767);

 

  BEGIN

    LOOP

      UTL_FILE.GET_LINE(vHandle, vInput,32767);

      DBMS_OUTPUT.PUT_LINE(vInput);

    END LOOP;

  EXCEPTION WHEN NO_DATA_FOUND THEN

    DBMS_OUTPUT.PUT_LINE('파일의 마지막');

  END;

 

  UTL_FILE.FCLOSE(vHandle);

EXCEPTION WHEN OTHERS THEN

  UTL_FILE.FCLOSE_ALL; RAISE;

END;

/

주의사항 


  • UTL_FILE에서 한번에 입출력할 수 있는 길이는 32767(32K) 바이트 (※) 

  • OPEN 한 파일은 반드시 CLOSE 하도록 예외 처리를 해둔다.UTL_FILE.FCLOSE_ALL 를 사용하면 편리

  • RAW형을 출력할 수 있지만 줄 끝에는 OS 고유의 개행 코드가 반드시 부여된다.


    Oracle 10g 에서는 wb 에 의한 (RAW 모드) FOPEN 가 서포트되고 있으므로, 그 쪽을 사용하면 문제 없다.

이 제한에 있어서 Oracle 10g 이후가 아니면 순수한 바이너리필드를 사용할수 없다.

(※) 한 번의 기입으로 32KB 를 넘을 수 없지만, RAW 모드로의 기입에 대해서는 여러 차례에 기입을 분할하는 것으로 1행이 32KB 를 초과하는 것이 가능하다

 
 

 

VoIP의 활용사례

개발 이야기/VoIP | 2008. 9. 18. 17:03
Posted by 시반
1. Voip 기술과 현재 활용사례

 

VoIP(Voice over Internet Protocol)란?

IP network을 이용해 voice와 data를 전송하는 기술로 기존에 사용된 음성 통화망의 TDM방식과 Circuit Switching 방식을 사용하지 않고 음성의 Analog 신호를 Digital 신호로 압축하고, IP Packet으로 변환하여 Internet을 통하여

Voice, Data, Video 서비스를 제공하여 인터넷 텔레포니(Internet Telephony)를 가능하게 한 통신 기술이다.

 

 

VoIP 기술은 음성 신호를 전통적인 PSTN에 전송하는 것이 아니라, 게이트웨이에서 음성 신호를 표준 규격

(G.711, G.729A, G.723.1)에 맞게 압축해 상대 게이트웨이로 전송함으로써 음성 통화를 하는 것을 의미한다.

여기에는 지속적으로 연결이 유지돼야 하는 데이터 네트워크에, 돌발적으로 발생하는 음성 통화의 트래픽을 함께

전송할 수 있도록 하는 기술이 요구된다. 많은 통신업체들은 물론이고 시장은 IP에서의 음성 통합을 대세로 인정하고 있다.

그러나 이미 PBX 기반의 인프라 구축이 많은 만큼 이를 수용하면서 점진적으로 IP로 넘어갈 수 있도록 하는 경로가 다양하게 제시되고 있다. 게이트웨이와 소프트스위치 등은 이런 차세대 네트워크의 기본으로, IP 디바이스 간의 호를 지능적으로 처리해 미디어 게이트웨이를 통해 PSTN과 통합된다.

출처 : 데이콤 Voip overview 문서, Tong - 다모아Tong님의 IT관련 자료통

 

 

2. Voip 기술 장.단점

 

- 장점

 

1. 일단 장비가 구축이 되면 통신요금이 일반전화에 비해 30~60% 정도 저렴하다.

2. 여러 가지 부가서비스를 활용할 수 있다.

 

- 단점

 

1. 통신장비 구축 비용이 많이 든다.

2. 통신 품질이 떨어진다. (패킷의 지연이나 손실의 우려)

3. 통신 보안이 취약하다.

 

 

3. Voip 실제 활용에 따른 이득과 보완대책

 

- VoIP를 도입하는 주요 이유.

 

1.통신 비용 절감을 위해 66%

2.음성과 데이터 네트워크의 통합을 위해 43%

3.두 분야 이상에서의 원스톱 커뮤니케이션 구현 위한 기술 플랫폼을 마련하기 위해 41%

4.두 분야 이상에서의 협업을 위해 36%

5.관리의 용이성을 위해 31%

6.확장성을 위해 24%

7.기타 14%

비고: 복수 응답 허용

대상: 현재 VoIP를 사용하고 있거나 계획 중인 업체 280곳

출처: 320명의 기업 기술 전문가를 대상으로 한 인포메이션위크 리서치의 VoIP 설문조사

 

 

VoIP의 활용사례.

 

- 활용 사례 1

버진 엔터테인먼트 노스 아메리카가 지난 8월에 VoIP를 도입했을 때, 시스템이 제공하는 주요 기능 중 하나가 음성 메일을 이메일 시스템과 결합시킨 통합 메시징이었다. 버진 엔터테인먼트의 CEO인 사이먼 라이트가 VoIP 도입을 결정했을 때, 도입 이유는 비용 절감이었으며, 통합 메시징은 논의조차 되지 않았다. 라이트는 어느날 자신의 음성 메일이 이메일 수신함에 뜨는 것을 보고 놀라지 않을 수 없었다. 그는 별도의 비용이 청구될까봐 즉시 알아보라고 했으며, 무료라는 말에 안도할 수 있었다. 그로부터 2주일이 지난 뒤, 그는 자신의 모든 메시지를 한 곳에서 확인할 수 있다는 것에 매우 만족해했으며, 자신이 회사에 들어오고 난 이후 VoIP를 도입한 것이 가장 잘한 일이라고 말할 정도이다. 이 회사는 현재 VoIP를 다른 커뮤니케이션 플랫폼과 연동해 직원들의 협업을 향상시킬 수 있는 방안을 모색하고 있다.

 

- 활용 사례 2

인력 대부분을 메릴랜드 본사로 통합하는데 분주한 미국 식품의약국(FDA)은 통합 커뮤니케이션을 적극 활용하고 있다. FDA는 18,000명에 이르는 직원들과 15개 빌딩에서의 협업을 높이기 위해 VoIP를 도입했으며, IP 화상회의도 추진하고 있다. 일부 과학자와 연구원들의 경우 데스크톱에서 시스코의 IP 커뮤니케이터 통합 커뮤니케이션 애플리케이션에 이미 액세스하고 있으며, 통합된 음성과 비디오, 데이터를 통해 구내에서 프로젝트에 대한 협업이 가능하다. 이를 통해, 한 과학자가 실험실에서의 약품 분석 결과를 동료에게 설명하거나 텍스트나 데이터를 통해 결과를 보내는 등의 작업을 동일한 인터페이스를 통해 동시에 진행할 수 있다. FDA의 CIO인 글렌 로저스는 “이제 전화는 과거처럼 단순한 전화가 아니다”라고 밝혔다.

 

- 활용 사례 3

시애틀의 MTM 호텔 1000의 경우, 80개의 객실마다 3대의 IP 폰을 설치했으며, 호텔 맨위층의 럭셔리 객실에 47대의 IP 폰을 설치했다. 이 호텔의 짐 심킨스 부사장은 “프로그래밍이 가능한데다 외관도 수려하다”면서, “오늘의 점심 특선 메뉴를 액정에 띄울 수도 있으며, 가상의 관리인 역할도 제공한다”고 말했다. 프로그래밍이 가능하다는 예는, 투숙객이 차량을 호출하고 싶을 때, 자신의 객실에 설치된 VoIP 폰의 버튼을 눌러 발레 데스크에 연락하면 투숙객의 차량 위치를 즉시 확인할 수 있다.   

 

출처: 이플님의 블로그에서 퍼온글...(컴퓨터월드 2006년 9월호/InformationWeek)

'개발 이야기 > VoIP' 카테고리의 다른 글

[VoIP의 개요] 음성변조  (0) 2008.09.18
VoIP의 필요성  (0) 2008.09.18
IP 텔레포니와 VoIP  (0) 2008.09.18
SOA와 VoIP 서비스  (0) 2008.09.18
VoIP, 통화 음질이 전부는 아니다  (0) 2008.09.18
 

5. VoIP 시장 동향

개발 이야기/VoIP | 2008. 9. 18. 15:34
Posted by 시반
PSTN 전화 대체재로 VoIP 시장 폭발적 성장
2008년 160억달러 시장 규모 전망 … 통신사업자 경쟁적 투자 확대 나서


연·재·순·서
1. PSTN에서 VoIP로
2. VoIP 기술 ① : 프로토콜

6. VoIP 향후 전망

 

이종석
케이티인포텍 신사업기획단 상무
jslee@kti.co.kr


네트워크의 올-IP화가 진전되면서 VoIP 시스템이 기존 PSTN 전화의 대체재로 등장, 현재 전 세계적으로 성장세를 보이고 있다. 특히 광대역통합망(BcN)과 네트워크의 올-IP화는 유비쿼터스 시대로 진화하기 위한 전제조건으로, IP망을 통해 음성을 전송하는 VoIP 서비스의 첫 단계라고 할 수 있다. 단기적으로 VoIP 시스템은 PSTN의 부분적인 대체 시스템으로 기능하게 될 것이며, 서서히 주류로 진화해 갈 전망이다. <편집자>


전 세계적으로 초고속인터넷 보급률이 증가하면서 VoIP 서비스의 이용 기반도 확대되고 있는 추세다. OECD 30개국의 평균 인터넷 보급률이 1995년 3% 수준에서 2003년 40% 이상으로 급격히 증가한 데 이어, 2004년 1천600만명이던 VoIP 서비스 사용자가 2008년에는 2억명에 육박할 것으로 기대된다. 또한 VoIP 서비스 시장 매출액은 2004년 10억달러에서 2008년에 160억달러로 늘어날 전망으로 이는 전체 음성통신시장의 6%에 해당하는 수치다.



국내 VoIP 시장 현황
전 세계 VoIP 시장은 지난 2000년 초반 유료 비즈니스 모델 실패 이후 시장이 침체됐다. 하지만 과도기를 거치며 새로운 유형의 통신서비스로 인식되기 시작, 높은 초고속인터넷 보급률과 함께 점차 성장이 가속화되고 있다.
국내의 경우 2000년 새롬C&T의 무료 인터넷전화로 시작됐다. 초기에는 수익모델의 한계로 침체된 게 사실이지만, 과도기를 거쳐 IP시대로 돌입하면서 새로운 비즈니스 모델로 떠오르고 있다. 기존 유선 음성전화 시장의 대체재로 빠르게 성장 중인 국내 VoIP 시장은 지난해 전체 통신시장의 2.9%의 비율을 차지한 것으로 집계됐으며, 오는 2008년에는 8천83억원까지 치솟을 전망이다. 이는 전체 유선통신 시장의 12.5%에 해당한다.
지난 2003년 VoIP 서비스 관련 MoU(Minutes of Use)는 약 9억7천700만분이며 오는 2008년에는 약 130억472만분으로 증가할 것으로 예상된다. 이미 유선전화, 초고속인터넷, 망 설비 및 IT 솔루션, 케이블TV 등 다양한 사업배경을 지닌 사업자들이 각기 다른 전략으로 VoIP 시장에 진출했으며, 이들의 시장선점 경쟁도 갈수록 치열해지는 양상이다.
기존 유선전화사업자는 시장방어를 목적으로 도매시장과 기업용 시장을 중심으로 사업을 전개 중이다. 특히 시내전화 후발 사업자들은 유선음성시장의 점유율을 만회하기 위해 적극적으로 VoIP 서비스 사업을 추진하는 모습이다. 이들은 기업전용망과 함께 결합상품 또는 부가서비스상품으로 VoIP 서비스 사업을 전개, 기업용 시장을 중점 공략하고 있다. 덕분에 IP-PBX 및 소프트 스위치가 각광받는 제품으로 떠오르고 있다.
서비스 제공자 시장 측면에서 가장 눈에 띄는 부분은 케이블TV 방송업체(SO)들이다. 케이블TV 방송업체들은 별도법인을 설립, 기간통신사업 허가를 획득해 독자 브랜드로 사업을 준비하며 방송, 인터넷, 전화를 결합한 TPS 제공으로 통신업체에 대응하겠다는 전략이다.
막대한 사용자층을 확보하고 있는 인터넷 포털들도 이를 기반으로 인터넷전화 시장에 진입하려는 움직임을 보이고 있다. 다음은 이미 글로벌 P2P 텔레포니 업체인 스카이프(Skype)와 연합해 VoIP 서비스 시장에 뛰어들었고, NHN, SK커뮤니케이션즈 등 거대 포털 업체들도 별정통신사업자로 등록 또는 이를 계획하고 있는 것으로 알려졌다. 이들은 기간통신사업자와의 제휴를 통해 VoIP 서비스를 제공할 전망이다.



해외 VoIP 장비시장 현황
VoIP 장비는 크게 통신사업자 및 서비스 사업자 네트워크에 위치하는 사업자용 장비와 기업과 가정에 공급되는 가입자 장비(CPE)로 구분된다. 사업자용 장비에는 소프트 스위치와 미디어 게이트웨이가 포함되며, 가입자 장비로는 IP PBX 관련 제품군과 VoIP 게이트웨이, VoCM(Voice over Cable Modem) 등이 있다.
소프트 스위치의 경우 아직까지도 그 정의가 진화하는 중이다. 과거보다는 네트워크 상에서 SBC(Session Border Controller)나 애플리케이션 서버 등과 함께 보다 복합적인 구조로 정의되는 경향을 보인다.
美 보니지(Vonage)와 AT&T, 日 야후BB 등 일부 통신 사업자는 지난 2003년부터 광대역 음성(voice over broadband) 서비스를 성공적으로 제공하고 있다. 이로 인해 다른 통신사업자들도 자사의 VoIP와 관련된 전략을 재평가하고 VoIP 관련 장비를 도입하고 있는 추세다.
현재 전세계적으로 레거시 TDM 기반의 네트워크에서 차세대 네트워크로의 진화가 점진적으로 이뤄지고 있다. 소프트 스위치나 미디어 게이트웨이는 이러한 차세대 네트워크 구조에서 기존 PSTN의 레거시 CO(Central Office) 스위치를 대체하며 주목을 받고 있다.
그러나 현재 통신사업자들의 재정적인 어려움으로 인해 이러한 네트워크 마이그레이션을 언제 어떠한 방법으로 진행할 것인가에 대해 보다 현실적인 평가 또한 진행되고 있다. 이러한 평가는 보다 애플리케이션 중심적, 혹은 매출을 창출하는 ROI 중심적으로 이뤄지는 게 현실이다. 그럼에도 불구하고 이러한 차세대 스위칭 장비들은 기존 레거시 장비 시장을 지속적으로 잠식해 오는 2009년부터는 레거시 장비 시장 규모를 추월할 것으로 예상된다.



해외 장비 시장 전망
전세계 소프트 스위치, 미디어 게이트웨이 장비 시장은 지난 2004년 약 13억5천만달러에서 향후 5년간 연평균 성장률 47%로 성장해 오는 2009년에는 약 92억7천만달러 규모가 될 것으로 예상된다. 이 중 소프트 스위치와 미디어 게이트웨이의 비중은 상대적으로 미디어 게이트웨이에 대한 성장이 높아 2004년 52%에서 2009년에는 58%로 증가할 전망이다.
유선과 무선 네트워크로 구분해 보면, 현재 유선 네트워크 상에서의 도입이 많은 비중을 차지하고 있지만 무선 네트워크에서의 도입도 지속적으로 증가해 2009년에는 무선의 비중이 27%로 증가할 것으로 기대된다. 지역적으로 보자면 2004년 북미지역이 전체 시장의 약 47%를 차지하고 있고, 그 뒤를 유럽 26%, 아시아 17%, 기타 지역 10%이 뒤따르고 있다. 그러나 향후 성장률에 있어서는 상대적으로 북미 이외 지역이 높게 성장할 전망이다.
차세대 네트워크로의 마이그레이션이 진전되면서, 전통적인 회선교환 음성 스위치 장비 시장은 연평균 10% 내외의 감소가 예상되는 반면 VoIP 장비 시장은 연평균 51%씩 성장해 2008년에는 전체 서비스 사업자 음성 스위치 장비 시장에서 40%의 비중을 차지하게 될 것으로 보인다.
지금까지 전통적인 서비스 사업자 회선 교환 음성 스위치 장비 시장은 5대 대형 장비 업체들(알카텔, 루슨트, 에릭슨, 노텔, 지멘스)이 전체 시장의 70% 이상을 독점해 왔다. VoIP 서비스는 케이블 사업자나 전문 서비스 사업자 위주에서 이제 기존의 음성 전화 서비스 사업자들도 시장에 진출하고 있으며, 이로 인한 장비 시장 확대가 예상된다.
현재 VoIP 서비스는 단순한 음성 중심에서 부가 수익을 제공하는 다양한 애플리케이션 중심으로 진화하는 중이다. 또한 음성 서비스의 경우에도 단순히 통화 품질이 높은 서비스를 제공하는 것보다 고객의 요구에 따라 서비스의 품질을 조정해 다양한 가격대로 제공하는 추세다.
유선과 무선, 방송간의 경계가 무너지고 상호간에 컨버전스가 이뤄지고 있는 상황에서 최근 무선 네트워크를 중심으로 한 IMS(IP Multimedia Subsystem) 아키텍처가 주목받고 있다. 이러한 IMS를 통한 광대역, 무선, 영상, 음성 등의 융합은 향후 VoIP 관련 장비 시장의 주요한 성장 동인으로 작용할 전망이다. 이를 통해 언제 어디서나 어떠한 네트워크에서든 사용자들이 다양한 디바이스를 통해 멀티미디어 서비스를 제공받을 수 있는 기반이 마련되고 있으며 통신사업자들은 효율적인 차세대 네트워크 구축을 통해 수익성을 제고할 수 있는 서비스와 애플리케이션을 제공할 수 있을 전망이다.



미국 VoIP 서비스 현황
미국의 VoIP 서비스 사업은 기존 사업자보다는 순수 인터넷 사업자와 케이블TV 사업자를 중심으로 진행되고 있으며, 기존 통신 사업자들도 점차 VoIP 서비스 사업에 뛰어들고 있다. 특히 초고속인터넷과 함께 인터넷전화 시장이 확장되고 있다는 점이 가장 큰 변화다.
지난 2004년 3천300만명의 초고속인터넷 사용자가 오는 2008년에는 6천800만명에 이를 전망이다. 이에 발맞춰 현재 2.7%에 불과한 VoIP 서비스 사용자도 2008년에는 25.7%로 증가할 것으로 기대된다. 특히 케이블 사업자와 ISP의 가입자 위주로 VoIP 사용자가 증가하는 양상이다. 보니지는 40만 이상의 가입자를 확보하고 있으며, TPS 전략의 일환으로 타임워너와 컴캐스트 등도 VoIP 서비스 사업을 확대하고 있는 것으로 밝혀졌다.



일본 VoIP 서비스 시장 현황
일본은 2010년까지 전화망을 IP망으로 전환한다는 계획의 일환으로 VoIP 서비스 사업을 추진 중이다. 현재 일본 VoIP 시장은 초고속인터넷 사업자인 소프트뱅크가 시장을 선점하고 있으며, NTT도 지난해 인터넷전화 시장에 진입해 현재 많은 기관에서 VoIP 서비스를 사용하고 있다.
일본은 초고속인터넷 가입자의 대다수가 VoIP 서비스에 가입하면서 2005년에 약 830만명의 가입자를 보유한 VoIP 서비스 강국이다. 규제 및 기타 관련 부분이 국내 VoIP 시장보다 가입자를 유발하는 측면이 상당히 크다. 일례로 소프트뱅크의 경우 시내통화는 12%, 국제통화는 최고 95%까지 할인된 가격으로 VoIP 서비스를 제공한다. 대표적인 VoIP 서비스 제공업체인 소프트뱅크의 경우 초고속인터넷 가입자의 93%가 VoIP 서비스를 사용하고 있으며 APRU는 예상했던 1천엔(9달러)을 넘어 4천엔(37달러)을 달성했다.



중국 VoIP 현황
중국 정부는 VoIP 서비스를 기본적인 통신업무로 규정하고 있다. 이론적으로 지배적 사업자인 6개의 통신 서비스 제공자에게 VoIP 서비스를 승인한 가운데 폰 투 폰(Phone-to-Phone) VoIP 서비스도 가능하다. 중국 신식사업부는 PC 투 PC 기반의 VoIP 서비스는 규제하지 않는다. 따라서 PC 투 PC 서비스는 PSTN과 독립적으로 운영된다.
가장 논란이 되는 부분은 PC 투 폰 혹은 웹폰의 경우다. 중국 정부는 이 서비스를 4개의 서비스 타입으로 분류했다. 첫째 차이나텔레콤과 차이나넷콤은 4개 도시지역에서 웹폰 서비스를 실시할 수 있는 면허를 취득했다. 두 번째 차이나타이통은 VoIP 서비스 면허는 취득했지만 웹폰 면허는 취득하지 못했다. 세 번째 외국 회사와 파트너십을 체결한 ISP로 구분했으며 마지막은 기술 벤처로 분류했다.
웹폰과 VoIP 서비스는 다르다. VoIP는 H.323을 기반으로 한 기본적인 전기통신 서비스로 각 종단 네트워크에서는 PSTN을 사용하고, 중간의 전송부분을 IP 네트워크로 이용하는 폰 투 폰 개념인 반면 웹폰은 PC 투 폰 서비스를 의미한다. 웹폰 서비스는 전기통신 서비스 카탈로그에 포함돼 있지 않으며, 중국 신식사업부에서 각종 전기통신 서비스를 정의할 때 성숙한 기술이 아니었기 때문이다.
웹폰 서비스의 시도는 대형 유선 사업자들이 선도했으며, 사용자들은 3개의 다른 형태의 서비스를 이용할 수 있었다. 첫째 서비스는 폰 투 폰 서비스로 차이나텔레콤, 차이나넷콤, 차이나모바일, 차이나유니콤, 차이나타이통 그리고 차이나새털라이트에서 제공했으며, 두 번째 PC 투 폰 서비스는 차이나텔레콤, 차이나넷콤 그리고 여러 다른 ISP와 기술 벤처들이 제공했다. 마지막으로 PC 투 PC 서비스는 MSN, 야후 같은 대형 포털의 메시징 서비스를 통해 이뤄졌다.
현재 중국 VoIP 시장에서 유망한 품목은 소프트 스위치와 차세대 네트워크, IP 게이트웨이, IP-PBX 솔루션 그리고 그룹 통화 및 비디오 컨퍼런싱 등이 가능한 VoIP 애플리케이션이 있다. 중국의 VoIP 시장은 지난 3년간 꾸준히 성장하고 있으나 전체적인 사용자 숫자를 추산하기는 힘들다. 약 20%의 인터넷 사용자가 VoIP 서비스를 이용할 것으로 추산되고 있다. 장거리 시외전화는 감소하는 대신 VoIP를 통한 수입은 꾸준히 증대되고 있고, VoIP의 전체 매출은 통신 서비스 전체에서 10%보다 작은 비율을 차지하지만, 계속 증대되는 양상이다.


유럽 VoIP 서비스 현황
유럽의 기존 통신 사업자들은 VoIP의 발전 가능성에 신중함을 보였으나, 2004년 초까지 많은 사업자들이 VoIP 기술을 적용하기 위한 계획을 준비한 게 사실이다. 유럽의 VoIP 발전은 2004년 유럽의 규제체계가 상업적으로 실행가능한 가입자망 세분화(local loop unbundling) 서비스를 전달하기 시작했을 때부터 본격적으로 이뤄졌다. 이것은 VoIP와 같은 IP 기반 서비스의 제공을 위한 준비로 프랑스, 독일, 영국이 300만 정도의 DSL 라인을 구성하도록 만들었다.
전통적인 통신회사들은 VoIP의 발전으로 서서히 이윤손실을 볼 수 있지만, BT의 글로벌 서비스와 프랑스텔레콤의 워너두(Wanadoo)의 경우에서 볼 수 있듯 기존 통신 사업자에 의한 VoIP 서비스 제공이 대세적인 상업적 관행임을 볼 수 있다. 프랑스, 독일 및 영국의 VoIP 시장이 유럽에서 가장 큰 부분을 차지하고 있어 아직까지 널리 확산됐다고 보기는 어렵지만 초고속인터넷의 성장과 더불어 꾸준히 시장이 성장하고 있다.

'개발 이야기 > VoIP' 카테고리의 다른 글

인터넷전화(VoIP) 부활하는가?  (0) 2008.09.18
6. VoIP 향후 전망  (0) 2008.09.18
4. IP-PBX의 기능과 역할  (0) 2008.09.18
3. VoIP 기술② : 네트워크 구조  (0) 2008.09.18
2. VoIP 기술① : 프로토콜  (0) 2008.09.18
 

고급 자바스크립트 활용 II

WEB2.0 | 2008. 4. 2. 18:04
Posted by 시반
바로 전 기사에서는 두 가지 형태의 자바스크립트 위젯과 떠다니는 텍스트, 팝업 메뉴를 완전한 소스를 보여주면서 소개하였다. 이 기사에서는 또 다른 유용한 자바스크립트 위젯을 계속해서 소개해볼 텐데, 실제로 위젯이 어떻게 동작하는 지에 대해 집중적으로 살펴봄으로써 여러분이 그것들을 필요한 대로 손쉽게 수정할 수 있게 할 것이다. 이 기사에서 사용된 자바스크립트는 수정할 필요 없이 현재 사용되고 있는 주요 브라우저에서 모두 동작해야 한다. 별 어려움 없이 말이다…

div 태그를 이용한 이미지 토글

종종 여러분은 이미지 같은 무언가를 웹 페이지에 잔뜩 집어넣고 싶을 때가 있을 수도 있는데, 그것들을 모두 집어넣기엔 웹 페이지의 공간을 너무 많이 차지한다. 그러면 이미지 하나만 집어넣고 사용자가 스위치를 이용해서 다른 이미지로 교체하도록 하면 어떨까? 아마 이렇게 작동할 것이다:

div_toggle.html

이렇게 하는 것은 실제로 매우 간단하다. 한 가지 알아둘 것은 매번 이미지를 전환할 때마다 브라우저는 서버와 교신하지 않는다는 것이다. 하지만 이미지는 즉시 전환된다. 트릭이 무엇이냐고? 바로 이미지를 모두 HTML에 집어넣긴 하지만 한번에 하나씩만 보여주는 것이다! 이는 div 태그와 스타일을 이용해서 손쉽게 완성할 수 있다. 이 기법을 이용하면 인상적인 효과를 꽤 많이 만들어 낼 수 있으며, 이어지는 예제에서 볼 수 있을 것이다. 하지만 처음에는 지금 보여지고 있는 예제가 실제로 어떻게 작동하는 지에 대해서만 생각해 보기로 하자. 단 하나의 자바스크립트 함수만 사용하였다:
function ShowImage(page, tag)
{
    var i = 1;
    var el;
    while (el = document.getElementById(tag + i)) {
        if (i == page)
            el.style.display = 'block';
        else
            el.style.display = 'none';
        i++;
    }
}
실제 이미지들은 HTML상에 나타나야 할 위치에 놓여져 있는데, 각 이미지들은 다음과 같이 해당 div 태그에 들어있다:
<table>
    <tr valign="top">
        <td>
            <div style="display:block" id="image1">
                <img src="/onlamp/2007/08/23/graphics/pic1.jpg" />
            </div>
            <div style="display:none" id="image2">
                <img src="/onlamp/2007/08/23/graphics/pic2.jpg" />
            </div>
            <div style="display:none" id="image3">
                <img src="/onlamp/2007/08/23/graphics/pic3.jpg" />
            </div>
        </td>
        <td width="100%" align="right">
            <select onchange="ShowImage(parseInt(this.value), 'image');">
                <option selected="selected" value="1">Image 1</option>
                <option value="2">Image 2</option>
                <option value="3">Image 3</option>
            </select>
        </td>
    </tr>
</table>
위 테이블 구조는 단순히 레이아웃에 맞춰져 있는데, 기사의 논의 목적상 그런 것은 무시할 수 있다. 중요한 부분은 테이블의 첫 번째 셀 안에 들어있는 세 개의 div 태그들이다. 다른 div 태그들은 display가 none으로 설정되어 있는데 반해 첫 번째 div 태그는 display가 block으로 설정되어 있다. 비록 이전에 이미지를 서버로부터 전달받아 로컬에 저장하여 웹 페이지의 나머지 부분에 있더라도 display가 none으로 설정되어 있는 것들은 뷰에서 감춰져 브라우저 창에 그려지지 않는다. 따라서 처음에는 pic1.jpg만 보여지고 다른 두 개의 이미지는 볼 수 없다.

그런 다음 선택상자(selector box)에 onchange 이벤트가 발생할 때 자바스크립트 함수를 호출하도록 만들어 놓는다. 이렇게 하면 사용자가 선택상자에서 새로운 것을 선택 할 때 이벤트가 발생한다. 자바스크립트에는 두 개의 인자를 전달하는데, 각각 선택상자의 노드 자체에 대한 레퍼런스와 이미지를 담고 있는 div 태그의 id이다(id는 image1, image2, image3으로 모두 image로 시작한다는 것을 염두에 둔다).

함수는 보여줄 이미지를 의미하는 최근에 선택된 값을 가지고 실행된다. parseInt를 이용하여 선택된 값이 문자열이 아니라 숫자로 저장되도록 하였다. 다음으로는 첫 번째 div 태그에 대한 핸들을 가져오는데, 위 경우 image1이라는 id를 가진 것을 가져오게 된다. 만약 현재 이미지가 보여질 이미지이면 display 스타일을 block으로 지정하고 나머지 것들은 none으로 지정한다. 그리고 나서 더 이상 태그를 찾을 수 없을 때까지 다음 태그들을 처리한다.

그러므로 드롭 다운 박스에 새로운 항목들이 선택될 때마다 해당 div 블록이 보여지며 다른 것들은 모두 감춰진다. 이미지들은 모두 웹 페이지상의 동일한 물리적 공간을 공유하고 있는데, 왜냐하면 HTML내에서 서로서로 바로 옆에 위치해 있기 때문이다. 하지만 물론 꼭 이렇게 해야 하는 것은 아니므로 이미지들을 페이지의 서로 다른 영역에 뿌려놓고 원한다면 선택하는 것에 따라 다양한 위치에 그림을 나타나게 할 수도 있었다. 이와 비슷하게 이미지에도 어떠한 제약사항이 가해지는 것도 아니라서, 죄다 div 태그 사이에 집어넣고 마우스 클릭 한번으로 감추고 보이게 할 수도 있다. 이는 여러분이 일반적으로 집어넣는 것 보다 훨씬 더 많은 정보를 웹 페이지에 집어넣을 수 있도록 해주며 사용자는 아무런 스크롤도 할 필요가 없다.

탭 : div 좀 더 갖고 놀기

div 태그를 이용하는 다른 독창적인 예제를 통해 계속 진행해 보자. 종종 정보가 담겨있는 여러 개의 "탭(tab)"이 포함된 웹 페이지를 만들어 보고 싶을 때가 있다. 마치 요즘 사용되는 대부분의 웹 브라우저에서 제공하는 탭 브라우징 기능이 작동하는 것 마냥 탭을 클릭하면 탭에 들어있는 정보를 보여주고 다른 부분들은 감춰진다. 하지만 일반적으로 이처럼 HTML상의 탭을 클릭하면 페이지를 다시 불러오기 때문에 확실히 인터페이스의 자연스러움이 흐트러지게 된다. 정보가 즉각적으로 나타날 때 좀 더 멋있게 할 수는 없을까? 이전 예제에서 배웠던 매우 사소한 트릭을 이용하면 그렇게 할 수 있다. 한번 해보자:

tab_source.html

놀랄 것도 없이 이 예제는 이전 예제에서 사용했던 것과 정확히 동일한 자바스크립트 함수를 사용하고 있고 있는데, 전혀 다른 효과를 보여주고 있다. 나머지 부분은 몇 가지 단순한 CSS 규칙만으로 이루어진다. 이제 이 예제의 HTML을 살펴보기로 하자.
<div style="display:block" id="tab1">
    <ul class="tab">
        <li class="tab_selected" onclick="ShowImage(1, 'tab');">
            Summary
        </li>
        <li onclick="ShowImage(2, 'tab');">
            Details
        </li>
        <li onclick="ShowImage(3, 'tab');">
            Known Issues
        </li>
    </ul>
    <p>
        Introducing the new, improved multi-widget.  It slices, it dices, it even does
        your taxes!  Order yours today!  Call now: 555-WIDG
    </p>
</div>

<div style="display:none" id="tab2">
    <ul class="tab">
        <li onclick="ShowImage(1, 'tab');">
            Summary
        </li>
        <li class="tab_selected" onclick="ShowImage(2, 'tab');">
            Details
        </li>
        <li onclick="ShowImage(3, 'tab');">
            Known Issues
        </li>
    </ul>
    <p>
        The multi-widget is a sophisticated piece of complex machinery designed by the
        country's leading nuclear physicists.  Order yours today and you will quickly
        learn how easy it is to do just about anything in no time, thanks to our patented
        EZ-Widge technology.
    </p>
    <p>
        Motor: 5HP<br />
        Dimensions: 8" x 5" x 2"<br />
        Weight: 212 g<br />
        Radioactivity: negligible
    </p>
</div>

<div style="display:none" id="tab3">
    <ul class="tab">
        <li onclick="ShowImage(1, 'tab');">
            Summary
        </li>
        <li onclick="ShowImage(2, 'tab');">
            Details
        </li>
        <li class="tab_selected" onclick="ShowImage(3, 'tab');">
            Known Issues
        </li>
    </ul>

    <ul>
        <li>Do not use multi-widget near open flames</li>
        <li>Do not run while holding multi-widget</li>
        <li>Do not taunt multi-widget</li>
        <li>
            Multi-widget may, under certain as yet undetermined circumstances,
            spontaneously explode.  We hereby disclaim any libaility for personal injury
            caused as a result of multi-widget; for your safety, we recommend wearing
            body armor while handling multi-widget.
        </li>
    </ul>
</div>
마치 이전 예제에서 각각의 이미지 하나당 하나의 div를 가졌던 것처럼3개의 div 섹션(각 탭 당 하나씩)을 가지고 있음을 알아둔다. 그리고 이번에도 첫 번째 블록에만 display:block으로 지정하고 나머지 것들은 display:none으로 지정하여 처음에는 오직 첫 번째 블록만 보이도록 한다. 이러한 각 섹션들은 세 개의 탭을 그림으로써 시작하는데, 선택된 블록만 다른 것과 블록과 다른 색상을 띤다. 그렇게 하여 실제로는 각 탭을 선택할 때마다 세 개의 탭을 모두 몇 번이고 다시 그리게 되는 셈이다. 탭에 들어가는 내용은 임의의 HTML이 될 수 있다. 기억해둘 것은 내용은 오직 한번만 보여지고, 실제 탭의 HTML만 수회에 걸쳐 반복되기 때문에 "낭비되는(wasted)" 공간을 최소화할 수 있는 것이다.

각 항목에 onclick 이벤트가 발생하면 showImage 자바스크립트 함수가 호출된다는 것을 알아둔다. 첫 번째 예제에서 살펴본 것과 같이 showImage 함수는 인자로 전달된 하나만 제외하고 나머지 모든 div 섹션들을 숨긴다. 이와 같이 여기에서는 이 함수를 여러분이 클릭한 탭만을 보여주고 다른 나머지 것들은 감추는데 사용한다. 탭을 적절하게 그리는 데에는 실질적으로 CSS나 스타일을 사용하며 CSS에는 tab과 tab_selected라는 이름의 두 클래스를 정의하였다. 전자는 특별한데가 없는 전체 탭에 적용되는 것이고, 후자는 현재 선택된 탭에만 적용되는 것이다. CSS의 내용은 다음과 같다:
ul.tab {
    margin: 0;
    padding: 3px 0;
    border-bottom: 1px solid #778;
    font-weight: bold;
}

ul.tab li {
    display: inline;
    padding: 3px 0.5em;
    margin-left: 3px;
    border-top: 1px solid #778;
    border-left: 1px solid #778;
    border-right: 1px solid #778;
    border-bottom: none;
    background: top repeat-x #89aac7;
    white-space: nowrap;
    color: white;
    cursor:pointer;
}

ul.tab li.tab_selected {
    background: #fff;
    border-bottom: 1px solid #fff;
    color: black;
}
첫 번째 섹션은 ul 태그와 전체 탭 바에 적용된다. 첫 번째 섹션은 margin과 padding을 지정하여 무조건 왼쪽위로 지정하고 border가 탭 바의 바닥에 그려지게 한다. 적당히 줄을 맞추기 위해 padding이 필요하며, 탭 바의 텍스트는 모두 진하게 표시하였다.

다음 섹션은 탭 바에 들어있는 모든 li 태그에 적용된다. 아마 display:inline이 가장 중요한 속성일텐데, 목록을 수직이 아닌 수평으로 만들어 주기 때문이다. 다시 한번 padding과 margin을 이용하여 탭을 일렬로 세우고 탭 사이사이의 여백을 맞춘다. border 속성은 상단과 탭 좌우를 그린다(바닥은 ul 태그로 그려짐을 떠올려본다). 마지막으로 배경 및 전경색상을 지정하고 텍스트 줄바꿈은 비활성화 하였다.

마지막 섹션은 현재 선택된 탭에만 적용되는데, 두 번째 섹션에 정의되어 있는 모든 설정을 재정의한다. 바뀐 것은 탭의 배경색상과 전경색상이며 ul 태그의 검정색 바닥 경계선을 흰색 바닥 경계선으로 그려줄 뿐만 아니라 선택된 탭을 눈에 띄도록 해준다. 이는 선택된 탭이 다른 탭 앞으로 튀어 나온 것처럼 착각하게 만든다.

이 예제에서 모든 탭의 내용은 모두 페이지 안으로 불러들여져 저장되므로 탭을 클릭하면 거의 즉각적으로 새로운 정보가 만들어지며 페이지를 다시 불러오지 않기 때문에 주의가 분산되지도 않는다. 매우 간단한 자바스크립트 함수와 CSS를 조금 사용하여 실로 매우 인상적인 효과를 거둘 수 있었다.

훨씬 고급스러운 div 트릭

앞에서 배웠던 트릭을 이용하는 유용한 애플리케이션의 마지막 예제로서 많은 양의 내용이나 목록을 요약하여 사용자가 관심있는 목록만을 열어볼 수 있도록 하는데 사용할 수 있는 다음의 예제를 만들어 보기로 하자:

advanced_div.html

아래는 위 예제의 소스이다:
<div style="display:block;" id="colors1">
    <table style="background:#eeeebb">
        <tr>
            <td>
                <img src="/onlamp/2007/08/23/graphics/expand.jpg" style="cursor:pointer;"
                alt="Click to Expand" title="Click to Expand" 
                onclick="ShowImage(2, 'colors');" />
            </td>
            <td>
                Choice of four widget colors
            </td>
        </tr>
    </table>
</div>
<div style="display:none;" id="colors2">
    <table style="background:#eeeebb">
        <tr valign="top">
            <td>
                <img src="/onlamp/2007/08/23/graphics/collapse.jpg" style="cursor:pointer;"
                alt="Click to Collapse" title="Click to Collapse" 
                onclick="ShowImage(1, 'colors');" />
            </td>
            <td>
                <ul>
                    <li>blue</li>
                    <li>green</li>
                    <li>red</li>
                    <li>brown</li>
                </ul>
            </td>
        </tr>
    </table>
</div>
이제 이 예제가 어떻게 작동하는지 꽤 명확하게 알 수 있어야 한다. 이번에도 위에서는 두 개의 div 블록을 포함하고 있는데, 하나는 접혀 있는 내용에 펼침 버튼이 있는 것이고, 다른 하나는 완전히 펼쳐진 내용에 닫기 버튼이 있는 것이다. 처음에는 닫힌 버전(display:block)만을 보여주고 이미지의 onclick 콜백을 이용하여 div 블록이 바뀌는 것을 감지한다. 블록에는 colors1과 colors2라는 id가 주어지는데, 그렇게 하여 앞서 작성했던 ShowImage 자바스크립트 함수로 손쉽게 전환할 수 있다.

드래그 앤 드롭과 맞바꾸기(swap)

이제 div 태그에 대해 멀미날 정도로 조사해 보았으므로 이번에는 조금 다른 것에 관해 알아보기로 하자. 이 예제에서는 마우스로 텍스트(혹은 이미지)를 드래그 앤 드롭할 수 있는 메소드를 보여줄 것이다. 이러한 메소드는 자바스크립트 게임이나 좀 더 중요한 목적, 예를 들면 여러분이 한 페이지에 들어있는 이미지의 순서를 바꾸거나 할 때 사용할 수 있다. 다음 예제에서는 서로 위에 포개져 있는 세 개의 이름을 드래그 앤 드롭하여 이름의 위치를 바꿔보도록 하겠다. 여러분이 John과 Jane은 문제없이 위치를 바꿀 수 있겠지만, Bill은 다른 것과 서로 위치를 바꿀 수 없을 것이다. 왜냐하면 Bill은 항상 말썽만을 일으키는 녀석이기 때문이다.

draggable.html

이 예제는 지금껏 보여주었던 것보다는 더 많은 양의 코드를 필요로 하긴 하지만 상당히 직관적이기도 하다. 다른 예제와는 달리 이번 예제는 전역 마우스 이벤트를 이용한다. 구체적으로 말하자면 이 예제는 트리거되는 세 개의 콜백 함수(마우스가 눌렸을 때, 마우스가 이동할 때, 마우스 버튼을 놓았을 때)에 의존한다. 이러한 종류의 전역 이벤트를 사용하는 것의 단점은 만약 여러분이 한꺼번에 여러 가지를 이어서 할 경우 상당히 곤란한 경우를 겪을 수도 있다는 것이다. 그러므로 여러분은 이러한 전역 이벤트를 사용하는 것을 최소화해야 하며 페이지당 기껏해야 하나 혹은 두 개만을 갖도록 해야 한다. 특히 이러한 예제의 경우 전역 이벤트는 상당히 필수적이다. 한 문단씩 살펴보기로 하자.
// 콜백을 지정
document.onmousedown = mousedown;
document.onmousemove = movemouse;
document.onmouseup   = mouseup;
var lastobj; // 마지막으로 마우스를 올려놓았던 드래그 가능한 객체
var isdrag; // 객체를 드래그 하고 있을 경우 True
다음 코드에서는 세 개의 콜백 함수들을 초기화한다. mousedown과 mousemove는 각각 사용자가 마우스 버튼을 클릭할 때와 이동할 때 호출될 것이며, mouseup은 왼쪽 마우스 버튼을 놓았을 때 트리거될 것이다. 또한 여기에서는 두 개의 전역 변수가 필요한데, 첫 번째 것은 가장 최근에 마우스를 올려놓았던 객체를 추적하기 위한 것이며, 두 번째는 현재 객체를 드래그하고 있을 경우 true를 값으로 가지는 플래그 변수이다.
// 다음 코드는 여러분이 텍스트를 클릭했을 때 
// 드래그할 수 있는 텍스트를 강조하지 않도록 한다.
// 테이블은 drag_drop이라는 id를 가진 모든 드래그 
// 가능한 텍스트를 포함한다.

window.onload = function()
{
    var e = document.getElementById('drag_drop');
    if (e) {
        if (moz)
            e.onmousedown = function () { return false; } // mozilla
        else
            e.onselectstart = function () { return false; } // ie
    }
}
페이지가 로딩되자마자 위 함수가 실행되는데, 드래그할 수 있는 객체에 대해 클릭할 경우 보통 우리가 텍스트를 클릭했을 때 일어나는 일처럼 텍스트를 강조하지 않도록 한다. 이는 일반적으로 텍스트를 강조하도록 요청되는 함수를 빈 함수로 재정의하여 강조하지 않도록 만들 수 있다.
// 객체의 id에 근거하여 두 객체간에 맞바꾸기가 허용되는지를 확인한다.
// 각각의 드래그할 수 있는 항목들의 짝에 대해 맞바꾸기를 허용하거나 금지하도록 하는
// 조건을 여러분이 원하는 대로 변경한다.
function allowswap(a,b)
{
    if (a.id == "dragdropa" && b.id == "dragdropb" || a.id == "dragdropb" && b.id 
    == "dragdropa")
        return true;
    return false;
}

// 객체가 드래그할 수 있는 것이면 true를 반환 - 필요에 맞게 변경하도록 한다.
function isdraggable(obj)
{
    if (obj.id.substr(0,8) == "dragdrop")
        return true;
    return false;
}
두 개의 유틸리티 함수도 필요한데, 주어진 두 객체에 대하여 allowswap함수는 두 객체가 서로 맞바꿀 수 있을 경우 true를 반환하며, 그렇지 않을 경우 false를 반환한다. 확실히 여기에 들어있는 조금 복잡한 로직을 이용하여 여러분은 꽤 재미있는 일을 할 수 있다. isdraggable함수는 주어진 객체가 드래그 가능할 경우true를 반환한다. 이 예제의 취지상 객체가 드래그할 수 있는지를 단순히 객체의 id가 dragdrop으로 시작하는지 근거하여 판단하고 있는데, 물론 여러분은 그렇지 하지 않을 수도 있으며, 여러분이 원하는 대로 변경할 수도 있다. 가령 특정 class로 드래그할 수 있음을 나타낼 수도 있는데, 이 예제의 취지상 위에서 했던 것만으로도 충분하다.
// 마우스 버튼이 놓였을 경우의 콜백. 이 함수는 항목이 드래그 할 수 있는지를 확인하고,
// 드래그 할 수 있으면 프로세스를 초기화한다.
function mousedown(e) 
{
    var obj = moz ? e.target : event.srcElement;
    // DOM 트리를 추적하여 클릭한 항목이 드래그 할 수 있는지를 확인한다.
    // 이렇게 하면 예를 들면 TD를 감싸고 있는 TR이 드래그 할 수 있는 객체일 경우에도
    // 여러분이 클릭할 수 있다.
    while (obj.tagName != "HTML" && obj.tagName != "BODY" && !isdraggable(obj)) {
        obj = moz ? obj.parentNode : obj.parentElement;
    }
    if (isdraggable(obj)) {
    // 만약 드래그 할 수 있으면 전역 플래그 변수를 설정하여 이 객체를 추적하도록 하고,
    // 또한 객체의 포인터를 전역 변수에 저장한다(dragobj).
        isdrag = true;
        dragobj = obj;

        // origx, origy는 드래그되는 객체의 원래 시작 위치임.
        origx = dragobj.style.left;
        origy = dragobj.style.top;

        // x,y는 window내의 절대 좌표
        x = moz ? e.clientX : event.clientX;
        y = moz ? e.clientY : event.clientY;

        // offsetX, offsetY는 여러분이 클릭한 객체가 정확히 어디에 있는지에 의존한다.
        // 따라서 여러분이 객체의 중앙을 클릭할 경우, 객체는 그 위치에서
        // 마우스에 '덧붙여지는데(attached)', 예를 들면 좌상단 모서리에 덧붙여지지는 않는다.
        offsetX = moz ? e.layerX + 2: event.x + 2;
        offsetY = moz ? e.layerY + 2: event.y + 2;
    }
}
마우스 버튼이 눌렸을 때 호출되는 mousedown 함수가 코드의 첫 번째 주요 부분이다. 무언가가 클릭되면 그것이 드래그 할 수 있는지를 확인한다. 만약 드래그 할 수 없다면 그것의 부모 노드 등이 드래그 할 수 있는지를 확인한다. 이렇게 하는 이유는 여러분이 무언가를 클릭했을 때 브라우저가 일반적으로 DOM 트리에서 가장 낮고 깊이가 깊은 항목의 핸들을 반환할 것이기 때문이다. 그렇기 때문에 예를 들어p 태그를 감싸고 있는 span 태그가 드래그 할 수 있는 것으로 표시되어 있을 경우, 그러한 태그 사이의 텍스트를 클릭했을 때 여러분은 드래그 할 수 있는 것으로 표시되어 있지는 않은 p 태그의 핸들을 가져오게 된다. 그러나 부모 노드를 확인하여 실제로 그 노드가 드래그 할 수 있는 항목의 자식인지를 확인하여 실제로는 드래그 할 수 있는지 여부를 알아낼 수 있다.

무언가 드래그 할 수 있는 것을 클릭했다고 가정하면 전역 플래그 변수를 true로 설정하고 그 객체를 dragobj에 저장한다. 또한 몇 가지 좌표도 저장하는데, 이러한 좌표에는 dragobj의 원래 위치, 클릭한 마우스의 상대 위치 및 클릭한 절대 위치가 포함된다.
// 마우스가 이동할 때의 콜백. 이 함수는 여러분이 맞바꿀 수 있거나 맞바꿀 수 없는 객체위에서
// 마우스를 움직일 때 커서를 변경할 것이다.
function movemouse(e)
{
    // 현재 객체를 드래그하고 있는지를 확인
    if (isdrag) {
        // 만약 현재 객체를 드래그하고 있다면 드래그되는 객체의 위치를 마우스가 처음 클릭한 이후로
        // 상대적으로 마우스가 움직인만큼 지정한다.
        dragobj.style.left = moz ? origx + e.clientX - x 
              + offsetX + 'px' : origx + event.clientX - x + offsetX;
        dragobj.style.top  = moz ? origy + e.clientY - y + offsetY 
              + 'px' : origy + event.clientY - y + offsetY;
        var obj = moz ? e.target : event.srcElement;
    
        // 지금 맞바꿀 수 없는 엘리먼트상에 있을 경우 커서 스타일을 
        // 맞바꿈이 금지되어 있음을 보여주는 것으로 변경한다.
        if (obj != dragobj && isdraggable(obj) && !allowswap(dragobj,obj)) {
            obj.style.cursor = 'wait';
            // 객체에 대한 핸들을 전역변수에 저장하여 커서를 나중에 초기화할 수 있도록 한다.
            lastobj = obj;
        }
        else if (lastobj)  // 드래그할 수 없는 객체의 이동이 끝나는대로 커서를 초기화한다.
            lastobj.style.cursor = 'pointer';
        return false;
    }
    else {
        // 간혹 드롭 아이콘으로 갇힐 수 있는데, 그러므로 드래그하고 있지는 않지만 드래그할 수 있는
        // 항목을 전달할 때 안전하게 하기 위해 커서를 복원한다.
        var obj = moz ? e.target : event.srcElement;
        if (isdraggable(obj))
            obj.style.cursor = 'pointer';
    }
}
마우스가 이동할 때마다 먼저 무언가가 드래그되고 있는지를 확인한다. 무언가가 드래그되고 있다면 그 객체가 어디로 드래그 되어야 하는지를 계산하여(아무튼 객체가 스스로 알아서 마우스를 따라다니는 것은 아니다!) 그에 맞게 객체를 이동시킨다. 또한 다른 드래그 할 수 있는 객체 위에 마우스를 올려놓았는지도 확인한다. 그럴 경우 allowswap 함수를 호출하여 맞바꾸기를 할 수 있는지를 결정한다. 맞바꾸기를 할 수 없다면 커서는 "대기(wait)" 모양으로 바꾼다(컴퓨터마다 모양이 다양하긴 하지만 표준 대기 커서이다). 객체를 서로 맞바꿀 수 있거나 드래그 할 수 있는 객체 위에 마우스를 올려놓지 않았다면 커서를 그대로 두고, 이전에 모양을 바꾸었다면 다시 모양을 복원한다.

한 가지 추가적으로 알아두어야 할 것은 드래그할 수 있는 객체 위에 마우스를 올려 놓더라도 현재 아무것도 드래그하고 있지 않으면 그대로 커서를 원래대로 복원한다는 것이다. 왜냐하면 사용자가 마우스를 얼마나 빨리 이동하고 버튼을 놓는 등의 동작을 하느냐에 따라 간혹 커서가 "대기" 상태에 갇힐 수 있기 때문이다. 그렇기 때문에 위에서 언급한 커서를 복원하는 로직은 failproof하지는 않다.
// 마우스 버튼을 놓았을 때의 콜백이며 맞바꾸기가 일어나야 하는지를 확인하며
// 맞바꾸기가 일어나지 말아야할 경우 드래그되는 개체를 원래 시작위치로 되돌려 보낸다.

function mouseup(e)
{
    if (isdrag) {  // 무언가가 드래그되고 있다면

        // 마우스 버튼이 놓여진 객체를 획득한다.
        var obj = moz ? e.target : event.srcElement;

        // 맞바꿀 수 있는 객체에 대해 마우스가 놓여졌는지를 확인한다.
        if (obj != dragobj && isdraggable(obj) && allowswap(dragobj, obj)) {

            // 맞바꾸기가 허용된 경우, 색상, 툴팁, 드래그 되는 객체의 내용을
            // 마우스가 놓여진 객체의 것들과 맞바꾼다.
            var htm = obj.innerHTML;
            obj.innerHTML = dragobj.innerHTML;
            dragobj.innerHTML = htm;

            var col = obj.style.color;
            obj.style.color = dragobj.style.color;
            dragobj.style.color = col;

            var titl = obj.title;
            obj.title = dragobj.title;
            dragobj.title = titl;

            // 현재 드래그하고 있는 객체(dragobj)의 위치를 다른 객체(obj)의 위치로 지정하고
            // obj를 dragobj가 드래그되기 전에 dragobj의 원래 위치(origx, origy)로 이동한다.
            dragobj.style.left = obj.style.left;
            dragobj.style.top = obj.style.top;
            obj.style.left = origx;
            obj.style.top = origy;
        }
        else {
            // 맞바꾸기가 일어나지 않으므로 드래그되는 객체를 원래의 시작 지점으로 돌려보낸다.
            dragobj.style.left = origx;
            dragobj.style.top = origy;
        }

        // 커서가 movemouse에서 바뀌었을 경우 커서를 포인터로 복원한다.
        if (lastobj) {
            lastobj.style.cursor = 'pointer';
        }
    }
    isdrag = false;  // 현재 아무것도 드래그되는 것이 없음
}
mouseup이벤트는 객체를 드래그하는 동안 마우스가 놓여졌는지에 관해 가장 상세한 조사를 벌인다. 드래그할 수 있는 객체를 놓을 경우 allowswap 함수를 이용하여 맞바꾸기가 가능한지를 확인한다. 바꾸기가 가능하다면 두 객체의 텍스트 내용, 색상, 그리고 툴팁(title 속성)을 서로 맞바꾼다. 이 시점에서 여러분은 여러분 목적에 맞게 단순히 객체의 모든 속성들을 맞바꾸길 선호할지도 모르겠다. 그리고 나서는 드래그되고 있는 객체를 마우스를 놓은 객체가 위치한 곳까지 이동시킨 후, 이번에는 마우스를 놓은 객체를 드래그되는 객체의 원래 시작지점으로 이동시킨다. 이리하여 맞바꾸기가 완료된다. 반면 맞바꾸기가 금지되어 있으면 단순히 드래그 되는 객체를 원래의 시작지점으로 돌려 보낸다. 두 경우 모두 마우스 커서가 movemouse 상태의 "대기" 커서로 변했을 경우 마우스 커서를 복원하고 더 이상 객체를 드래그하고 있지 않다는 것을 나타내기 위해 isdrag 플래그 변수를 초기화한다.

마지막으로 객체를 인스턴스화하는 것은 매우 쉽다. 드래그 할 수 있는 객체의id가 dragdrop으로 시작한다는 것만 기억하면 된다:
<table id="drag_drop" align="center" style="font-size:150%; color:green; 
    background-color:#88ccff; white-space: nowrap;">
  <tr>
    <td>
      <span id="dragdropa" style="cursor: pointer; position: 
      relative; color: #ff0000" title="John Doe">John</span>
    </td>
  </tr>
  <tr>
    <td>
      <span id="dragdropb" style="cursor: pointer; position: 
      relative; color: #a0522d" title="Jane Smith">Jane</span>
    </td>
  </tr>
  <tr>
    <td>
      <span id="dragdropc" style="cursor: pointer; position: 
      relative; color: #00aa00" title="Bill Schwartz">Bill</span>
    </td>
  </tr>
</table>

편의상 테이블에 객체가 위치해 있을 경우 각기 다른 색상을 띠도록 하였는데, 중요한 점은 드래그할 수 있는 항목의 id가 allowswap에서도 참조되며 style 속성이 position:relative라는 사실이다. 이 공식은 자바스크립트에서 객체들의 위치를 계산하여 상대적인 위치를 추정하는데 사용되었다. 또한 감싸고 있는 테이블의 id는 drag_drop인데, window.onload 함수의 맨 위에서 참조되고 있다는 것도 알아두도록 한다.

요약

대체로 앞서의 예제들은 웹 페이지의 일부를 나누거나 선택적으로 보이게끔 하는 데 있어 다소 창의적인 방식으로 div 태그가 사용될 수 있음을 보여주고 있다. 드래그 앤 드롭 예제는 요즘 볼 수 있는 대부부의 고급스런 웹 페이지에서 볼 수 있는 상당히 강력한 개념을 정말로 간단하게 보여주는 예제의 하나일 뿐이다. 거기에 조금만 더 작업을 하면 예를 들어 완전히 커스터마이즈가 가능한 홈 페이지를 만들어 여러분이 각종 뉴스 피드나 이미지, 그리고 핵심 컨텐츠들을 드래그 하고 서로 위치를 바꿀 수 있도록 할 수도 있다. 여러분의 상상력만이 유일한 제약사항일 뿐이다!


저자 Howard Feldman은 퀘벡주의 몬트리올에 위치한 Chemical Computing Group의 연구원이다.

 

 

제공: 한빛 네트워크
저자: Howard Feldman
역자: 이대엽
원문: Advanced JavaScript II

 

고급 자바스크립트 활용Ⅰ-Ⅰ

WEB2.0 | 2008. 4. 2. 18:01
Posted by 시반
웹 애플리케이션

컴퓨터 시대의 초창기때부터 서로 다른 플랫폼간의 소프트웨어 상호 운용성은 항상 관심의 대상이 되어 왔다. 가능한한 이용자층을 넓게 확대하기 위해, 업체들은 유명한 소프트웨어 프로그램을 하나의 장치에서 또 다른 장치로 옮겨왔고, 이것은 주로 몇개월이 걸리는 작업이거나, 가끔 새로운 하드웨어나 운영체제 상에서는 완전히 재작성 되기도 했다. 컴퓨터가 점점 더 강력해지고 C와 C++ 같은 언어들이 대부분의 플랫폼 상에서 사용가능한 표준이 되어감에 따라, 프로그램을 한번만 작성하여 원하는 만큼의 많은 시스템에서 사용할 수 있게 컴파일 하기가 더 쉬워졌다. C 컴파일러를 가지고 있기만 하면 소프트웨어를 빌드할수 있고 의도한대로 작동할 수 있다.

그러나, 그래픽 유저 인터페이스(GUI)를 가진 소프트웨어가 표준화 되면서 얘기가 달라졌다. Mac에서의 GUI는 윈도나 다양한 유닉스상의 그것과 틀려보였다. 물론 Tcl/Tk이나 wxWidgets같은 이른바 "위젯 툴킷"이라 불리는 것들은 C++, 파이썬, 펄과 같은 많은 유명한 언어들과 연결되어 윈도, 리눅스, 맥OS X, 그리고 기타 운영체제에서도 (거의) 똑같은 동작을 하는 플랫폼 독립적인 GUI를 만들수 있게 하기는 하다. 그러나 오늘날에는 거의 모든 장치에 매우 강력한 GUI 해석기가 존재한다. 바로 웹 브라우저다.

웹 브라우저는 처음에는 사용자들에게 단순히 마크업을 만족스러운 방법으로 보여주는데 유용했지만, 지금은 놀라울 정도로 복잡한 소프트웨어 인터페이스로서 실행될 수 있을 정도로 발전해왔고 C/C++과 다른 고수준 언어들로 쓰여진 소프트웨어들과도 견줄만 하다. 이것은 대체로 자바스크립트 지원과 웹 2.0기술 덕택이다. 모든 플랫폼상의 거의 모든 브라우저가 이 스크립트 언어의 일반적인 하위집합을 지원하며, 이전보다 플랫폼 독립적인 애플리케이션을 만들기가 더 쉬워졌다.

자바스크립트 툴킷

최근 몇몇 자바스크립트 툴킷이 야후, 구글, 도조와 같은 곳들에서 사용가능해졌다. 위에서 언급한 위젯 툴킷들과 매우 흡사하게, 이것들은 메뉴, 캘린더, 트리와 같은 다양한 위젯에 대한 자바스크립트 루틴을 제공하며, 웹사이트나 웹 애플리케이션에 쉽게 도입할 수 있게 허용한다. 여기 아주 조금만 요약해 보도록 한다.

툴킷은 웹페이지에 흥미로운 요소를 더하기 위해 좋고, 많은 이점을 가지고 있다. 이것들은 많은 브라우저 상에서 테스트 되었으며, 모든 일반적인 브라우저들에서 대부분 작동한다. 일부는 문서화가 잘 되어 있으며, 재밌는 웹페이지들을 순식간에 만들 수 있게 한다. 그러나, 이것들은 페이지 크기에 추가적인 몇백 킬로바이트를 더함으로써 불필요하게 거대해질수도 있고, 새로운 브라우저에 대한 지원이 추가되길 기다려야 할수도 있다. (예를 들어, 몇몇가지는 아직 IE7에서 작동하지 않는다.) 또한, 많은 회사들이 그것과 관련한 책임의 부족과 디버깅의 어려움 등을 이유로 오픈소스 소프트웨어를 사용할 수 없거나 사용하지 않을 것이다.

이 일련의 글들은 향상된 자바스크립트 테크닉을 사용한 튜토리얼 역할을 하기 위해 쓰여졌고, 이러한 툴킷들과 매우 비슷하게 여러 브라우저들과 호환되는 위젯을 만드는 법을 (완전한 소스를 가지고) 설명할 뿐만 아니라, 그것이 어떻게 작동하는지에 대해 자세히 설명하고 그럼으로써 여러분이 자신만의 것을 만들 수 있도록 할 것이다. 메뉴, 탭, 트리와 같은 것들을 구현하는 법에 대한 예제는 웹상에 많이 있다. 그러나 많은 것들이 극히 형편없게 작성되어 있거나 브라우저간 호환되지 않게 되어 있다. 자바스크립트, CSS, DOM, HTML에 대한 더 나은 온라인 레퍼런스 중의 하나가 www.w3schools.com이다. 만약 이 글상에서 친숙하지 않은 HTML/CSS 태그나 자바스크립트 함수를 본다면 이 사이트를 참조할 것을 권한다. HTML DOM에 대한 튜토리얼도 여기서 볼 수 있다. 앞으로 논의될 항목에는 팝업 메뉴, 플로팅 메시지, 드래그 & 드롭 객체, XML HTTP (페이지를 다시 로딩하지 않고 페이지 내용을 동적으로 바꿈) 등이 있다.

언급될 함수들은 윈도XP상의 IE7과 파이어폭스 2.0에서 테스트 되었지만 최근의 모든 브라우저에서 대부분 작동해야 함을 지적할 필요가 있다. 모든 브라우저 특화된 코드들은 본문 중에 특별히 짚어줄 것이다. 또한 자바스크립트와 DOM을 가지고 같은 목표를 달성하는 방법에는 여러가지가 있음을 명심하라. 다음 예제들은 그 중 한가지 방법을 제공하지만 모든 경우에 가장 빠르거나 가장 좋은 방법은 아닐 수 있다. 예제들은 단순성과 기능성을 가지고 읽기에 편안하게 작성되었다.

자바스크립트의 마법

다음에 보게 될 첫번째 예제는 브라우저 창이 스크롤 될 때에도 한 곳에 머물러 있는 떠있는 텍스트(혹은 이미지)를 만드는 법이다. 이것은 웹 애플리케이션에서 "잠시만 기다리세요"와 같은 메시지를 사용자에게 표시하거나 웹 페이지에 항상 표시되는 워터마크 등을 만드는데 사용할 수 있다. 이것은 자바스크립트 코드 몇 줄로 만들 수 있다:
<span id="testmsg" style="position: absolute; visibility: hidden; background: red;"
>This is a test?</span>

<form action="" method="get">
 <input name="submit" type="submit" value="Hide Message" onClick="Message_Display
('testmsg', 0, 700, 50); return false;" />
 <input name="submit" type="submit" value="Show Message" onClick="Message_Display
('testmsg', 1, 700, 50); return false;" />
</form>
이것은 다음 두개의 자바스크립트 함수로 만들 수 있다.
var ie = document.all;
var moz = document.getElementById && !document.all; 
var intr;

function Message_UpdatePos(msg, dy) {
    var el = document.getElementById(msg);
    if (ie) {
        el.style.pixelTop = document.body.scrollTop + dy;
    }
    else if (moz) {
        el.style.top = window.pageYOffset + dy + 'px';
    }
}

function Message_Display(msg, vis, dx, dy) {
    var el = document.getElementById(msg);

    // 메시지 위치

    if (ie) {
        el.style.pixelTop = document.body.scrollTop + dy;
        el.style.pixelLeft = document.body.clientWidth - dx;
    }
    else if (moz) {
        el.style.top = window.pageYOffset + dy + 'px';
        el.style.left = window.innerWidth - dx + 'px';
    }
    if (vis) {  // 표시하거나
        el.style.visibility = "visible";
        intr = setInterval("Message_UpdatePos('" + msg + "', " + dy + ")", 1);
    }
    else {  // 숨긴다
        el.style.visibility = "hidden";
        if (intr)
            clearInterval(intr);
    }
}
메시지 자체는 span 태그가 허용되는 페이지상의 모든 곳에서 인스턴스화 될 수 있다:
<span id="testmsg" style="position: absolute;
visibility: hidden; background: red;">This is a test…</span>
그러면 버튼은 단순히 다음과 같이 구현하여:
onclick="Message_Display('testmsg', 1, 700, 50); return false;"
메시지를 켜거나
onclick="Message_Display('testmsg', 0, 700, 50); return false;"
다시 끌 수 있다.

Message_Display에 전달하는 인수들은 메시지 텍스트를 가지는 span 태그의 id, 메시지를 보이게 할 것인지 안보이게 할 것인지를 가리키는 Boolean 값, 그리고 메시지가 위치해야할 브라우저 윈도의 우상단으로부터의 x, y 거리(이 경우에는 우측에서 700px, 상단에서 50px)이다. 여기에서의 키는 span 태그의 스타일이다. 절대 포지셔닝을 이용하여 메시지를 페이지의 나머지로부터 띄워서 표시하고 페이지의 나머지 흐름에 고정되지 않게 할 수 있다. 왜 span 태그가 사용되었는지도 알아두어야 한다. span 태그나 div 태그 둘 다 "아무것도 하지 않는" 태그들이며 문서상에서 각각 수평, 수직적으로 블록의 윤곽을 그리는데 사용한다. 이것들은 보통 문서에서 보이지 않는 효과를 가지고 있고, 그렇기 때문에 전체적인 외양을 변화시키지 않고도 특정한 스타일로 블록을 감싸는데 사용될 수 있다. 그러므로 이것들은 자바스크립트 위젯을 만들때 매우 간편하다.

이 함수는 다음과 같이 작동한다. 먼저 getElementById를 사용하여 메시지 span 태그에 대한 핸들을 얻어낸다. getElementById는 태그에 대한 포인터를 얻어내는 가장 쉬운 방법이다. 다음 단계는 인터넷 익스플로러 (ie)와 파이어폭스/모질라 (moz)에서 다르긴 하지만 둘 다 메시지를 원하는 위치(dx, dy)에 재위치 시키기 위한 같은 목적을 달성한다. 메시지는 visibility 스타일을 사용하여 켜거나 끌 수 있다. 마지막 라인은 자바스크립트 타이머에 대한 설명이 좀더 필요하다.

타이머는 자바스크립트에서 일정 시간 후에 함수를 실행시키는데 유용한 방법인데, setTimeout을 한번 사용하던지 setInterval을 반복적으로 사용할 수 있다. 이것들은 자바스크립트에서는 sleep 명령과 동일한 명령이 없기 때문에 특히나 유용하며 그렇기 때문에 이것들은 가장 좋은 대안을 제공한다. 이것들은 지정된 간격의 시간이 지날 때까지 어떠한 CPU 시간도 사용하지 않는다. 한가지 반드시 주의해야 할 것은 이 강력한 기능을 남용하지 말아야 하는 것인데, 적당히 사용한다면 일부 인상적인 효과를 달성할 수 있게 해준다. 이 경우에는 인자인 vis에 기초하여 Message_UpdatePos(msg, dy)를 실행시키는 타이머를 설정하며 타이머는 1ms 마다 실행된다. 전역 변수인 intr를 사용하여 타이머 포인터를 저장했음에 주의한다. 이것은 Message_Display를 몇번 호출하는 동안 유지하여야 하기 때문이다.

마지막으로 Message_UpdatePos를 보면 근본적으로 Message_Display의 처음 시작부분--메시지에 대한 핸들을 얻어내고 페이지의 상단으로부터 y 간격을 업데이트하는--과 같음에 주목하자. 그러므로 페이지가 스크롤될 때 메시지 위치는 스크롤 이벤트의 1ms 이내에 거기에 따라 재조정되고, 우상단 구석에서 항상 같은 위치에 떠있어 보인다. 메시지는 브라우저를 넓게 보거나 좁게 보기 위해 수평적으로 크기를 바꾸면 움직이지 않음에 주의한다. 연습삼아 이것이 잘 작동할 수 있게 코드를 수정해보자.
 
제공 : 한빛 네트워크
저자 : Howard Feldman
역자 : 추홍엽
원문 : Writing Advanced JavaScript
 

미디어 플레이어 Windows Media Player v11(WinXP) 한글판 다운로드

 

공개여부 : 공개

운영체제 : WinXP

 

다운받은 파일을 실행하면 다음과 같은 정품인증이 필요하다는 메시지가 뜨며 진행이 되지 않는다

(물론 윈도우즈 정품사용자들은 잘 진행이 되겠지만....-_-)

 

 

 

익스플로러 7도 그렇구 왜 이리 정품인증을 하라는 메시지가 뜨는건지..

여하튼 이렇게 정품인증을 하라는 메시지가 나오면 첨부한 reg파일을 실행하신후 다시 미디어플레이어를 실행하시면 아래와 같은 미디어 플레이어 화면이 접할 수 있을 것이다.

 

 

 

 
블로그 이미지

시반

시반(詩伴)이란 함께 시를 짓는 벗이란 뜻을 가지고 있습니다. 함께 나눌수 있는 그런 공간이길 바라며...

카테고리

분류 전체보기 (233)
개발 이야기 (73)
WEB2.0 (57)
DB2 (24)
MySQL (6)
오라클 (26)
기타 (44)
취미 (0)
잡담 (2)